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

Subversion Repositories rf68000

[/] [rf68000/] [trunk/] [software/] [examples/] [TinyBasic.asm] - Blame information for rev 4

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

Line No. Rev Author Line
1 2 robfinch
******************************************************************
2
*                                                                *
3
*               Tiny BASIC for the Motorola MC68000              *
4
*                                                                *
5
* Derived from Palo Alto Tiny BASIC as published in the May 1976 *
6
* issue of Dr. Dobb's Journal.  Adapted to the 68000 by:         *
7
*       Gordon Brandly                                           *
8
*       12147 - 51 Street                                        *
9
*       Edmonton AB  T5W 3G8                                     *
10
*       Canada                                                   *
11
*       (updated mailing address for 1996)                       *
12
*                                                                *
13
* This version is for MEX68KECB Educational Computer Board I/O.  *
14
*                                                                *
15
******************************************************************
16
*    Copyright (C) 1984 by Gordon Brandly. This program may be   *
17
*    freely distributed for personal use only. All commercial    *
18
*                      rights are reserved.                      *
19
******************************************************************
20
 
21
* Vers. 1.0  1984/7/17  - Original version by Gordon Brandly
22
*       1.1  1984/12/9  - Addition of '$' print term by Marvin Lipford
23
*       1.2  1985/4/9   - Bug fix in multiply routine by Rick Murray
24
 
25
*       OPT     FRS,BRS         forward ref.'s & branches default to short
26
 
27
;CR     EQU     $0D             ASCII equates
28
;LF     EQU     $0A
29
;TAB    EQU     $09
30
;CTRLC  EQU     $03
31
;CTRLH  EQU     $08
32
;CTRLS  EQU     $13
33
;CTRLX  EQU     $18
34
 
35
BUFLEN  EQU     80              length of keyboard input buffer
36
        CODE
37
*       ORG     $10000          first free address using Tutor
38
*
39
* Standard jump table. You can change these addresses if you are
40
* customizing this interpreter for a different environment.
41
*
42
START   BRA     CSTART          Cold Start entry point
43
GOWARM  BRA     WSTART          Warm Start entry point
44
GOOUT   BRA OUTC                Jump to character-out routine
45
GOIN    BRA INC         Jump to character-in routine
46
GOAUXO  BRA     AUXOUT          Jump to auxiliary-out routine
47
GOAUXI  BRA     AUXIN           Jump to auxiliary-in routine
48
GOBYE   BRA     BYEBYE          Jump to monitor, DOS, etc.
49
*
50
* Modifiable system constants:
51
*
52
TXTBGN  DC.L    $41000          beginning of program memory
53
ENDMEM  DC.L    $41FF0          end of available memory
54
*
55
* The main interpreter starts here:
56
*
57
CSTART  MOVE.L  ENDMEM,SP       initialize stack pointer
58
        move.l  #OUTC1,OUTPTR
59
        move.l  #INC1,INPPTR
60
        LEA     INITMSG,A6      tell who we are
61
        BSR     PRMESG
62
        MOVE.L  TXTBGN,TXTUNF   init. end-of-program pointer
63
        MOVE.L  ENDMEM,D0       get address of end of memory
64
        SUB.L   #2048,D0        reserve 2K for the stack
65
        MOVE.L  D0,STKLMT
66
        SUB.L   #108,D0         reserve variable area (27 long words)
67
        MOVE.L  D0,VARBGN
68
WSTART  CLR.L   D0              initialize internal variables
69
        MOVE.L  D0,LOPVAR
70
        MOVE.L  D0,STKGOS
71
        MOVE.L  D0,CURRNT       current line number pointer = 0
72
        MOVE.L  ENDMEM,SP       init S.P. again, just in case
73
        LEA     OKMSG,A6        display "OK"
74
        bsr     PRMESG
75
ST3     MOVE.B  #'>',D0         Prompt with a '>' and
76
        bsr     GETLN           read a line.
77
        bsr     TOUPBUF         convert to upper case
78
        MOVE.L  A0,A4           save pointer to end of line
79
        LEA     BUFFER,A0       point to the beginning of line
80
        bsr     TSTNUM          is there a number there?
81
        bsr     IGNBLK          skip trailing blanks
82
        TST     D1              does line no. exist? (or nonzero?)
83
        BEQ     DIRECT          if not, it's a direct statement
84
        CMP.L   #$FFFF,D1       see if line no. is <= 16 bits
85
        BCC     QHOW            if not, we've overflowed
86
        MOVE.B  D1,-(A0)        store the binary line no.
87
        ROR     #8,D1           (Kludge to store a word on a
88
        MOVE.B  D1,-(A0)        possible byte boundary)
89
        ROL     #8,D1
90
        bsr     FNDLN           find this line in save area
91
        MOVE.L  A1,A5           save possible line pointer
92
        BNE     ST4             if not found, insert
93
        bsr     FNDNXT          find the next line (into A1)
94
        MOVE.L  A5,A2           pointer to line to be deleted
95
        MOVE.L  TXTUNF,A3       points to top of save area
96
        bsr     MVUP            move up to delete
97
        MOVE.L  A2,TXTUNF       update the end pointer
98
ST4     MOVE.L  A4,D0           calculate the length of new line
99
        SUB.L   A0,D0
100
        CMP.L   #3,D0           is it just a line no. & CR?
101
        BEQ     ST3             if so, it was just a delete
102
        MOVE.L  TXTUNF,A3       compute new end
103
        MOVE.L  A3,A6
104
        ADD.L   D0,A3
105
        MOVE.L  VARBGN,D0       see if there's enough room
106
        CMP.L   A3,D0
107
        BLS     QSORRY          if not, say so
108
        MOVE.L  A3,TXTUNF       if so, store new end position
109
        MOVE.L  A6,A1           points to old unfilled area
110
        MOVE.L  A5,A2           points to beginning of move area
111
        bsr     MVDOWN          move things out of the way
112
        MOVE.L  A0,A1           set up to do the insertion
113
        MOVE.L  A5,A2
114
        MOVE.L  A4,A3
115
        bsr     MVUP            do it
116
        BRA     ST3             go back and get another line
117
 
118
*
119
*******************************************************************
120
*
121
* *** Tables *** DIRECT *** EXEC ***
122
*
123
* This section of the code tests a string against a table. When
124
* a match is found, control is transferred to the section of
125
* code according to the table.
126
*
127
* At 'EXEC', A0 should point to the string, A1 should point to
128
* the character table, and A2 should point to the execution
129
* table. At 'DIRECT', A0 should point to the string, A1 and
130
* A2 will be set up to point to TAB1 and TAB1_1, which are
131
* the tables of all direct and statement commands.
132
*
133
* A '.' in the string will terminate the test and the partial
134
* match will be considered as a match, e.g. 'P.', 'PR.','PRI.',
135
* 'PRIN.', or 'PRINT' will all match 'PRINT'.
136
*
137
* There are two tables: the character table and the execution
138
* table. The character table consists of any number of text items.
139
* Each item is a string of characters with the last character's
140
* high bit set to one. The execution table holds a 16-bit
141
* execution addresses that correspond to each entry in the
142
* character table.
143
*
144
* The end of the character table is a 0 byte which corresponds
145
* to the default routine in the execution table, which is
146
* executed if none of the other table items are matched.
147
*
148
* Character-matching tables:
149
TAB1
150
        DC.B    '
151
        DC.B    '
152
        DC.B    '>CO',('M'+$80)
153
        DC.B    '>CO',('N'+$80)
154
        DC.B    '<>CO',('M'+$80)
155
        DC.B    '<>CO',('N'+$80)
156
        DC.B    'LIS',('T'+$80)         Direct commands
157
        DC.B    'LOA',('D'+$80)
158
        DC.B    'NE',('W'+$80)
159
        DC.B    'RU',('N'+$80)
160
        DC.B    'SAV',('E'+$80)
161
TAB2    DC.B    'NEX',('T'+$80)         Direct / statement
162
        DC.B    'LE',('T'+$80)
163
        DC.B    'I',('F'+$80)
164
        DC.B    'GOT',('O'+$80)
165
        DC.B    'GOSU',('B'+$80)
166
        DC.B    'RETUR',('N'+$80)
167
        DC.B    'RE',('M'+$80)
168
        DC.B    'FO',('R'+$80)
169
        DC.B    'INPU',('T'+$80)
170
        DC.B    'PRIN',('T'+$80)
171
        DC.B    'POK',('E'+$80)
172
        DC.B    'STO',('P'+$80)
173
        DC.B    'BY',('E'+$80)
174
        DC.B    'CAL',('L'+$80)
175
        DC.B    0
176
TAB4    DC.B    'PEE',('K'+$80)         Functions
177
        DC.B    'RN',('D'+$80)
178
        DC.B    'AB',('S'+$80)
179
        DC.B    'SIZ',('E'+$80)
180
        DC.B    0
181
TAB5    DC.B    'T',('O'+$80)           "TO" in "FOR"
182
        DC.B    0
183
TAB6    DC.B    'STE',('P'+$80)         "STEP" in "FOR"
184
        DC.B    0
185
TAB8    DC.B    '>',('='+$80)           Relational operators
186
        DC.B    '<',('>'+$80)
187
        DC.B    ('>'+$80)
188
        DC.B    ('='+$80)
189
        DC.B    '<',('='+$80)
190
        DC.B    ('<'+$80)
191
        DC.B    0
192
        DC.B    0        <- for aligning on a word boundary
193
 
194
* Execution address tables:
195
TAB1_1
196
        DC.L    INCOM
197
        DC.L    INCON
198
        DC.L    OUTCOM
199
        DC.L    OUTCON
200
        DC.L    IOCOM
201
        DC.L    IOCON
202
        DC.L    LIST                    Direct commands
203
        DC.L    LOAD
204
        DC.L    NEW
205
        DC.L    RUN
206
        DC.L    SAVE
207
TAB2_1  DC.L    NEXT                    Direct / statement
208
        DC.L    LET
209
        DC.L    IF
210
        DC.L    GOTO
211
        DC.L    GOSUB
212
        DC.L    RETURN
213
        DC.L    REM
214
        DC.L    FOR
215
        DC.L    INPUT
216
        DC.L    PRINT
217
        DC.L    POKE
218
        DC.L    STOP
219
        DC.L    GOBYE
220
        DC.L    CALL
221
        DC.L    DEFLT
222
TAB4_1  DC.L    PEEK                    Functions
223
        DC.L    RND
224
        DC.L    ABS
225
        DC.L    SIZE
226
        DC.L    XP40
227
TAB5_1  DC.L    FR1                     "TO" in "FOR"
228
        DC.L    QWHAT
229
TAB6_1  DC.L    FR2                     "STEP" in "FOR"
230
        DC.L    FR3
231
TAB8_1  DC.L    XP11    >=              Relational operators
232
        DC.L    XP12    <>
233
        DC.L    XP13    >
234
        DC.L    XP15    =
235
        DC.L    XP14    <=
236
        DC.L    XP16    <
237
        DC.L    XP17
238
*
239
DIRECT  LEA     TAB1,A1
240
        LEA     TAB1_1,A2
241
EXEC    bsr     IGNBLK          ignore leading blanks
242
        MOVE.L  A0,A3           save the pointer
243
        CLR.B   D2              clear match flag
244
EXLP    MOVE.B  (A0)+,D0        get the program character
245
        MOVE.B  (A1),D1         get the table character
246
        BNE     EXNGO           If end of table,
247
        MOVE.L  A3,A0           restore the text pointer and...
248
        BRA     EXGO            execute the default.
249
EXNGO   MOVE.B  D0,D3           Else check for period...
250
        AND.B   D2,D3           and a match.
251
        CMP.B   #'.',D3
252
        BEQ     EXGO            if so, execute
253
        AND.B   #$7F,D1         ignore the table's high bit
254
        CMP.B   D0,D1           is there a match?
255
        BEQ     EXMAT
256
        ADDQ.L  #4,A2           if not, try the next entry
257
        MOVE.L  A3,A0           reset the program pointer
258
        CLR.B   D2              sorry, no match
259
EX1     TST.B   (A1)+           get to the end of the entry
260
        BPL     EX1
261
        BRA     EXLP            back for more matching
262
EXMAT   MOVEQ   #-1,D2          we've got a match so far
263
        TST.B   (A1)+           end of table entry?
264
        BPL     EXLP            if not, go back for more
265
EXGO    LEA     0,A3            execute the appropriate routine
266
        MOVE.L  (A2),A3
267
        JMP     (A3)
268
*
269
*******************************************************************
270
* Console redirection
271
* 
272
* >COM will redirect output to the COM port
273
* 
274
* >CON will redirect output to the console
275
* <>COM will redirect input and output to the COM port
276
* <>CON will redirect input and output to the console
277
*******************************************************************
278
INCON
279
        move.l  #INC1,INPPTR
280
        bra                     FINISH
281
INCOM
282
        move.l  #AUXIN,INPPTR
283
        bra                     FINISH
284
IOCOM
285
        move.l  #AUXIN,INPPTR
286
OUTCOM
287
        move.l  #AUXOUT,OUTPTR
288
        bra                     FINISH
289
IOCON
290
        move.l  #INC1,INPPTR
291
OUTCON
292
        move.l  #OUTC1,OUTPTR
293
        bra                     FINISH
294
 
295
*******************************************************************
296
*
297
* What follows is the code to execute direct and statement
298
* commands. Control is transferred to these points via the command
299
* table lookup code of 'DIRECT' and 'EXEC' in the last section.
300
* After the command is executed, control is transferred to other
301
* sections as follows:
302
*
303
* For 'LIST', 'NEW', and 'STOP': go back to the warm start point.
304
* For 'RUN': go execute the first stored line if any; else go
305
* back to the warm start point.
306
* For 'GOTO' and 'GOSUB': go execute the target line.
307
* For 'RETURN' and 'NEXT'; go back to saved return line.
308
* For all others: if 'CURRNT' is 0, go to warm start; else go
309
* execute next command. (This is done in 'FINISH'.)
310
*
311
*******************************************************************
312
*
313
* *** NEW *** STOP *** RUN (& friends) *** GOTO ***
314
*
315
* 'NEW' sets TXTUNF to point to TXTBGN
316
*
317
* 'STOP' goes back to WSTART
318
*
319
* 'RUN' finds the first stored line, stores its address
320
* in CURRNT, and starts executing it. Note that only those
321
* commands in TAB2 are legal for a stored program.
322
*
323
* There are 3 more entries in 'RUN':
324
* 'RUNNXL' finds next line, stores it's address and executes it.
325
* 'RUNTSL' stores the address of this line and executes it.
326
* 'RUNSML' continues the execution on same line.
327
*
328
* 'GOTO expr' evaluates the expression, finds the target
329
* line, and jumps to 'RUNTSL' to do it.
330
*
331
NEW     bsr     ENDCHK
332
        MOVE.L  TXTBGN,TXTUNF   set the end pointer
333
 
334
STOP    bsr     ENDCHK
335
        BRA     WSTART
336
 
337
RUN     bsr     ENDCHK
338
        MOVE.L  TXTBGN,A0       set pointer to beginning
339
        MOVE.L  A0,CURRNT
340
 
341
RUNNXL  TST.L   CURRNT          executing a program?
342
        beq     WSTART          if not, we've finished a direct stat.
343
        CLR.L   D1              else find the next line number
344
        MOVE.L  A0,A1
345
        bsr     FNDLNP
346
        BCS     WSTART          if we've fallen off the end, stop
347
 
348
RUNTSL  MOVE.L  A1,CURRNT       set CURRNT to point to the line no.
349
        MOVE.L  A1,A0           set the text pointer to
350
        ADDQ.L  #2,A0           the start of the line text
351
 
352
RUNSML  bsr     CHKIO           see if a control-C was pressed
353
        LEA     TAB2,A1         find command in TAB2
354
        LEA     TAB2_1,A2
355
        BRA     EXEC            and execute it
356
 
357
GOTO    bsr     EXPR            evaluate the following expression
358
        bsr     ENDCHK          must find end of line
359
        MOVE.L  D0,D1
360
        bsr     FNDLN           find the target line
361
        bne     QHOW            no such line no.
362
        BRA     RUNTSL          go do it
363
 
364
*
365
*******************************************************************
366
*
367
* *** LIST *** PRINT ***
368
*
369
* LIST has two forms:
370
* 'LIST' lists all saved lines
371
* 'LIST #' starts listing at the line #
372
* Control-S pauses the listing, control-C stops it.
373
*
374
* PRINT command is 'PRINT ....:' or 'PRINT ....'
375
* where '....' is a list of expressions, formats, back-arrows,
376
* and strings.  These items a separated by commas.
377
*
378
* A format is a pound sign followed by a number.  It controls
379
* the number of spaces the value of an expression is going to
380
* be printed in.  It stays effective for the rest of the print
381
* command unless changed by another format.  If no format is
382
* specified, 11 positions will be used.
383
*
384
* A string is quoted in a pair of single- or double-quotes.
385
*
386
* An underline (back-arrow) means generate a  without a 
387
*
388
* A  is generated after the entire list has been printed
389
* or if the list is empty.  If the list ends with a semicolon,
390
* however, no  is generated.
391
*
392
 
393
LIST    bsr     TSTNUM          see if there's a line no.
394
        bsr     ENDCHK          if not, we get a zero
395
        bsr     FNDLN           find this or next line
396
LS1     BCS     FINISH          warm start if we passed the end
397
        bsr     PRTLN           print the line
398
        bsr     CHKIO           check for listing halt request
399
        BEQ     LS3
400
        CMP.B   #CTRLS,D0       pause the listing?
401
        BNE     LS3
402
LS2     bsr     CHKIO           if so, wait for another keypress
403
        BEQ     LS2
404
LS3     bsr     FNDLNP          find the next line
405
        BRA     LS1
406
 
407
PRINT   MOVE    #11,D4          D4 = number of print spaces
408
        bsr     TSTC            if null list and ":"
409
        DC.B    ':',PR2-*
410
        bsr     CRLF            give CR-LF and continue
411
        BRA     RUNSML          execution on the same line
412
PR2     bsr     TSTC            if null list and 
413
        DC.B    CR,PR0-*
414
        bsr     CRLF            also give CR-LF and
415
        BRA     RUNNXL          execute the next line
416
PR0     bsr     TSTC            else is it a format?
417
        DC.B    '#',PR1-*
418
        bsr     EXPR            yes, evaluate expression
419
        MOVE    D0,D4           and save it as print width
420
        BRA     PR3             look for more to print
421
PR1     bsr     TSTC            is character expression? (MRL)
422
        DC.B    '$',PR4-*
423
        bsr     EXPR            yep. Evaluate expression (MRL)
424
        BSR     GOOUT           print low byte (MRL)
425
        BRA     PR3             look for more. (MRL)
426
PR4     bsr     QTSTG           is it a string?
427
        BRA.S   PR8             if not, must be an expression
428
PR3     bsr     TSTC            if ",", go find next
429
        DC.B    ',',PR6-*
430
        bsr     FIN             in the list.
431
        BRA     PR0
432
PR6     bsr     CRLF            list ends here
433
        BRA     FINISH
434
PR8     MOVE    D4,-(SP)        save the width value
435
        bsr     EXPR            evaluate the expression
436
        MOVE    (SP)+,D4        restore the width
437
        MOVE.L  D0,D1
438
        bsr     PRTNUM          print its value
439
        BRA     PR3             more to print?
440
 
441
FINISH  bsr     FIN             Check end of command
442
        BRA     QWHAT           print "What?" if wrong
443
 
444
*
445
*******************************************************************
446
*
447
* *** GOSUB *** & RETURN ***
448
*
449
* 'GOSUB expr:' or 'GOSUB expr' is like the 'GOTO' command,
450
* except that the current text pointer, stack pointer, etc. are
451
* saved so that execution can be continued after the subroutine
452
* 'RETURN's.  In order that 'GOSUB' can be nested (and even
453
* recursive), the save area must be stacked.  The stack pointer
454
* is saved in 'STKGOS'.  The old 'STKGOS' is saved on the stack.
455
* If we are in the main routine, 'STKGOS' is zero (this was done
456
* in the initialization section of the interpreter), but we still
457
* save it as a flag for no further 'RETURN's.
458
*
459
* 'RETURN' undoes everything that 'GOSUB' did, and thus
460
* returns the execution to the command after the most recent
461
* 'GOSUB'.  If 'STKGOS' is zero, it indicates that we never had
462
* a 'GOSUB' and is thus an error.
463
*
464
GOSUB   bsr     PUSHA           save the current 'FOR' parameters
465
        bsr     EXPR            get line number
466
        MOVE.L  A0,-(SP)        save text pointer
467
        MOVE.L  D0,D1
468
        bsr     FNDLN           find the target line
469
        BNE     AHOW            if not there, say "How?"
470
        MOVE.L  CURRNT,-(SP)    found it, save old 'CURRNT'...
471
        MOVE.L  STKGOS,-(SP)    and 'STKGOS'
472
        CLR.L   LOPVAR          load new values
473
        MOVE.L  SP,STKGOS
474
        BRA     RUNTSL
475
 
476
RETURN  bsr     ENDCHK          there should be just a 
477
        MOVE.L  STKGOS,D1       get old stack pointer
478
        BEQ     QWHAT           if zero, it doesn't exist
479
        MOVE.L  D1,SP           else restore it
480
        MOVE.L  (SP)+,STKGOS    and the old 'STKGOS'
481
        MOVE.L  (SP)+,CURRNT    and the old 'CURRNT'
482
        MOVE.L  (SP)+,A0        and the old text pointer
483
        bsr     POPA            and the old 'FOR' parameters
484
        BRA     FINISH          and we are back home
485
 
486
*
487
*******************************************************************
488
*
489
* *** FOR *** & NEXT ***
490
*
491
* 'FOR' has two forms:
492
* 'FOR var=exp1 TO exp2 STEP exp1' and 'FOR var=exp1 TO exp2'
493
* The second form means the same thing as the first form with a
494
* STEP of positive 1.  The interpreter will find the variable 'var'
495
* and set its value to the current value of 'exp1'.  It also
496
* evaluates 'exp2' and 'exp1' and saves all these together with
497
* the text pointer, etc. in the 'FOR' save area, which consisits of
498
* 'LOPVAR', 'LOPINC', 'LOPLMT', 'LOPLN', and 'LOPPT'.  If there is
499
* already something in the save area (indicated by a non-zero
500
* 'LOPVAR'), then the old save area is saved on the stack before
501
* the new values are stored.  The interpreter will then dig in the
502
* stack and find out if this same variable was used in another
503
* currently active 'FOR' loop.  If that is the case, then the old
504
* 'FOR' loop is deactivated. (i.e. purged from the stack)
505
*
506
* 'NEXT var' serves as the logical (not necessarily physical) end
507
* of the 'FOR' loop.  The control variable 'var' is checked with
508
* the 'LOPVAR'.  If they are not the same, the interpreter digs in
509
* the stack to find the right one and purges all those that didn't
510
* match.  Either way, it then adds the 'STEP' to that variable and
511
* checks the result with against the limit value.  If it is within
512
* the limit, control loops back to the command following the
513
* 'FOR'.  If it's outside the limit, the save area is purged and
514
* execution continues.
515
*
516
FOR     bsr     PUSHA           save the old 'FOR' save area
517
        bsr     SETVAL          set the control variable
518
        MOVE.L  A6,LOPVAR       save its address
519
        LEA     TAB5,A1         use 'EXEC' to test for 'TO'
520
        LEA     TAB5_1,A2
521
        BRA     EXEC
522
FR1     bsr     EXPR            evaluate the limit
523
        MOVE.L  D0,LOPLMT       save that
524
        LEA     TAB6,A1         use 'EXEC' to look for the
525
        LEA     TAB6_1,A2       word 'STEP'
526
        BRA     EXEC
527
FR2     bsr     EXPR            found it, get the step value
528
        BRA     FR4
529
FR3     MOVEQ   #1,D0           not found, step defaults to 1
530
FR4     MOVE.L  D0,LOPINC       save that too
531
FR5     MOVE.L  CURRNT,LOPLN    save address of current line number
532
        MOVE.L  A0,LOPPT        and text pointer
533
        MOVE.L  SP,A6           dig into the stack to find 'LOPVAR'
534
        BRA     FR7
535
FR6     ADD.L   #20,A6          look at next stack frame
536
FR7     MOVE.L  (A6),D0         is it zero?
537
        BEQ     FR8             if so, we're done
538
        CMP.L   LOPVAR,D0       same as current LOPVAR?
539
        BNE     FR6             nope, look some more
540
        MOVE.L  SP,A2           Else remove 5 long words from...
541
        MOVE.L  A6,A1           inside the stack.
542
        LEA     20,A3
543
        ADD.L   A1,A3
544
        bsr     MVDOWN
545
        MOVE.L  A3,SP           set the SP 5 long words up
546
FR8     BRA     FINISH          and continue execution
547
 
548
NEXT    bsr     TSTV            get address of variable
549
        BCS     QWHAT           if no variable, say "What?"
550
        MOVE.L  D0,A1           save variable's address
551
NX0     MOVE.L  LOPVAR,D0       If 'LOPVAR' is zero, we never...
552
        BEQ     QWHAT           had a FOR loop, so say "What?"
553
        CMP.L   D0,A1           else we check them
554
        BEQ     NX3             OK, they agree
555
        bsr     POPA            nope, let's see the next frame
556
        BRA     NX0
557
NX3     MOVE.L  (A1),D0         get control variable's value
558
        ADD.L   LOPINC,D0       add in loop increment
559
        BVS     QHOW            say "How?" for 32-bit overflow
560
        MOVE.L  D0,(A1)         save control variable's new value
561
        MOVE.L  LOPLMT,D1       get loop's limit value
562
        TST.L   LOPINC
563
        BPL     NX1             branch if loop increment is positive
564
        EXG     D0,D1
565
NX1     CMP.L   D0,D1           test against limit
566
        BLT     NX2             branch if outside limit
567
        MOVE.L  LOPLN,CURRNT    Within limit, go back to the...
568
        MOVE.L  LOPPT,A0        saved 'CURRNT' and text pointer.
569
        BRA     FINISH
570
NX2     bsr     POPA            purge this loop
571
        BRA     FINISH
572
 
573
*
574
*******************************************************************
575
*
576
* *** REM *** IF *** INPUT *** LET (& DEFLT) ***
577
*
578
* 'REM' can be followed by anything and is ignored by the
579
* interpreter.
580
*
581
* 'IF' is followed by an expression, as a condition and one or
582
* more commands (including other 'IF's) separated by colons.
583
* Note that the word 'THEN' is not used.  The interpreter evaluates
584
* the expression.  If it is non-zero, execution continues.  If it
585
* is zero, the commands that follow are ignored and execution
586
* continues on the next line.
587
*
588
* 'INPUT' is like the 'PRINT' command, and is followed by a list
589
* of items.  If the item is a string in single or double quotes,
590
* or is an underline (back arrow), it has the same effect as in
591
* 'PRINT'.  If an item is a variable, this variable name is
592
* printed out followed by a colon, then the interpreter waits for
593
* an expression to be typed in.  The variable is then set to the
594
* value of this expression.  If the variable is preceeded by a
595
* string (again in single or double quotes), the string will be
596
* displayed followed by a colon.  The interpreter the waits for an
597
* expression to be entered and sets the variable equal to the
598
* expression's value.  If the input expression is invalid, the
599
* interpreter will print "What?", "How?", or "Sorry" and reprint
600
* the prompt and redo the input.  The execution will not terminate
601
* unless you press control-C.  This is handled in 'INPERR'.
602
*
603
* 'LET' is followed by a list of items separated by commas.
604
* Each item consists of a variable, an equals sign, and an
605
* expression.  The interpreter evaluates the expression and sets
606
* the variable to that value.  The interpreter will also handle
607
* 'LET' commands without the word 'LET'.  This is done by 'DEFLT'.
608
*
609
REM     BRA     IF2             skip the rest of the line
610
 
611
IF      bsr     EXPR            evaluate the expression
612
IF1     TST.L   D0              is it zero?
613
        BNE     RUNSML          if not, continue
614
IF2     MOVE.L  A0,A1
615
        CLR.L   D1
616
        bsr     FNDSKP          if so, skip the rest of the line
617
        BCC     RUNTSL          and run the next line
618
        BRA     WSTART          if no next line, do a warm start
619
 
620
INPERR  MOVE.L  STKINP,SP       restore the old stack pointer
621
        MOVE.L  (SP)+,CURRNT    and old 'CURRNT'
622
        ADDQ.L  #4,SP
623
        MOVE.L  (SP)+,A0        and old text pointer
624
 
625
INPUT   MOVE.L  A0,-(SP)        save in case of error
626
        bsr     QTSTG           is next item a string?
627
        BRA.S   IP2             nope
628
        bsr     TSTV            yes, but is it followed by a variable?
629
        BCS     IP4             if not, branch
630
        MOVE.L  D0,A2           put away the variable's address
631
        BRA     IP3             if so, input to variable
632
IP2     MOVE.L  A0,-(SP)        save for 'PRTSTG'
633
        bsr     TSTV            must be a variable now
634
        BCS     QWHAT           "What?" it isn't?
635
        MOVE.L  D0,A2           put away the variable's address
636
        MOVE.B  (A0),D2         get ready for 'PRTSTG'
637
        CLR.B   D0
638
        MOVE.B  D0,(A0)
639
        MOVE.L  (SP)+,A1
640
        bsr     PRTSTG          print string as prompt
641
        MOVE.B  D2,(A0)         restore text
642
IP3     MOVE.L  A0,-(SP)        save in case of error
643
        MOVE.L  CURRNT,-(SP)    also save 'CURRNT'
644
        MOVE.L  #-1,CURRNT      flag that we are in INPUT
645
        MOVE.L  SP,STKINP       save the stack pointer too
646
        MOVE.L  A2,-(SP)        save the variable address
647
        MOVE.B  #':',D0         print a colon first
648
        bsr     GETLN           then get an input line
649
        LEA     BUFFER,A0       point to the buffer
650
        bsr     EXPR            evaluate the input
651
        MOVE.L  (SP)+,A2        restore the variable address
652
        MOVE.L  D0,(A2)         save value in variable
653
        MOVE.L  (SP)+,CURRNT    restore old 'CURRNT'
654
        MOVE.L  (SP)+,A0        and the old text pointer
655
IP4     ADDQ.L  #4,SP           clean up the stack
656
        bsr     TSTC            is the next thing a comma?
657
        DC.B    ',',IP5-*
658
        BRA     INPUT           yes, more items
659
IP5     BRA     FINISH
660
 
661
DEFLT   CMP.B   #CR,(A0)        empty line is OK
662
        BEQ     LT1             else it is 'LET'
663
 
664
LET     bsr     SETVAL          do the assignment
665
        bsr     TSTC            check for more 'LET' items
666
        DC.B    ',',LT1-*
667
        BRA     LET
668
LT1     BRA     FINISH          until we are finished.
669
 
670
*
671
*******************************************************************
672
*
673
* *** LOAD *** & SAVE ***
674
*
675
* These two commands transfer a program to/from an auxiliary
676
* device such as a cassette, another computer, etc.  The program
677
* is converted to an easily-stored format: each line starts with
678
* a colon, the line no. as 4 hex digits, and the rest of the line.
679
* At the end, a line starting with an '@' sign is sent.  This
680
* format can be read back with a minimum of processing time by
681
* the 68000.
682
*
683
LOAD    MOVE.L  TXTBGN,A0       set pointer to start of prog. area
684
        MOVE.B  #CR,D0          For a CP/M host, tell it we're ready...
685
        BSR     GOAUXO          by sending a CR to finish PIP command.
686
LOD1
687
        BSR     GOAUXI          look for start of line
688
        BEQ     LOD1
689
        CMP.B   #'@',D0         end of program?
690
        BEQ     LODEND
691
        CMP.B   #':',D0         if not, is it start of line?
692
        BNE     LOD1            if not, wait for it
693
        BSR     GBYTE           get first byte of line no.
694
        MOVE.B  D1,(A0)+        store it
695
        BSR     GBYTE           get 2nd bye of line no.
696
        MOVE.B  D1,(A0)+        store that, too
697
LOD2
698
        BSR     GOAUXI          get another text char.
699
        BEQ     LOD2
700
        MOVE.B  D0,(A0)+        store it
701
        CMP.B   #CR,D0          is it the end of the line?
702
        BNE     LOD2            if not, go back for more
703
        BRA     LOD1            if so, start a new line
704
LODEND
705
        MOVE.L  A0,TXTUNF       set end-of program pointer
706
        BRA     WSTART          back to direct mode
707
 
708
GBYTE
709
        MOVEQ   #1,D2           get two hex characters from auxiliary
710
        CLR.L   D1              and store them as a byte in D1
711
GBYTE1
712
        BSR     GOAUXI          get a char.
713
        BEQ     GBYTE1
714
        CMP.B   #'A',D0
715
        BCS     GBYTE2
716
        SUBQ.B  #7,D0           if greater than 9, adjust
717
GBYTE2
718
        AND.B   #$F,D0          strip ASCII
719
        LSL.B   #4,D1           put nybble into the result
720
        OR.B    D0,D1
721
        DBRA    D2,GBYTE1       get another char.
722
        RTS
723
 
724
SAVE
725
        MOVE.L  TXTBGN,A0       set pointer to start of prog. area
726
        MOVE.L  TXTUNF,A1       set pointer to end of prog. area
727
SAVE1
728
        MOVE.B  #CR,D0          send out a CR & LF (CP/M likes this)
729
        BSR     GOAUXO
730
        MOVE.B  #LF,D0
731
        BSR     GOAUXO
732
        CMP.L   A0,A1           are we finished?
733
        BLS     SAVEND
734
        MOVE.B  #':',D0         if not, start a line
735
        BSR     GOAUXO
736
        MOVE.B  (A0)+,D1        send first half of line no.
737
        BSR     PBYTE
738
        MOVE.B  (A0)+,D1        and send 2nd half
739
        BSR     PBYTE
740
SAVE2
741
        MOVE.B  (A0)+,D0        get a text char.
742
        CMP.B   #CR,D0          is it the end of the line?
743
        BEQ     SAVE1           if so, send CR & LF and start new line
744
        BSR     GOAUXO          send it out
745
        BRA     SAVE2           go back for more text
746
SAVEND
747
        MOVE.B  #'@',D0         send end-of-program indicator
748
        BSR     GOAUXO
749
        MOVE.B  #CR,D0          followed by a CR & LF
750
        BSR     GOAUXO
751
        MOVE.B  #LF,D0
752
        BSR     GOAUXO
753
        MOVE.B  #$1A,D0         and a control-Z to end the CP/M file
754
        BSR     GOAUXO
755
        BRA     WSTART          then go do a warm start
756
 
757
PBYTE   MOVEQ   #1,D2           send two hex characters from D1's low byte
758
PBYTE1  ROL.B   #4,D1           get the next nybble
759
        MOVE.B  D1,D0
760
        AND.B   #$F,D0          strip off garbage
761
        ADD.B   #'0',D0         make it into ASCII
762
        CMP.B   #'9',D0
763
        BLS     PBYTE2
764
        ADDQ.B  #7,D0           adjust if greater than 9
765
PBYTE2  BSR     GOAUXO          send it out
766
        DBRA    D2,PBYTE1       then send the next nybble
767
        RTS
768
 
769
*
770
*******************************************************************
771
*
772
* *** POKE *** & CALL ***
773
*
774
* 'POKE expr1,expr2' stores the byte from 'expr2' into the memory
775
* address specified by 'expr1'.
776
*
777
* 'CALL expr' jumps to the machine language subroutine whose
778
* starting address is specified by 'expr'.  The subroutine can use
779
* all registers but must leave the stack the way it found it.
780
* The subroutine returns to the interpreter by executing an RTS.
781
*
782
POKE    BSR     EXPR            get the memory address
783
        bsr     TSTC            it must be followed by a comma
784
        DC.B    ',',PKER-*
785
        MOVE.L  D0,-(SP)        save the address
786
        BSR     EXPR            get the byte to be POKE'd
787
        MOVE.L  (SP)+,A1        get the address back
788
        MOVE.B  D0,(A1)         store the byte in memory
789
        BRA     FINISH
790
PKER    BRA     QWHAT           if no comma, say "What?"
791
 
792
CALL    BSR     EXPR            get the subroutine's address
793
        TST.L   D0              make sure we got a valid address
794
        BEQ     QHOW            if not, say "How?"
795
        MOVE.L  A0,-(SP)        save the text pointer
796
        MOVE.L  D0,A1
797
        JSR     (A1)            jump to the subroutine
798
        MOVE.L  (SP)+,A0        restore the text pointer
799
        BRA     FINISH
800
*
801
*******************************************************************
802
*
803
* *** EXPR ***
804
*
805
* 'EXPR' evaluates arithmetical or logical expressions.
806
* ::=
807
*          
808
* where  is one of the operators in TAB8 and the result
809
* of these operations is 1 if true and 0 if false.
810
* ::=(+ or -)(+ or -)(...
811
* where () are optional and (... are optional repeats.
812
* ::=( <* or /> )(...
813
* ::=
814
*           
815
*           ()
816
*  is recursive so that the variable '@' can have an 
817
* as an index, functions can have an  as arguments, and
818
*  can be an  in parenthesis.
819
*
820
EXPR    BSR     EXPR2
821
        MOVE.L  D0,-(SP)        save  value
822
        LEA     TAB8,A1         look up a relational operator
823
        LEA     TAB8_1,A2
824
        BRA     EXEC            go do it
825
 
826
XP11    BSR     XP18            is it ">="?
827
        BLT     XPRT0           no, return D0=0
828
        BRA     XPRT1           else return D0=1
829
 
830
XP12    BSR     XP18            is it "<>"?
831
        BEQ     XPRT0           no, return D0=0
832
        BRA     XPRT1           else return D0=1
833
 
834
XP13    BSR     XP18            is it ">"?
835
        BLE     XPRT0           no, return D0=0
836
        BRA     XPRT1           else return D0=1
837
 
838
XP14    BSR     XP18            is it "<="?
839
        BGT     XPRT0           no, return D0=0
840
        BRA     XPRT1           else return D0=1
841
 
842
XP15    BSR     XP18            is it "="?
843
        BNE     XPRT0           if not, return D0=0
844
        BRA     XPRT1           else return D0=1
845
XP15RT  RTS
846
 
847
XP16    BSR     XP18            is it "<"?
848
        BGE     XPRT0           if not, return D0=0
849
        BRA     XPRT1           else return D0=1
850
XP16RT  RTS
851
 
852
XPRT0   CLR.L   D0              return D0=0 (false)
853
        RTS
854
 
855
XPRT1   MOVEQ   #1,D0           return D0=1 (true)
856
        RTS
857
 
858
XP17    MOVE.L  (SP)+,D0        it's not a rel. operator
859
        RTS                     return D0=
860
 
861
XP18    MOVE.L  (SP)+,D0        reverse the top two stack items
862
        MOVE.L  (SP)+,D1
863
        MOVE.L  D0,-(SP)
864
        MOVE.L  D1,-(SP)
865
        BSR     EXPR2           do second 
866
        MOVE.L  (SP)+,D1
867
        CMP.L   D0,D1           compare with the first result
868
        RTS                     return the result
869
 
870
EXPR2   bsr     TSTC            negative sign?
871
        DC.B    '-',XP21-*
872
        CLR.L   D0              yes, fake '0-'
873
        BRA     XP26
874
XP21    bsr     TSTC            positive sign? ignore it
875
        DC.B    '+',XP22-*
876
XP22    BSR     EXPR3           first 
877
XP23    bsr     TSTC            add?
878
        DC.B    '+',XP25-*
879
        MOVE.L  D0,-(SP)        yes, save the value
880
        BSR     EXPR3           get the second 
881
XP24    MOVE.L  (SP)+,D1
882
        ADD.L   D1,D0           add it to the first 
883
        BVS     QHOW            branch if there's an overflow
884
        BRA     XP23            else go back for more operations
885
XP25    bsr     TSTC            subtract?
886
        DC.B    '-',XP42-*
887
XP26    MOVE.L  D0,-(SP)        yes, save the result of 1st 
888
        BSR     EXPR3           get second 
889
        NEG.L   D0              change its sign
890
        JMP     XP24            and do an addition
891
 
892
EXPR3   BSR     EXPR4           get first 
893
XP31    bsr     TSTC            multiply?
894
        DC.B    '*',XP34-*
895
        MOVE.L  D0,-(SP)        yes, save that first result
896
        BSR     EXPR4           get second 
897
        MOVE.L  (SP)+,D1
898
        bsr     MULT32          multiply the two
899
        BRA     XP31            then look for more terms
900
XP34    bsr     TSTC            divide?
901
        DC.B    '/',XP42-*
902
        MOVE.L  D0,-(SP)        save result of 1st 
903
        BSR     EXPR4           get second 
904
        MOVE.L  (SP)+,D1
905
        EXG     D0,D1
906
        bsr     DIV32           do the division
907
        BRA     XP31            go back for any more terms
908
 
909
EXPR4   LEA     TAB4,A1         find possible function
910
        LEA     TAB4_1,A2
911
        BRA     EXEC
912
XP40    BSR     TSTV            nope, not a function
913
        BCS     XP41            nor a variable
914
        MOVE.L  D0,A1
915
        CLR.L   D0
916
        MOVE.L  (A1),D0         if a variable, return its value in D0
917
EXP4RT  RTS
918
XP41    bsr     TSTNUM          or is it a number?
919
        MOVE.L  D1,D0
920
        TST     D2              (if not, # of digits will be zero)
921
        BNE     EXP4RT          if so, return it in D0
922
PARN    bsr     TSTC            else look for ( EXPR )
923
        DC.B    '(',XP43-*
924
        BSR     EXPR
925
        bsr     TSTC
926
        DC.B    ')',XP43-*
927
XP42    RTS
928
XP43    BRA     QWHAT           else say "What?"
929
 
930
*
931
* ===== Test for a valid variable name.  Returns Carry=1 if not
932
*       found, else returns Carry=0 and the address of the
933
*       variable in D0.
934
 
935
TSTV    bsr     IGNBLK
936
        CLR.L   D0
937
        MOVE.B  (A0),D0         look at the program text
938
        SUB.B   #'@',D0
939
        BCS     TSTVRT          C=1: not a variable
940
        BNE     TV1             branch if not "@" array
941
        ADDQ    #1,A0           If it is, it should be
942
        BSR     PARN            followed by (EXPR) as its index.
943
        ADD.L   D0,D0
944
        BCS     QHOW            say "How?" if index is too big
945
        ADD.L   D0,D0
946
        BCS     QHOW
947
        MOVE.L  D0,-(SP)        save the index
948
        bsr     SIZE            get amount of free memory
949
        MOVE.L  (SP)+,D1        get back the index
950
        CMP.L   D1,D0           see if there's enough memory
951
        BLS     QSORRY          if not, say "Sorry"
952
        MOVE.L  VARBGN,D0       put address of array element...
953
        SUB.L   D1,D0           into D0
954
        RTS
955
TV1     CMP.B   #27,D0          if not @, is it A through Z?
956
        EOR     #1,CCR
957
        BCS     TSTVRT          if not, set Carry and return
958
        ADDQ    #1,A0           else bump the text pointer
959
        ADD     D0,D0           compute the variable's address
960
        ADD     D0,D0
961
        MOVE.L  VARBGN,D1
962
        ADD     D1,D0           and return it in D0 with Carry=0
963
TSTVRT  RTS
964
 
965
*
966
* ===== Multiplies the 32 bit values in D0 and D1, returning
967
*       the 32 bit result in D0.
968
*
969
MULT32  MOVE.L  D1,D4
970
        EOR.L   D0,D4           see if the signs are the same
971
        TST.L   D0              take absolute value of D0
972
        BPL     MLT1
973
        NEG.L   D0
974
MLT1    TST.L   D1              take absolute value of D1
975
        BPL     MLT2
976
        NEG.L   D1
977
MLT2    CMP.L   #$FFFF,D1       is second argument <= 16 bits?
978
        BLS     MLT3            OK, let it through
979
        EXG     D0,D1           else swap the two arguments
980
        CMP.L   #$FFFF,D1       and check 2nd argument again
981
        BHI     QHOW            one of them MUST be 16 bits
982
MLT3    MOVE    D0,D2           prepare for 32 bit X 16 bit multiply
983
        MULU    D1,D2           multiply low word
984
        SWAP    D0
985
        MULU    D1,D0           multiply high word
986
        SWAP    D0
987
*** Rick Murray's bug correction follows:
988
        TST     D0              if lower word not 0, then overflow
989
        BNE     QHOW            if overflow, say "How?"
990
        ADD.L   D2,D0           D0 now holds the product
991
        BMI     QHOW            if sign bit set, it's an overflow
992
        TST.L   D4              were the signs the same?
993
        BPL     MLTRET
994
        NEG.L   D0              if not, make the result negative
995
MLTRET  RTS
996
 
997
*
998
* ===== Divide the 32 bit value in D0 by the 32 bit value in D1.
999
*       Returns the 32 bit quotient in D0, remainder in D1.
1000
*
1001
DIV32   TST.L   D1              check for divide-by-zero
1002
        BEQ     QHOW            if so, say "How?"
1003
        MOVE.L  D1,D2
1004
        MOVE.L  D1,D4
1005
        EOR.L   D0,D4           see if the signs are the same
1006
        TST.L   D0              take absolute value of D0
1007
        BPL     DIV1
1008
        NEG.L   D0
1009
DIV1    TST.L   D1              take absolute value of D1
1010
        BPL     DIV2
1011
        NEG.L   D1
1012
DIV2    MOVEQ   #31,D3          iteration count for 32 bits
1013
        MOVE.L  D0,D1
1014
        CLR.L   D0
1015
DIV3    ADD.L   D1,D1           (This algorithm was translated from
1016
        ADDX.L  D0,D0           the divide routine in Ron Cain's
1017
        BEQ     DIV4            Small-C run time library.)
1018
        CMP.L   D2,D0
1019
        BMI     DIV4
1020
        ADDQ.L  #1,D1
1021
        SUB.L   D2,D0
1022
DIV4    DBRA    D3,DIV3
1023
        EXG     D0,D1           put rem. & quot. in proper registers
1024
        TST.L   D4              were the signs the same?
1025
        BPL     DIVRT
1026
        NEG.L   D0              if not, results are negative
1027
        NEG.L   D1
1028
DIVRT   RTS
1029
 
1030
*
1031
* ===== The PEEK function returns the byte stored at the address
1032
*       contained in the following expression.
1033
*
1034
PEEK    BSR     PARN            get the memory address
1035
        MOVE.L  D0,A1
1036
        CLR.L   D0              upper 3 bytes will be zero
1037
        MOVE.B  (A1),D0         get the addressed byte
1038
        RTS                     and return it
1039
 
1040
*
1041
* ===== The RND function returns a random number from 1 to
1042
*       the value of the following expression in D0.
1043
*
1044
RND     BSR     PARN            get the upper limit
1045
        TST.L   D0              it must be positive and non-zero
1046
        BEQ     QHOW
1047
        BMI     QHOW
1048
        MOVE.L  D0,D1
1049
        MOVE.L  RANPNT,A1       get memory as a random number
1050
        CMP.L   #LSTROM,A1
1051
        BCS     RA1
1052
        LEA     START,A1        wrap around if end of program
1053
RA1     MOVE.L  (A1)+,D0        get the slightly random number
1054
        BCLR    #31,D0          make sure it's positive
1055
        MOVE.L  A1,RANPNT       (even I can do better than this!)
1056
        BSR     DIV32           RND(n)=MOD(number,n)+1
1057
        MOVE.L  D1,D0           MOD is the remainder of the div.
1058
        ADDQ.L  #1,D0
1059
        RTS
1060
 
1061
*
1062
* ===== The ABS function returns an absolute value in D0.
1063
*
1064
ABS     BSR     PARN            get the following expr.'s value
1065
        TST.L   D0
1066
        BPL     ABSRT
1067
        NEG.L   D0              if negative, complement it
1068
        BMI     QHOW            if still negative, it was too big
1069
ABSRT   RTS
1070
 
1071
*
1072
* ===== The SIZE function returns the size of free memory in D0.
1073
*
1074
SIZE    MOVE.L  VARBGN,D0       get the number of free bytes...
1075
        SUB.L   TXTUNF,D0       between 'TXTUNF' and 'VARBGN'
1076
        RTS                     return the number in D0
1077
 
1078
*
1079
*******************************************************************
1080
*
1081
* *** SETVAL *** FIN *** ENDCHK *** ERROR (& friends) ***
1082
*
1083
* 'SETVAL' expects a variable, followed by an equal sign and then
1084
* an expression.  It evaluates the expression and sets the variable
1085
* to that value.
1086
*
1087
* 'FIN' checks the end of a command.  If it ended with ":",
1088
* execution continues.  If it ended with a CR, it finds the
1089
* the next line and continues from there.
1090
*
1091
* 'ENDCHK' checks if a command is ended with a CR. This is
1092
* required in certain commands, such as GOTO, RETURN, STOP, etc.
1093
*
1094
* 'ERROR' prints the string pointed to by A0. It then prints the
1095
* line pointed to by CURRNT with a "?" inserted at where the
1096
* old text pointer (should be on top of the stack) points to.
1097
* Execution of Tiny BASIC is stopped and a warm start is done.
1098
* If CURRNT is zero (indicating a direct command), the direct
1099
* command is not printed. If CURRNT is -1 (indicating
1100
* 'INPUT' command in progress), the input line is not printed
1101
* and execution is not terminated but continues at 'INPERR'.
1102
*
1103
* Related to 'ERROR' are the following:
1104
* 'QWHAT' saves text pointer on stack and gets "What?" message.
1105
* 'AWHAT' just gets the "What?" message and jumps to 'ERROR'.
1106
* 'QSORRY' and 'ASORRY' do the same kind of thing.
1107
* 'QHOW' and 'AHOW' also do this for "How?".
1108
*
1109
SETVAL  BSR     TSTV            variable name?
1110
        BCS     QWHAT           if not, say "What?"
1111
        MOVE.L  D0,-(SP)        save the variable's address
1112
        bsr     TSTC            get past the "=" sign
1113
        DC.B    '=',SV1-*
1114
        BSR     EXPR            evaluate the expression
1115
        MOVE.L  (SP)+,A6
1116
        MOVE.L  D0,(A6)         and save its value in the variable
1117
        RTS
1118
SV1     BRA     QWHAT           if no "=" sign
1119
 
1120
FIN     bsr     TSTC            *** FIN ***
1121
        DC.B    ':',FI1-*
1122
        ADDQ.L  #4,SP           if ":", discard return address
1123
        BRA     RUNSML          continue on the same line
1124
FI1     bsr     TSTC            not ":", is it a CR?
1125
        DC.B    CR,FI2-*
1126
        ADDQ.L  #4,SP           yes, purge return address
1127
        BRA     RUNNXL          execute the next line
1128
FI2     RTS                     else return to the caller
1129
 
1130
ENDCHK  bsr     IGNBLK
1131
        CMP.B #':',(a0)
1132
        BEQ ENDCHK1
1133
        CMP.B   #CR,(A0)        does it end with a CR?
1134
        BNE     QWHAT           if not, say "WHAT?"
1135
ENDCHK1:
1136
        RTS
1137
 
1138
QWHAT   MOVE.L  A0,-(SP)
1139
AWHAT   LEA     WHTMSG,A6
1140
ERROR   bsr     PRMESG          display the error message
1141
        MOVE.L  (SP)+,A0        restore the text pointer
1142
        MOVE.L  CURRNT,D0       get the current line number
1143
        BEQ     WSTART          if zero, do a warm start
1144
        CMP.L   #-1,D0          is the line no. pointer = -1?
1145
        BEQ     INPERR          if so, redo input
1146
        MOVE.B  (A0),-(SP)      save the char. pointed to
1147
        CLR.B   (A0)            put a zero where the error is
1148
        MOVE.L  CURRNT,A1       point to start of current line
1149
        bsr     PRTLN           display the line in error up to the 0
1150
        MOVE.B  (SP)+,(A0)      restore the character
1151
        MOVE.B  #'?',D0         display a "?"
1152
        BSR     GOOUT
1153
        CLR     D0
1154
        SUBQ.L  #1,A1           point back to the error char.
1155
        bsr     PRTSTG          display the rest of the line
1156
        BRA     WSTART          and do a warm start
1157
QSORRY  MOVE.L  A0,-(SP)
1158
ASORRY  LEA     SRYMSG,A6
1159
        BRA     ERROR
1160
QHOW    MOVE.L  A0,-(SP)        Error: "How?"
1161
AHOW    LEA     HOWMSG,A6
1162
        BRA     ERROR
1163
*
1164
*******************************************************************
1165
*
1166
* *** GETLN *** FNDLN (& friends) ***
1167
*
1168
* 'GETLN' reads in input line into 'BUFFER'. It first prompts with
1169
* the character in D0 (given by the caller), then it fills the
1170
* buffer and echos. It ignores LF's but still echos
1171
* them back. Control-H is used to delete the last character
1172
* entered (if there is one), and control-X is used to delete the
1173
* whole line and start over again. CR signals the end of a line,
1174
* and causes 'GETLN' to return.
1175
*
1176
* 'FNDLN' finds a line with a given line no. (in D1) in the
1177
* text save area.  A1 is used as the text pointer. If the line
1178
* is found, A1 will point to the beginning of that line
1179
* (i.e. the high byte of the line no.), and flags are NC & Z.
1180
* If that line is not there and a line with a higher line no.
1181
* is found, A1 points there and flags are NC & NZ. If we reached
1182
* the end of the text save area and cannot find the line, flags
1183
* are C & NZ.
1184
* 'FNDLN' will initialize A1 to the beginning of the text save
1185
* area to start the search. Some other entries of this routine
1186
* will not initialize A1 and do the search.
1187
* 'FNDLNP' will start with A1 and search for the line no.
1188
* 'FNDNXT' will bump A1 by 2, find a CR and then start search.
1189
* 'FNDSKP' uses A1 to find a CR, and then starts the search.
1190
*
1191
GETLN   BSR     GOOUT           display the prompt
1192
        MOVE.B  #' ',D0         and a space
1193
        BSR     GOOUT
1194
        LEA     BUFFER,A0       A0 is the buffer pointer
1195
GL1     bsr     CHKIO           check keyboard
1196
        BEQ     GL1             wait for a char. to come in
1197
        CMP.B   #CTRLH,D0       delete last character?
1198
        BEQ     GL3             if so
1199
        CMP.B   #CTRLX,D0       delete the whole line?
1200
        BEQ     GL4             if so
1201
        CMP.B   #CR,D0          accept a CR
1202
        BEQ     GL2
1203
        CMP.B   #' ',D0         if other control char., discard it
1204
        BCS     GL1
1205
GL2     MOVE.B  D0,(A0)+        save the char.
1206
        BSR     GOOUT           echo the char back out
1207
        CMP.B   #CR,D0          if it's a CR, end the line
1208
        BEQ     GL7
1209
        CMP.L   #(BUFFER+BUFLEN-1),A0   any more room?
1210
        BCS     GL1             yes: get some more, else delete last char.
1211
GL3     MOVE.B  #CTRLH,D0       delete a char. if possible
1212
        BSR     GOOUT
1213
        MOVE.B  #' ',D0
1214
        BSR     GOOUT
1215
        CMP.L   #BUFFER,A0      any char.'s left?
1216
        BLS     GL1             if not
1217
        MOVE.B  #CTRLH,D0       if so, finish the BS-space-BS sequence
1218
        BSR     GOOUT
1219
        SUBQ.L  #1,A0           decrement the text pointer
1220
        BRA     GL1             back for more
1221
GL4     MOVE.L  A0,D1           delete the whole line
1222
        SUB.L   #BUFFER,D1      figure out how many backspaces we need
1223
        BEQ     GL6             if none needed, branch
1224
        SUBQ    #1,D1           adjust for DBRA
1225
GL5     MOVE.B  #CTRLH,D0       and display BS-space-BS sequences
1226
        BSR     GOOUT
1227
        MOVE.B  #' ',D0
1228
        BSR     GOOUT
1229
        MOVE.B  #CTRLH,D0
1230
        BSR     GOOUT
1231
        DBRA    D1,GL5
1232
GL6     LEA     BUFFER,A0       reinitialize the text pointer
1233
        BRA     GL1             and go back for more
1234
GL7     MOVE.B  #LF,D0          echo a LF for the CR
1235
        BRA     GOOUT
1236
 
1237
FNDLN   CMP.L   #$FFFF,D1       line no. must be < 65535
1238
        BCC     QHOW
1239
        MOVE.L  TXTBGN,A1       init. the text save pointer
1240
 
1241
FNDLNP  MOVE.L  TXTUNF,A2       check if we passed the end
1242
        SUBQ.L  #1,A2
1243
        CMP.L   A1,A2
1244
        BCS     FNDRET          if so, return with Z=0 & C=1
1245
        MOVE.B  (A1),D2 if not, get a line no.
1246
        LSL     #8,D2
1247
        MOVE.B  1(A1),D2
1248
        CMP.W   D1,D2           is this the line we want?
1249
        BCS     FNDNXT          no, not there yet
1250
FNDRET  RTS                     return the cond. codes
1251
 
1252
FNDNXT  ADDQ.L  #2,A1           find the next line
1253
 
1254
FNDSKP
1255
        CMP.B   #CR,(A1)+       try to find a CR
1256
        BEQ             FNDLNP
1257
        CMP.L   TXTUNF,A1
1258
        BLO             FNDSKP
1259
        BRA             FNDLNP          check if end of text
1260
 
1261
*
1262
*******************************************************************
1263
*
1264
* *** MVUP *** MVDOWN *** POPA *** PUSHA ***
1265
*
1266
* 'MVUP' moves a block up from where A1 points to where A2 points
1267
* until A1=A3
1268
*
1269
* 'MVDOWN' moves a block down from where A1 points to where A3
1270
* points until A1=A2
1271
*
1272
* 'POPA' restores the 'FOR' loop variable save area from the stack
1273
*
1274
* 'PUSHA' stacks for 'FOR' loop variable save area onto the stack
1275
*
1276
MVUP    CMP.L   A1,A3           see the above description
1277
        BEQ     MVRET
1278
        MOVE.B  (A1)+,(A2)+
1279
        BRA     MVUP
1280
MVRET   RTS
1281
 
1282
MVDOWN  CMP.L   A1,A2           see the above description
1283
        BEQ     MVRET
1284
        MOVE.B  -(A1),-(A3)
1285
        BRA     MVDOWN
1286
 
1287
POPA    MOVE.L  (SP)+,A6        A6 = return address
1288
        MOVE.L  (SP)+,LOPVAR    restore LOPVAR, but zero means no more
1289
        BEQ     PP1
1290
        MOVE.L  (SP)+,LOPINC    if not zero, restore the rest
1291
        MOVE.L  (SP)+,LOPLMT
1292
        MOVE.L  (SP)+,LOPLN
1293
        MOVE.L  (SP)+,LOPPT
1294
PP1     JMP     (A6)            return
1295
 
1296
PUSHA   MOVE.L  STKLMT,D1       Are we running out of stack room?
1297
        SUB.L   SP,D1
1298
        BCC     QSORRY          if so, say we're sorry
1299
        MOVE.L  (SP)+,A6        else get the return address
1300
        MOVE.L  LOPVAR,D1       save loop variables
1301
        BEQ     PU1             if LOPVAR is zero, that's all
1302
        MOVE.L  LOPPT,-(SP)     else save all the others
1303
        MOVE.L  LOPLN,-(SP)
1304
        MOVE.L  LOPLMT,-(SP)
1305
        MOVE.L  LOPINC,-(SP)
1306
PU1     MOVE.L  D1,-(SP)
1307
        JMP     (A6)            return
1308
 
1309
*
1310
*******************************************************************
1311
*
1312
* *** PRTSTG *** QTSTG *** PRTNUM *** PRTLN ***
1313
*
1314
* 'PRTSTG' prints a string pointed to by A1. It stops printing
1315
* and returns to the caller when either a CR is printed or when
1316
* the next byte is the same as what was passed in D0 by the
1317
* caller.
1318
*
1319
* 'QTSTG' looks for an underline (back-arrow on some systems),
1320
* single-quote, or double-quote.  If none of these are found, returns
1321
* to the caller.  If underline, outputs a CR without a LF.  If single
1322
* or double quote, prints the quoted string and demands a matching
1323
* end quote.  After the printing, the next 2 bytes of the caller are
1324
* skipped over (usually a short branch instruction).
1325
*
1326
* 'PRTNUM' prints the 32 bit number in D1, leading blanks are added if
1327
* needed to pad the number of spaces to the number in D4.
1328
* However, if the number of digits is larger than the no. in
1329
* D4, all digits are printed anyway. Negative sign is also
1330
* printed and counted in, positive sign is not.
1331
*
1332
* 'PRTLN' prints the saved text line pointed to by A1
1333
* with line no. and all.
1334
*
1335
PRTSTG  MOVE.B  D0,D1           save the stop character
1336
PS1     MOVE.B  (A1)+,D0        get a text character
1337
        CMP.B   D0,D1           same as stop character?
1338
        BEQ     PRTRET          if so, return
1339
        BSR     GOOUT           display the char.
1340
        CMP.B   #CR,D0          is it a C.R.?
1341
        BNE     PS1             no, go back for more
1342
        MOVE.B  #LF,D0          yes, add a L.F.
1343
        BSR     GOOUT
1344
PRTRET  RTS                     then return
1345
 
1346
QTSTG   bsr     TSTC            *** QTSTG ***
1347
        DC.B    '"',QT3-*
1348
        MOVE.B  #'"',D0         it is a "
1349
QT1     MOVE.L  A0,A1
1350
        BSR     PRTSTG          print until another
1351
        MOVE.L  A1,A0
1352
        MOVE.L  (SP)+,A1        pop return address
1353
        CMP.B   #LF,D0          was last one a CR?
1354
        BEQ     RUNNXL          if so, run next line
1355
QT2     ADDQ.L  #2,A1           skip 2 bytes on return
1356
        JMP     (A1)            return
1357
QT3     bsr     TSTC            is it a single quote?
1358
        DC.B    '''',QT4-*
1359
        MOVE.B  #'''',D0        if so, do same as above
1360
        BRA     QT1
1361
QT4     bsr     TSTC            is it an underline?
1362
        DC.B    '_',QT5-*
1363
        MOVE.B  #CR,D0          if so, output a CR without LF
1364
        bsr     GOOUT
1365
        MOVE.L  (SP)+,A1        pop return address
1366
        BRA     QT2
1367
QT5     RTS                     none of the above
1368
 
1369
PRTNUM  MOVE.L  D1,D3           save the number for later
1370
        MOVE    D4,-(SP)        save the width value
1371
        MOVE.B  #$FF,-(SP)      flag for end of digit string
1372
        TST.L   D1              is it negative?
1373
        BPL     PN1             if not
1374
        NEG.L   D1              else make it positive
1375
        SUBQ    #1,D4           one less for width count
1376
PN1     DIVU    #10,D1          get the next digit
1377
        BVS     PNOV            overflow flag set?
1378
        MOVE.L  D1,D0           if not, save remainder
1379
        AND.L   #$FFFF,D1       strip the remainder
1380
        BRA     TOASCII         skip the overflow stuff
1381
PNOV    MOVE    D1,D0           prepare for long word division
1382
        CLR.W   D1              zero out low word
1383
        SWAP    D1              high word into low
1384
        DIVU    #10,D1          divide high word
1385
        MOVE    D1,D2           save quotient
1386
        MOVE    D0,D1           low word into low
1387
        DIVU    #10,D1          divide low word
1388
        MOVE.L  D1,D0           D0 = remainder
1389
        SWAP    D1              R/Q becomes Q/R
1390
        MOVE    D2,D1           D1 is low/high
1391
        SWAP    D1              D1 is finally high/low
1392
TOASCII SWAP    D0              get remainder
1393
        MOVE.B  D0,-(SP)        stack it as a digit
1394
        SWAP    D0
1395
        SUBQ    #1,D4           decrement width count
1396
        TST.L   D1              if quotient is zero, we're done
1397
        BNE     PN1
1398
        SUBQ    #1,D4           adjust padding count for DBRA
1399
        BMI     PN4             skip padding if not needed
1400
PN3     MOVE.B  #' ',D0         display the required leading spaces
1401
        BSR     GOOUT
1402
        DBRA    D4,PN3
1403
PN4     TST.L   D3              is number negative?
1404
        BPL     PN5
1405
        MOVE.B  #'-',D0         if so, display the sign
1406
        BSR     GOOUT
1407
PN5     MOVE.B  (SP)+,D0        now unstack the digits and display
1408
        BMI     PNRET           until the flag code is reached
1409
        ADD.B   #'0',D0         make into ASCII
1410
        BSR     GOOUT
1411
        BRA     PN5
1412
PNRET   MOVE    (SP)+,D4        restore width value
1413
        RTS
1414
 
1415
PRTLN   CLR.L   D1
1416
        MOVE.B  (A1)+,D1        get the binary line number
1417
        LSL     #8,D1
1418
        MOVE.B  (A1)+,D1
1419
        MOVEQ   #5,D4           display a 5 digit line no.
1420
        BSR     PRTNUM
1421
        MOVE.B  #' ',D0         followed by a blank
1422
        BSR     GOOUT
1423
        CLR     D0              stop char. is a zero
1424
        BRA     PRTSTG          display the rest of the line
1425
 
1426
*
1427
* ===== Test text byte following the call to this subroutine. If it
1428
*       equals the byte pointed to by A0, return to the code following
1429
*       the call. If they are not equal, branch to the point
1430
*       indicated by the offset byte following the text byte.
1431
*
1432
TSTC    BSR     IGNBLK          ignore leading blanks
1433
        MOVE.L  (SP)+,A1        get the return address
1434
        MOVE.B  (A1)+,D1        get the byte to compare
1435
        CMP.B   (A0),D1         is it = to what A0 points to?
1436
        BEQ     TC1             if so
1437
        CLR.L   D1              If not, add the second
1438
        MOVE.B  (A1),D1         byte following the call to
1439
        ADD.L   D1,A1           the return address.
1440
        JMP     (A1)            jump to the routine
1441
TC1     ADDQ.L  #1,A0           if equal, bump text pointer
1442
        ADDQ.L  #1,A1           Skip the 2 bytes following
1443
        JMP     (A1)            the call and continue.
1444
 
1445
*
1446
* ===== See if the text pointed to by A0 is a number. If so,
1447
*       return the number in D1 and the number of digits in D2,
1448
*       else return zero in D1 and D2.
1449
*
1450
TSTNUM  CLR.L   D1              initialize return parameters
1451
        CLR     D2
1452
        BSR     IGNBLK          skip over blanks
1453
TN1     CMP.B   #'0',(A0)       is it less than zero?
1454
        BCS     TSNMRET         if so, that's all
1455
        CMP.B   #'9',(A0)       is it greater than nine?
1456
        BHI     TSNMRET         if so, return
1457
        CMP.L   #214748364,D1   see if there's room for new digit
1458
        BCC     QHOW            if not, we've overflowd
1459
        MOVE.L  D1,D0           quickly multiply result by 10
1460
        ADD.L   D1,D1
1461
        ADD.L   D1,D1
1462
        ADD.L   D0,D1
1463
        ADD.L   D1,D1
1464
        MOVE.B  (A0)+,D0        add in the new digit
1465
        AND.L   #$F,D0
1466
        ADD.L   D0,D1
1467
        ADDQ    #1,D2           increment the no. of digits
1468
        BRA     TN1
1469
TSNMRET RTS
1470
 
1471
*
1472
* ===== Skip over blanks in the text pointed to by A0.
1473
*
1474
IGNBLK  CMP.B   #' ',(A0)       see if it's a space
1475
        BNE     IGBRET          if so, swallow it
1476
IGB1    ADDQ.L  #1,A0           increment the text pointer
1477
        BRA     IGNBLK
1478
IGBRET  RTS
1479
 
1480
*
1481
* ===== Convert the line of text in the input buffer to upper
1482
*       case (except for stuff between quotes).
1483
*
1484
TOUPBUF LEA     BUFFER,A0       set up text pointer
1485
        CLR.B   D1              clear quote flag
1486
TOUPB1
1487
        MOVE.B  (A0)+,D0        get the next text char.
1488
        CMP.B   #CR,D0          is it end of line?
1489
        BEQ     TOUPBRT         if so, return
1490
        CMP.B   #'"',D0         a double quote?
1491
        BEQ     DOQUO
1492
        CMP.B   #'''',D0        or a single quote?
1493
        BEQ     DOQUO
1494
        TST.B   D1              inside quotes?
1495
        BNE     TOUPB1          if so, do the next one
1496
        BSR     TOUPPER         convert to upper case
1497
        MOVE.B  D0,-(A0)        store it
1498
        ADDQ.L  #1,A0
1499
        BRA     TOUPB1          and go back for more
1500
TOUPBRT
1501
        RTS
1502
 
1503
DOQUO   TST.B   D1              are we inside quotes?
1504
        BNE     DOQUO1
1505
        MOVE.B  D0,D1           if not, toggle inside-quotes flag
1506
        BRA     TOUPB1
1507
DOQUO1  CMP.B   D0,D1           make sure we're ending proper quote
1508
        BNE     TOUPB1          if not, ignore it
1509
        CLR.B   D1              else clear quote flag
1510
        BRA     TOUPB1
1511
 
1512
*
1513
* ===== Convert the character in D0 to upper case
1514
*
1515
TOUPPER CMP.B   #'a',D0         is it < 'a'?
1516
        BCS     TOUPRET
1517
        CMP.B   #'z',D0         or > 'z'?
1518
        BHI     TOUPRET
1519
        SUB.B   #32,D0          if not, make it upper case
1520
TOUPRET RTS
1521
 
1522
*
1523
* 'CHKIO' checks the input. If there's no input, it will return
1524
* to the caller with the Z flag set. If there is input, the Z
1525
* flag is cleared and the input byte is in D0. However, if a
1526
* control-C is read, 'CHKIO' will warm-start BASIC and will not
1527
* return to the caller.
1528
*
1529
CHKIO   bsr     GOIN            get input if possible
1530
        BEQ     CHKRET          if Zero, no input
1531
        CMP.B   #CTRLC,D0       is it control-C?
1532
        BNE     CHKRET          if not
1533
        BRA     WSTART          if so, do a warm start
1534
CHKRET  RTS
1535
 
1536
*
1537
* ===== Display a CR-LF sequence
1538
*
1539
;CRLF   LEA     CLMSG,A6
1540
 
1541
*
1542
* ===== Display a zero-ended string pointed to by register A6
1543
*
1544
PRMESG  MOVE.B  (A6)+,D0        get the char.
1545
        BEQ     PRMRET          if it's zero, we're done
1546
        BSR     GOOUT           else display it
1547
        BRA     PRMESG
1548
PRMRET  RTS
1549
 
1550
******************************************************
1551
* The following routines are the only ones that need *
1552
* to be changed for a different I/O environment.     *
1553
******************************************************
1554
 
1555
*
1556
* ===== Output character to the console (Port 1) from register D0
1557
*       (Preserves all registers.)
1558
*
1559
OUTC
1560
        move.l  a6,-(a7)
1561
        move.l  OUTPTR,a6
1562
        jsr                     (a6)
1563
        move.l  (a7)+,a6
1564
        rts
1565
 
1566
OUTC1
1567
        movem.l         d0/d1,-(a7)
1568
        move.l          d0,d1
1569
        moveq.l         #6,d0
1570
        trap                    #15
1571
        movem.l         (a7)+,d0/d1
1572
        rts
1573
 
1574
*OUTC   BTST    #1,$10040       is port 1 ready for a character?
1575
*       BEQ     OUTC            if not, wait for it
1576
*       MOVE.B  D0,$10042       out it goes.
1577
*       RTS
1578
 
1579
*
1580
* ===== Input a character from the console into register D0 (or
1581
*       return Zero status if there's no character available).
1582
*
1583
INC
1584
        move.l  a6,-(a7)
1585
        move.l  INPPTR,a6
1586
        jsr                     (a6)
1587
        move.l  (a7)+,a6
1588
        rts
1589
 
1590
INC1
1591
        move.l  d1,-(a7)
1592
        moveq.l #5,d0                   * function 5 GetKey
1593
        trap            #15
1594
        move.l  d1,d0
1595
        move.l  (a7)+,d1
1596
        cmpi.b  #-1,d0
1597
        bne                     .0001
1598
        clr.b           d0
1599
.0001:
1600
        rts
1601
 
1602
*INC    BTST    #0,$10040       is character ready?
1603
*       BEQ     INCRET          if not, return Zero status
1604
*       MOVE.B  $10042,D0       else get the character
1605
*       AND.B   #$7F,D0         zero out the high bit
1606
*INCRET RTS
1607
 
1608
*
1609
* ===== Output character to the host (Port 2) from register D0
1610
*       (Preserves all registers.)
1611
*
1612
AUXOUT:
1613
        movem.l d0/d1,-(a7)
1614
        move.l  d0,d1
1615
        moveq           #34,d0
1616
        trap            #15
1617
        movem.l (a7)+,d0/d1
1618
        rts
1619
 
1620
*AUXOUT BTST    #1,$10041       is port 2 ready for a character?
1621
*       BEQ     AUXOUT          if not, wait for it
1622
*       MOVE.B  D0,$10043       out it goes.
1623
*       RTS
1624
 
1625
*
1626
* ===== Input a character from the host into register D0 (or
1627
*       return Zero status if there's no character available).
1628
*
1629
AUXIN:
1630
        move.l  d1,-(a7)
1631
        moveq           #36,d0                          ; serial get char from buffer
1632
        trap            #15
1633
        move.l  d1,d0
1634
        move.l  (a7)+,d1
1635
        cmpi.w  #-1,d0
1636
        beq                     .0001
1637
        andi.b  #$7F,d0                         ; clear high bit
1638
        ext.w           d0                                              ; return character in d0
1639
        ext.l           d0
1640
        rts
1641
.0001:
1642
        moveq           #0,d0                                   ; return zf=1 if no character available
1643
        rts
1644
 
1645
;AUXIN
1646
*AUXIN  BTST    #0,$10041       is character ready?
1647
*       BEQ     AXIRET          if not, return Zero status
1648
*       MOVE.B  $10043,D0       else get the character
1649
*       AND.B   #$7F,D0         zero out the high bit
1650
AXIRET  RTS
1651
 
1652
*
1653
* ===== Return to the resident monitor, operating system, etc.
1654
*
1655
BYEBYE
1656
        bra             Monitor
1657
;       MOVE.B  #228,D7         return to Tutor
1658
;       TRAP    #14
1659
 
1660
INITMSG DC.B    CR,LF,'Gordo''s MC68000 Tiny BASIC, v1.2',CR,LF,LF,0
1661
OKMSG   DC.B    CR,LF,'OK',CR,LF,0
1662
HOWMSG  DC.B    'How?',CR,LF,0
1663
WHTMSG  DC.B    'What?',CR,LF,0
1664
SRYMSG  DC.B    'Sorry.'
1665
CLMSG   DC.B    CR,LF,0
1666
        DC.B    0        <- for aligning on a word boundary
1667
LSTROM  EQU     *               end of possible ROM area
1668
*
1669
* Internal variables follow:
1670
*
1671
RANPNT  DC.L    START           random number pointer
1672
INPPTR  DS.L    1               input pointer
1673
OUTPTR  DS.L    1       output pointer
1674
CURRNT  DS.L    1               Current line pointer
1675
STKGOS  DS.L    1               Saves stack pointer in 'GOSUB'
1676
STKINP  DS.L    1               Saves stack pointer during 'INPUT'
1677
LOPVAR  DS.L    1               'FOR' loop save area
1678
LOPINC  DS.L    1               increment
1679
LOPLMT  DS.L    1               limit
1680
LOPLN   DS.L    1               line number
1681
LOPPT   DS.L    1               text pointer
1682
TXTUNF  DS.L    1               points to unfilled text area
1683
VARBGN  DS.L    1               points to variable area
1684
STKLMT  DS.L    1               holds lower limit for stack growth
1685
BUFFER  DS.B    BUFLEN          Keyboard input buffer
1686
TXT     EQU     *               Beginning of program area
1687
;       END

powered by: WebSVN 2.1.0

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