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

Subversion Repositories rtf68ksys

[/] [rtf68ksys/] [trunk/] [Software/] [BOOTROM.x68] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 robfinch
;------------------------------------------------------------------------------
2
; This is a bit of a mess.
3
;------------------------------------------------------------------------------
4
 
5
;------------------------------------------------------------------------------
6
; 0x00000 to 0x00007    boot vector
7
; 0x00008 to 0x003ff    interrupt vectors
8
; 0x00400 to 0x                 system variables
9
; 0x10000 to 0x1ffff    thread control blocks
10
; 0x20000 to 0x3ffff    bitmap memory, page 1
11
; 0x40000 to 0x5ffff    bitmap memory, page 2
12
; 0x60000 to 0x7ffff    initial thread stacks
13
;------------------------------------------------------------------------------
14
INACTIVE        EQU             0x0000
15
ACTIVE          EQU             0x0001
16
 
17
CR      EQU     0x0D            ;ASCII equates
18
LF      EQU     0x0A
19
TAB     EQU     0x09
20
CTRLC   EQU     0x03
21
CTRLH   EQU     0x08
22
CTRLS   EQU     0x13
23
CTRLX   EQU     0x18
24
 
25
Milliseconds    EQU             0x400
26
Lastloc                 EQU             0x404
27
ScreenPtr       EQU             0x410
28
ScreenColor     EQU             0x414
29
CursorRow       EQU             0x418
30
CursorCol       EQU             0x41A
31
KeybdEcho       EQU             0x41C
32
PenColor        EQU             0x420
33
PenColor8       EQU             0x424
34
FillColor       EQU             0x428
35
FillColor8      EQU             0x42C
36
DrawPos         EQU             0x430
37
KeybdBuffer     EQU             0x440
38
KeybdHead       EQU             0x450
39
KeybdTail       EQU             0x452
40
Keybuf          EQU             0x460
41
memend          EQU             0x500
42
scratch1        EQU             0x700
43
S19StartAddress EQU             0x800
44
KEYBD           EQU             0xFFDC0000
45
TEXTSCR         EQU             0xFFD00000
46
COLORSCR        EQU             0xFFD10000
47
PSG                     EQU             0xFFD40000
48
SPRITERAM       EQU             0xFFD80000
49
PSG_FREQUENCY0  EQU             0xFFD40000
50
PSG_PULSEWIDTH0 EQU             0xFFD40002
51
PSG_CTRL0               EQU             0xFFD40004
52
PSG_ATTACK0             EQU             0xFFD40008
53
PSG_DECAY0              EQU             0xFFD4000A
54
PSG_SUSTAIN0    EQU             0xFFD4000C
55
PSG_RELEASE0    EQU             0xFFD4000E
56
PSG_MASTVOL             EQU             0xFFD40040
57
BITMAPSCR       EQU             0x00020000
58
UART            EQU             0xFFDC0A00
59
UART_LS         EQU             UART+1
60
UART_CTRL       EQU             UART+7
61
RANDOM          EQU             0xFFDC0C00
62
TEXTCTRL        EQU             0xFFDA0000
63
TEXT_COLS       EQU             0xFFDA0000
64
TEXT_ROWS       EQU             0xFFDA0002
65
TEXT_CURPOS     EQU             0xFFDA0016
66
STACK           EQU             0xFFFE07FC
67
TMPPMOD         EQU             0xFFDC0300
68
GRAPHICS        EQU             0xFFDAE000
69
G_DRAWLINE      EQU             0x0002
70
 
71
                CODE
72
;------------------------------------------------------------------------------
73
;------------------------------------------------------------------------------
74
; Clear all memory
75
 
76
; RAM test
77
        even
78
 
79
; We clear the screen to give a visual indication that the system
80
; is working at all.
81
;
82
        org     0xFFFF1100
83
main:
84
        move.w  #0xCE,ScreenColor       ; blue on blue
85
        move.b  #1,KeybdEcho            ; turn on keyboard echo
86
        jsr             ClearScreen
87
        clr.w   CursorRow
88
        clr.w   CursorCol
89
        lea             MSGRAM,a1
90
        jsr             DisplayString
91
 
92
    lea         main5,a3      ; get return address for ram test
93
    jmp         ramtest       ; Call ram test routine. (Called this way in case there's no RAM).
94
main5:
95
        ; setup user stack pointer
96
        ;
97
        move.l  ENDMEM,a0
98
        move.l  a0,usp
99
 
100
        ; reset the screen stuff
101
        ;
102
        move.w  #0xCE,ScreenColor       ; blue on blue
103
        move.b  #1,KeybdEcho            ; turn on keyboard echo
104
        clr.w   CursorRow               ; reset after RAMTEST
105
        clr.w   CursorCol
106
 
107
        ; randomize sprite memory
108
        move.l  #32768,d1
109
        lea             SPRITERAM,a0
110
main6:
111
        move.l  RANDOM,d0
112
        move.w  d0,(a0)+
113
        subi.l  #1,d1
114
        bne             main6
115
 
116
        ; setup vector table
117
        ;
118
        lea             BusError,a0
119
        move.l  a0,0x008                ; set bus error vector
120
        lea             AddressError,a0
121
        move.l  a0,0x00C                ; set address error vector
122
        lea             IllegalInstruction,a0
123
        move.l  a0,0x010
124
        lea             Pulse1000,a0
125
        move.l  a0,0x078                ; set autovector 6
126
        lea             KeybdNMI,a0
127
        move.l  a0,0x07C                ; set autovector 7
128
        lea             0xFFFF0800,a0
129
        move.l  a0,0x080                ; trap #0 AOS entry     - task switch
130
        lea             0xFFFF0400,a0
131
        move.l  a0,0x084                ; trap #1 AOS entry - AOS system call dispatcher
132
        lea             0xFFFF0C00,a0
133
        move.l  a0,0x088                ; trap #2 AOS entry - dispatcher
134
        lea             TRAP15,a0
135
        move.l  a0,0x0BC                ; set trap 15 vector
136
 
137
        clr.l   Milliseconds
138
        andi    #0xF000,sr              ; enable interrupts, stay in supervisor mode
139
 
140
        moveq   #14,d0
141
        lea             MSGBOOTING,a1   ; Display the boot message
142
        trap    #15
143
 
144
;       jsr             Beep
145
 
146
        ; test keyboard, wait for 'x' to be pressed
147
j7:
148
;       jmp             0xFFFF0000              ; start AOS
149
        jmp             START
150
 
151
        moveq   #5,d0
152
        trap    #15
153
        cmpi.b  #'x',d1
154
        bne             j7
155
 
156
        ; Clear bitmap memory
157
        move.l  #0x40000,d0
158
        lea             BITMAPSCR,a0
159
        move.w  #0x1234,d2
160
j8:
161
        move.w  d2,(a0)+
162
        subi.l  #1,d0                   ; can't use dbeq (>count ffff)
163
        bne             j8
164
 
165
        jmp             START                   ; goto tiny basic
166
 
167
 
168
        clr.b   UART_CTRL               ; turn off hardware flow control
169
j10:
170
        lea             0xFFFF0000,a2   ; start of bootstrap ROM
171
j9:
172
        move.b  (a2)+,d1
173
j6:
174
        move.b  UART_LS,d0              ; check line status
175
        btst    #5,d0                   ; can we transmit more ?
176
        beq             j6                              ; no, go back
177
        move.b  d1,UART
178
        cmpa.l  #0xFFFF0100,a2
179
        blo             j9
180
        bra             j10
181
j2:
182
        move.b  0xFFDD0000,d0
183
        bpl             j2
184
        move.l  0xFFDD0004,a0
185
        jmp             (a0)
186
 
187
MSGRAM:
188
        dc.b    "RAM TEST",0
189
MSGBOOTING:
190
        dc.b    "BOOTING....",0
191
 
192
        align   16
193
 
194
;------------------------------------------------------------------------------
195
; Pressing Ctl-Alt-Del on the keyboard causes a keyboard NMI, the highest
196
; priority interrupt in the system. This should be almost the same as a reset.
197
;------------------------------------------------------------------------------
198
;
199
KeybdNMI:
200
        jmp             main
201
        rte
202
 
203
;------------------------------------------------------------------------------
204
; Unimplemented yet.
205
;
206
; Normal keyboard interrupt, the lowest priority interrupt in the system.
207
; Grab the character from the keyboard device and store it in a buffer.
208
;------------------------------------------------------------------------------
209
;
210
KeybdIRQ:
211
        movem.l a0/d0/d1,-(a7)
212
        move.w  KeybdHead,d1
213
        andi.w  #0xf,d1                                 ; D1 = index into buffer
214
        lea             KeybdBuffer,a0
215
KeybdIRQa:
216
        move.w  KEYBD,d0                                ; get keyboard character
217
        clr.w   KEYBD+2                                 ; clear keyboard strobe
218
        move.b  d0,(a0,d1.w)                    ; store character in buffer
219
        addi.w  #1,d1                                   ; increment head index
220
        andi.w  #0xF,d1
221
        move.w  d1,KeybdHead
222
KeybdIRQb:
223
        cmp.w   KeybdTail,d1                    ; check to see if we've collided
224
        bne             KeybdIRQc                               ; with the tail
225
        addi.w  #1,d1                                   ; if so, increment the tail index
226
        andi.w  #0xf,d1                                 ; the oldest character will be lost
227
        move.w  d1,KeybdTail
228
KeybdIRQc:
229
        movem.l (a7)+,a0/d0/d1
230
        rte
231
 
232
;------------------------------------------------------------------------------
233
; 1000 Hz interrupt
234
; - takes care of "flashing" the cursor
235
;------------------------------------------------------------------------------
236
;
237
Pulse1000:
238
        move.l  d0,-(a7)
239
        add.l   #1,Milliseconds
240
        add.w   #1,TEXTSCR+102
241
        tst.b   0xFFFF0000              ; clear interrupt
242
        move.l  Milliseconds,d0
243
        andi.b  #0x7f,d0
244
        cmpi.b  #64,d0
245
        bne             p10001
246
        bsr             FlashCursor
247
p10001:
248
        move.l  (a7)+,d0
249
        rte
250
 
251
;------------------------------------------------------------------------------
252
; Flash Cursor
253
;------------------------------------------------------------------------------
254
;
255
FlashCursor:
256
        movem.l a0/a1/d0/d2,-(a7)
257
        bsr             CalcScreenLoc
258
        adda.l  #0x10000,a0
259
        ; causes screen colors to flip around
260
        move.w  (a0),d0
261
        ror.b   #4,d0
262
        move.w  d0,(a0)
263
        cmpa.l  Lastloc,a0
264
        beq             flshcrsr1
265
        ; restore the screen colors of the previous cursor location
266
        move.l  Lastloc,a1
267
        move.w  ScreenColor,(a1)
268
        move.l  a0,Lastloc
269
flshcrsr1:
270
        movem.l (a7)+,a0/a1/d0/d2
271
        rts
272
 
273
;------------------------------------------------------------------------------
274
;------------------------------------------------------------------------------
275
IdleTask:
276
        LINK    A5,#-PSIZ       ;RESERVE SPACE ON STACK FOR INPUT COMMAND LINE;
277
    lea.l   -MLFLAG(A5),A0
278
        LEA.L   -STATZ(A5),A1
279
        MOVE.W  #EMPTY,-MLFLAG(A5)
280
        MOVE.W  #LETTE,-MXLTRS(A5)      ;SETUP FOR "LETTE" LETTERS (WAS 2);
281
        MOVE.L  #AOS_POSTBOX,D0
282
        TRAP    #1                      ;POST MAILBOX;
283
IdleTask1:
284
        add.w   #1,TEXTSCR+100
285
        trap    #0
286
        bra             IdleTask1
287
 
288
;------------------------------------------------------------------------------
289
; TRAP #15 handler
290
;------------------------------------------------------------------------------
291
;
292
TRAP15:
293
        movem.l d0/a0,-(a7)
294
        lea             T15DispatchTable,a0
295
        andi.l  #0x0ff,d0
296
        asl.l   #2,d0
297
        move.l  (a0,d0.w),a0
298
        jsr             (a0)
299
        movem.l (a7)+,d0/a0
300
        rte
301
 
302
T15DispatchTable:
303
; Task 0
304
dc.l    DisplayString0
305
dc.l    DisplayString1
306
dc.l    StubRout
307
dc.l    DisplayNum3
308
dc.l    StubRout
309
dc.l    GetKey
310
dc.l    DisplayChar
311
dc.l    CheckForKey
312
dc.l    StubRout
313
dc.l    StubRout
314
; Task 10
315
dc.l    StubRout
316
dc.l    Cursor1
317
dc.l    SetKeyboardEcho
318
dc.l    DisplayStringCRLF
319
dc.l    DisplayString
320
dc.l    StubRout
321
dc.l    StubRout
322
dc.l    StubRout
323
dc.l    StubRout
324
dc.l    StubRout
325
; Task 20
326
dc.l    DisplayNum20
327
dc.l    StubRout
328
dc.l    StubRout
329
dc.l    StubRout
330
dc.l    StubRout
331
dc.l    StubRout
332
dc.l    StubRout
333
dc.l    StubRout
334
dc.l    StubRout
335
dc.l    StubRout
336
; Task 30
337
dc.l    StubRout
338
dc.l    StubRout
339
dc.l    StubRout
340
dc.l    StubRout
341
dc.l    StubRout
342
dc.l    StubRout
343
dc.l    StubRout
344
dc.l    StubRout
345
dc.l    StubRout
346
dc.l    StubRout
347
; Task 40
348
dc.l    StubRout
349
dc.l    StubRout
350
dc.l    StubRout
351
dc.l    StubRout
352
dc.l    StubRout
353
dc.l    StubRout
354
dc.l    StubRout
355
dc.l    StubRout
356
dc.l    StubRout
357
dc.l    StubRout
358
; Task 50
359
dc.l    StubRout
360
dc.l    StubRout
361
dc.l    StubRout
362
dc.l    StubRout
363
dc.l    StubRout
364
dc.l    StubRout
365
dc.l    StubRout
366
dc.l    StubRout
367
dc.l    StubRout
368
dc.l    StubRout
369
; Task 60
370
dc.l    StubRout
371
dc.l    StubRout
372
dc.l    StubRout
373
dc.l    StubRout
374
dc.l    StubRout
375
dc.l    StubRout
376
dc.l    StubRout
377
dc.l    StubRout
378
dc.l    StubRout
379
dc.l    StubRout
380
; Task 70
381
dc.l    StubRout
382
dc.l    StubRout
383
dc.l    StubRout
384
dc.l    StubRout
385
dc.l    StubRout
386
dc.l    StubRout
387
dc.l    StubRout
388
dc.l    StubRout
389
dc.l    StubRout
390
dc.l    StubRout
391
; Task 80
392
dc.l    SetPenColor
393
dc.l    SetFillColor
394
dc.l    DrawPixel
395
dc.l    StubRout
396
dc.l    DrawLine
397
dc.l    DrawLineTo
398
dc.l    MoveTo
399
dc.l    FillRectangle
400
dc.l    StubRout
401
dc.l    StubRout
402
; Task 90
403
dc.l    DrawRectangle
404
 
405
;------------------------------------------------------------------------------
406
; Stub routine for unimplemented functionality.
407
;------------------------------------------------------------------------------
408
;
409
StubRout:
410
        rts
411
 
412
;------------------------------------------------------------------------------
413
; Set the graphics mode pen color
414
;------------------------------------------------------------------------------
415
SetPenColor:
416
        movem.l d0/d1,-(a7)
417
        move.l  d1,PenColor
418
        bsr             Cvt24To8
419
        move.b  d1,PenColor8
420
        movem.l (a7)+,d0/d1
421
        rts
422
 
423
SetFillColor:
424
        movem.l d0/d1,-(a7)
425
        move.l  d1,FillColor
426
        bsr             Cvt24To8
427
        move.b  d1,FillColor8
428
        movem.l (a7)+,d0/d1
429
        rts
430
 
431
Cvt24To8:
432
        movem.l d0/d2,-(a7)
433
        clr.l   d2
434
        ror.l   #6,d1
435
        move.l  d1,d0
436
        and.b   #3,d0
437
        move.b  d0,d2
438
        ror.l   #2,d1                   ;
439
        ror.l   #5,d1
440
        move.b  d1,d0
441
        and.b   #7,d0
442
        asl.w   #2,d0
443
        or.b    d0,d2
444
        ror.l   #3,d1
445
        ror.l   #5,d1
446
        move.b  d1,d0
447
        and.b   #7,d0
448
        asl.w   #5,d0
449
        or.b    d0,d2
450
        move.l  d2,d1
451
        movem.l (a7)+,d0/d2
452
        rts
453
 
454
;------------------------------------------------------------------------------
455
; d1.w = X
456
; d2.w = Y
457
;------------------------------------------------------------------------------
458
DrawPixel:
459
        movem.l a0/d1/d2,-(a7)
460
        mulu.w  #208,d2         ; Y * 208
461
        andi.l  #0xffff,d2
462
        asl.l   #1,d2           ; Y * 416
463
        and.l   #0x1ff,d1
464
        add.l   d1,d2           ; Y * 416 + X
465
        add.l   #BITMAPSCR,d2
466
        move.l  d2,a0
467
        move.b  PenColor8,(a0)
468
        movem.l (a7)+,a0/d1/d2
469
        rts
470
 
471
;------------------------------------------------------------------------------
472
; d1.w = X1
473
; d2.w = Y1
474
; d3.w = X2
475
; d4.w = Y2
476
;
477
; From Wikipedia:
478
;
479
;function line(x0, y0, x1, y1)
480
;   dx := abs(x1-x0)
481
;   dy := abs(y1-y0)
482
;   if x0 < x1 then sx := 1 else sx := -1
483
;   if y0 < y1 then sy := 1 else sy := -1
484
;   err := dx-dy
485
;
486
;   loop
487
;     setPixel(x0,y0)
488
;     if x0 = x1 and y0 = y1 exit loop
489
;     e2 := 2*err
490
;     if e2 > -dy then
491
;       err := err - dy
492
;       x0 := x0 + sx
493
;     end if
494
;     if e2 <  dx then
495
;       err := err + dx
496
;       y0 := y0 + sy
497
;     end if
498
;   end loop
499
;
500
; Registers
501
; d1,d2,d3,d4 = X1,Y1,X2,Y2 respectively
502
; d0 = sx, d7 = sy
503
; d5 = dx, d6 = dy
504
; a2 = err
505
; a3 = 2*err
506
;------------------------------------------------------------------------------
507
DrawLine:
508
        movem.l d0/d1/d2/d3/d4/d5/d6/d7/a2/a3,-(a7)
509
        andi.l  #0x1ff,d1
510
        andi.l  #0x1ff,d2
511
        andi.l  #0x1ff,d3
512
        andi.l  #0x1ff,d4
513
        move.w  d3,DrawPos              ; X
514
        move.w  d4,DrawPos+2    ; Y
515
        move.l  d1,d5
516
        sub.l   d3,d5
517
        bpl             dl1
518
        neg.l   d5              ; d5 = dx
519
dl1:
520
        move.l  d2,d6
521
        sub.l   d4,d6
522
        bpl             dl2
523
        neg.l   d6              ; d6 = dy
524
dl2:
525
        moveq   #1,d0   ; sx = 1
526
        moveq   #1,d7   ; sy = 1
527
        cmp.l   d3,d1
528
        blo             dl3
529
        neg.l   d0              ; sx = -1
530
dl3:
531
        cmp.l   d4,d2
532
        blo             dl5
533
        neg.l   d7              ; sy = -1
534
dl5:
535
        move.l  d5,a2
536
        suba.l  d6,a2   ; err = dx-dy
537
        neg.l   d6                      ; -dy
538
 
539
DrawLineLoop:
540
        bsr             DrawPixel
541
        cmp.l   d1,d3           ; x0 = x1 ?
542
        bne             dl7                     ; no, keep going
543
        cmp.l   d2,d4           ; y0 = y1 ?
544
        beq             dldone          ; yes -> line draw is done
545
dl7:
546
        move.l  a2,a3           ; e2 = err
547
        adda.l  a3,a3           ; e2 = 2*err
548
        cmpa.l  d6,a3           ; if (e2 > -dy)
549
        ble             dl8
550
        adda.l  d6,a2           ;     err = err + -dy
551
        add.l   d0,d1           ;     x0 = x0 + sx
552
dl8:
553
        cmpa.l  d5,a3           ; if (e2 < dx)
554
        bge             dl9
555
        adda.l  d5,a2           ;     err = err + dx
556
        add.l   d7,d2           ;     y0 = y0 + sy
557
dl9:
558
        bra DrawLineLoop
559
dldone:
560
        movem.l (a7)+,d0/d1/d2/d3/d4/d5/d6/d7/a2/a3
561
        rts
562
 
563
;------------------------------------------------------------------------------
564
; Draw line to X,Y
565
; D1.W = X
566
; D2.W = Y
567
;------------------------------------------------------------------------------
568
;
569
DrawLineTo:
570
        movem.l d1/d2/d3/d4,-(a7)
571
        move.w  d1,d3
572
        move.w  d2,d4
573
        move.w  DrawPos,d1
574
        move.w  DrawPos+2,d2
575
        bsr             DrawLine
576
        movem.l (a7)+,d1/d2/d3/d4
577
        rts
578
 
579
 
580
;------------------------------------------------------------------------------
581
; Move drawing position to X,Y
582
; d1.w = X
583
; d2.w = y
584
;------------------------------------------------------------------------------
585
;
586
MoveTo:
587
        move.w  d1,DrawPos
588
        move.w  d2,DrawPos+2
589
        rts
590
 
591
DrawRectangle:
592
        movem.l d0/d1/d2/d3/d4/d5/d6/d7,-(a7)
593
        move.w  d1,d0
594
        move.w  d2,d7
595
        move.w  d3,d5
596
        move.w  d4,d6
597
        move.w  d2,d4
598
        bsr             DrawLine
599
        move.w  d3,d1
600
        move.w  d4,d2
601
        move.w  d5,d3
602
        move.w  d6,d4
603
        bsr             DrawLine
604
        move.w  d3,d1
605
        move.w  d4,d2
606
        move.w  d0,d3
607
        move.w  d6,d4
608
        bsr             DrawLine
609
        move.w  d3,d1
610
        move.w  d4,d2
611
        move.w  d0,d3
612
        move.w  d7,d4
613
        bsr             DrawLine
614
        movem.l (a7)+,d0/d1/d2/d3/d4/d5/d6/d7
615
        rts
616
 
617
;------------------------------------------------------------------------------
618
; Draw a filled rectangle
619
;------------------------------------------------------------------------------
620
FillRectangle:
621
        movem.l d1/d2/d3/d4,-(a7)
622
        move.w  PenColor8,-(a7)
623
        bsr     DrawRectangle
624
        move.w  FillColor8,PenColor8
625
FillRect3:
626
        cmp.w   d1,d3
627
        blo             FillRect1
628
        cmp.w   d2,d4
629
        bhs             FillRect2
630
FillRect1:
631
        addi.w  #1,d1
632
        addi.w  #1,d2
633
        subi.w  #1,d3
634
        subi.w  #1,d4
635
        bsr             DrawRectangle
636
        bra             FillRect3
637
FillRect2:
638
        move.w  (a7)+,PenColor8
639
        movem.l (a7)+,d1/d2/d3/d4
640
        rts
641
 
642
;------------------------------------------------------------------------------
643
; d1.b 0=echo off, non-zero = echo on
644
;------------------------------------------------------------------------------
645
SetKeyboardEcho:
646
        move.b  d1,KeybdEcho
647
        rts
648
 
649
;------------------------------------------------------------------------------
650
; read ascii character into d1.b
651
;------------------------------------------------------------------------------
652
;
653
        nop
654
        nop
655
        nop
656
        nop
657
        nop
658
        nop
659
        nop
660
        nop
661
        nop
662
        nop
663
        nop
664
        nop
665
        nop
666
        nop
667
        nop
668
        nop
669
        nop
670
        nop
671
        nop
672
 
673
GetKey:
674
        move.w  KEYBD,d1
675
        bpl     GetKey
676
        clr.w   KEYBD+2                 ; clear the keyboard strobe
677
        and.w   #0xFF,d1                ; remove strobe bit
678
        cmpi.b  #0,KeybdEcho    ; is keyboard echo on ?
679
        beq             gk1
680
        cmpi.b  #'\r',d1                ; convert CR keystroke into CRLF
681
        beq             CRLF
682
        jsr             DisplayChar
683
gk1:
684
        rts
685
 
686
;------------------------------------------------------------------------------
687
; get key pending status into d1.b
688
;------------------------------------------------------------------------------
689
;
690
CheckForKey:
691
        move.w  KEYBD,d1
692
        bpl             cfk1
693
        move.b  #1,d1
694
        rts
695
cfk1:
696
        clr.b   d1
697
        rts
698
 
699
;
700
CRLF:
701
        move.l  d1,-(a7)
702
        move.b  #'\r',d1
703
        jsr             DisplayChar
704
        move.b  #'\n',d1
705
        jsr             DisplayChar
706
        move.l  (a7)+,d1
707
        rts
708
 
709
;------------------------------------------------------------------------------
710
; Calculate screen memory location from CursorRow,CursorCol.
711
; Destroys d0,d2,a0
712
;------------------------------------------------------------------------------
713
;
714
CalcScreenLoc:
715
        move.w  CursorRow,d0            ; compute screen location
716
        andi.w  #0x7f,d0
717
        mulu.w  TEXT_COLS,d0
718
        move.w  CursorCol,d2
719
        andi.w  #0xff,d2
720
        add.w   d2,d0
721
        asl.w   #1,d0
722
        add.l   #TEXTSCR,d0
723
        move.l  d0,a0                           ; a0 = screen location
724
        lsr.l   #1,d0
725
        move.w  d0,TEXT_CURPOS
726
        rts
727
 
728
;------------------------------------------------------------------------------
729
; Display a character on the screen
730
; d1.b = char to display
731
;------------------------------------------------------------------------------
732
;
733
DisplayChar:
734
        cmpi.b  #'\r',d1                        ; carriage return ?
735
        bne             dccr
736
        clr.w   CursorCol                       ; just set cursor column to zero on a CR
737
        rts
738
dccr:
739
        cmpi.b  #0x91,d1                        ; cursor right ?
740
        bne     dcx6
741
        cmpi.w  #51,CursorCol
742
        beq             dcx7
743
        addi.w  #1,CursorCol
744
dcx7:
745
        rts
746
dcx6:
747
        cmpi.b  #0x90,d1                        ; cursor up ?
748
        bne             dcx8
749
        cmpi.w  #0,CursorRow
750
        beq             dcx7
751
        subi.w  #1,CursorRow
752
        rts
753
dcx8:
754
        cmpi.b  #0x93,d1                        ; cursor left?
755
        bne             dcx9
756
        cmpi.w  #0,CursorCol
757
        beq             dcx7
758
        subi.w  #1,CursorCol
759
        rts
760
dcx9:
761
        cmpi.b  #0x92,d1                        ; cursor down ?
762
        bne             dcx10
763
        cmpi.w  #30,CursorRow
764
        beq             dcx7
765
        addi.w  #1,CursorRow
766
        rts
767
dcx10:
768
        cmpi.b  #0x94,d1                        ; cursor home ?
769
        bne             dcx11
770
        cmpi.w  #0,CursorCol
771
        beq             dcx12
772
        clr.w   CursorCol
773
        rts
774
dcx12
775
        clr.w   CursorRow
776
        rts
777
dcx11:
778
        movem.l d0/d1/d2/a0,-(a7)
779
        cmpi.b  #0x99,d1                        ; delete ?
780
        bne             dcx13
781
        bsr             CalcScreenLoc
782
        move.w  CursorCol,d0
783
        bra             dcx5
784
dcx13:
785
        cmpi.b  #CTRLH,d1                       ; backspace ?
786
        bne     dcx3
787
        cmpi.w  #0,CursorCol
788
        beq     dcx4
789
        subi.w  #1,CursorCol
790
        bsr             CalcScreenLoc           ; a0 = screen location
791
        move.w  CursorCol,d0
792
dcx5:
793
        move.w  2(a0),(a0)+
794
        addi.w  #1,d0
795
        cmp.w   TEXT_COLS,d0
796
        blo             dcx5
797
        move.w  #32,d0
798
        move.w  d0,-2(a0)
799
        bra             dcx4
800
dcx3:
801
        cmpi.b  #'\n',d1                ; linefeed ?
802
        beq             dclf
803
 
804
        bsr             CalcScreenLoc   ; a0 = screen location
805
        bsr             AsciiToScreen   ; convert ascii char to screen char
806
        move.w  d1,(a0)+
807
        bsr             IncCursorPos
808
        movem.l (a7)+,d0/d1/d2/a0
809
        rts
810
dclf:
811
        bsr             IncCursorRow
812
dcx4:
813
        movem.l (a7)+,d0/d1/d2/a0               ; get back a0
814
        rts
815
 
816
;------------------------------------------------------------------------------
817
; Increment the cursor position, scroll the screen if needed.
818
;------------------------------------------------------------------------------
819
;
820
IncCursorPos:
821
        addi.w  #1,TEXT_CURPOS
822
        addi.w  #1,CursorCol
823
        move.w  TEXT_COLS,d0
824
        cmp.w   CursorCol,d0
825
        bhs             icc1
826
        clr.w   CursorCol
827
IncCursorRow:
828
        addi.w  #1,CursorRow
829
        move.w  TEXT_ROWS,d0
830
        cmp.w   CursorRow,d0
831
        bhi             icc1
832
        move.w  TEXT_ROWS,d0
833
        move.w  d0,CursorRow            ; in case CursorRow is way over
834
        subi.w  #1,CursorRow
835
        asl.w   #1,d0
836
        sub.w   d0,TEXT_CURPOS
837
        bsr             ScrollUp
838
icc1:
839
        rts
840
 
841
;------------------------------------------------------------------------------
842
; Display a string on the screen.
843
;------------------------------------------------------------------------------
844
;
845
DisplayString:
846
        movem.l d0/d1/a1,-(a7)
847
dspj1:
848
        clr.l   d1                              ; clear upper bits of d1
849
        move.b  (a1)+,d1                ; move string char into d1
850
        cmpi.b  #0,d1                   ; is it end of string ?
851
        beq             dsret
852
        bsr             DisplayChar             ; display character
853
        bra             dspj1                   ; go back for next character
854
dsret:
855
        movem.l (a7)+,d0/d1/a1
856
        rts
857
 
858
DisplayStringCRLF:
859
        bsr             DisplayString
860
        bra             CRLF
861
 
862
;------------------------------------------------------------------------------
863
; Display a string on the screen. Stop at 255 chars, or NULL or D1.W
864
;------------------------------------------------------------------------------
865
;
866
DisplayString1:
867
        movem.l d0/d1/a1,-(a7)
868
        andi.w  #255,d1                 ; max 255 chars
869
        move.l  d1,d0
870
dspj11:
871
        move.b  (a1)+,d1                ; move string char into d1
872
        cmpi.b  #0,d1                   ; is it end of string ?
873
        beq             dsret1
874
        bsr             DisplayChar             ; display character
875
        dbeq    d0,dspj11               ; go back for next character
876
dsret1:
877
        movem.l (a7)+,d0/d1/a1
878
        rts
879
 
880
;------------------------------------------------------------------------------
881
; Display a string on the screen. Stop at 255 chars, or NULL or D1.W
882
; end string with CR,LF
883
;------------------------------------------------------------------------------
884
;
885
DisplayString0:
886
        bsr             DisplayString1
887
        bra             CRLF
888
 
889
;------------------------------------------------------------------------------
890
; Dispatch cursor functions
891
;------------------------------------------------------------------------------
892
;
893
Cursor1:
894
        cmpi.w  #0x00ff,d1
895
        beq             GetCursorPos
896
        cmpi.w  #0xFF00,d1
897
        beq             SetCursorPos
898
        jsr             ClearScreen
899
        rts
900
 
901
;------------------------------------------------------------------------------
902
; Get the cursor position.
903
; d1.b0 = row
904
; d1.b1 = col
905
;------------------------------------------------------------------------------
906
;
907
GetCursorPos:
908
        move.w  CursorCol,d1
909
        asl.w   #8,D1
910
        move.b  CursorRow,d1
911
        rts
912
 
913
;------------------------------------------------------------------------------
914
; Set the position of the cursor, update the linear screen pointer.
915
; d1.b0 = row
916
; d1.b1 = col
917
;------------------------------------------------------------------------------
918
;
919
SetCursorPos:
920
        move.l  d1,-(a7)
921
        move.b  d1,CursorRow
922
        lsr.w   #8,d1
923
        move.w  d1,CursorCol
924
        move.w  CursorRow,d1
925
        mulu.w  TEXT_COLS,d1
926
        add.w   CursorCol,d1
927
        asl.w   #1,d1
928
        move.w  d1,TEXT_CURPOS
929
scp1:
930
        move.l  (a7)+,d1
931
        rts
932
 
933
;------------------------------------------------------------------------------
934
; Clear the screen and the screen color memory
935
; We clear the screen to give a visual indication that the system
936
; is working at all.
937
;------------------------------------------------------------------------------
938
;
939
ClearScreen:
940
        move.w  TEXT_COLS,d1    ; calc number to clear
941
        mulu.w  TEXT_ROWS,d1
942
        move.w  #32,d0                  ; space character
943
        move.l  #TEXTSCR,a0             ; text screen address
944
csj4:
945
        move.w  d0,(a0)+
946
        dbeq    d1,csj4
947
 
948
        move.w  TEXT_COLS,d1    ; calc number to clear
949
        mulu.w  TEXT_ROWS,d1
950
        move.w  ScreenColor,d0          ; a nice color blue, light blue
951
        move.l  #COLORSCR,a0            ; text color address
952
csj3:
953
        move.w  d0,(a0)+
954
        dbeq    d1,csj3
955
        rts
956
 
957
;------------------------------------------------------------------------------
958
; Scroll text on the screen upwards
959
;------------------------------------------------------------------------------
960
;
961
ScrollUp:
962
        movem.l d0/d1/d2/a0,-(a7)
963
        move.w  TEXT_COLS,d0            ; calc number of chars to scroll
964
        mulu.w  TEXT_ROWS,d0
965
        sub.w   TEXT_COLS,d0            ; one less row
966
        lea             TEXTSCR,a0
967
        move.w  TEXT_COLS,d2
968
        asl.w   #1,d2
969
scrup1:
970
        move.w  (a0,d2.w),(a0)+
971
        dbeq    d0,scrup1
972
 
973
        move.w  TEXT_ROWS,d1
974
        subi.w  #1,d1
975
        jsr             BlankLine
976
        movem.l (a7)+,d0/d1/d2/a0
977
        rts
978
 
979
;------------------------------------------------------------------------------
980
; Blank out a line on the display
981
; line number to blank is in D1.W
982
;------------------------------------------------------------------------------
983
;
984
BlankLine:
985
        movem.l d0/a0,-(a7)
986
        move.w  TEXT_COLS,d0
987
        mulu.w  d1,d0                           ; d0 = row * cols
988
        asl.w   #1,d0                           ; *2 for moving words, not bytes
989
        add.l   #TEXTSCR,d0                     ; add in screen base
990
        move.l  d0,a0
991
        move.w  TEXT_COLS,d0            ; d0 = number of chars to blank out
992
blnkln1:
993
        move.w  #' ',(a0)+
994
        dbeq    d0,blnkln1
995
        movem.l (a7)+,d0/a0
996
        rts
997
 
998
;------------------------------------------------------------------------------
999
; d1 = number
1000
; d2.b = column width
1001
;------------------------------------------------------------------------------
1002
DisplayNum20:
1003
        movem.l d0/d1/d2/d3/d4,-(a7)
1004
        clr.l   d4
1005
        move.b  d2,d4
1006
        jsr             PRTNUM
1007
        movem.l (a7)+,d0/d1/d2/d3/d4
1008
        rts
1009
 
1010
;------------------------------------------------------------------------------
1011
; d1 = number
1012
;------------------------------------------------------------------------------
1013
DisplayNum3:
1014
        movem.l d0/d1/d2/d3/d4,-(a7)
1015
        clr.l   d4
1016
        jsr             PRTNUM
1017
        movem.l (a7)+,d0/d1/d2/d3/d4
1018
        rts
1019
 
1020
;------------------------------------------------------------------------------
1021
; Convert ASCII character to screen display character.
1022
;------------------------------------------------------------------------------
1023
;
1024
AsciiToScreen:
1025
        andi.w  #0x00ff,d1
1026
        cmpi.b  #'A',d1
1027
        blo             atoscr1
1028
        cmpi.b  #'Z',d1
1029
        bls             atoscr1
1030
        cmpi.b  #'z',d1
1031
        bhi     atoscr1
1032
        cmpi.b  #'a',d1
1033
        blo     atoscr1
1034
        subi.b  #0x60,d1
1035
atoscr1:
1036
        ori.w   #0x100,d1
1037
        rts
1038
 
1039
;------------------------------------------------------------------------------
1040
; Convert screen character to ascii character
1041
;------------------------------------------------------------------------------
1042
;
1043
ScreenToAscii:
1044
        andi.b  #0xff,d1
1045
        cmpi.b  #26,d1
1046
        bhi             stasc1
1047
        addi.b  #0x60,d1
1048
stasc1:
1049
        rts
1050
 
1051
;------------------------------------------------------------------------------
1052
; Display nybble in D1.B
1053
;------------------------------------------------------------------------------
1054
;
1055
DisplayNybble:
1056
        move.w  d1,-(a7)
1057
        andi.b  #0xF,d1
1058
        addi.b  #'0',d1
1059
        cmpi.b  #'9',d1
1060
        bls             dispnyb1
1061
        addi.b  #7,d1
1062
dispnyb1:
1063
        bsr             DisplayChar
1064
        move.w  (a7)+,d1
1065
        rts
1066
 
1067
;------------------------------------------------------------------------------
1068
; Display the byte in D1.B
1069
;------------------------------------------------------------------------------
1070
;
1071
DisplayByte:
1072
        move.w  d1,-(a7)
1073
        ror.b   #4,d1
1074
        bsr             DisplayNybble
1075
        rol.b   #4,d1
1076
        bsr             DisplayNybble
1077
        move.w  (a7)+,d1
1078
        rts
1079
 
1080
;------------------------------------------------------------------------------
1081
; Display the 32 bit word in D1.L
1082
;------------------------------------------------------------------------------
1083
;
1084
DisplayWord:
1085
        rol.l   #8,d1
1086
        bsr             DisplayByte
1087
        rol.l   #8,d1
1088
        bsr             DisplayByte
1089
        rol.l   #8,d1
1090
        bsr             DisplayByte
1091
        rol.l   #8,d1
1092
        bsr             DisplayByte
1093
        rts
1094
 
1095
DisplayMem:
1096
        move.b  #':',d1
1097
        jsr             DisplayChar
1098
        move.l  a0,d1
1099
        jsr             DisplayWord
1100
        moveq   #7,d2
1101
dspmem1:
1102
        move.b  #' ',d1
1103
        jsr             DisplayChar
1104
        move.b  (a0)+,d1
1105
        jsr             DisplayByte
1106
        dbra    d2,dspmem1
1107
        jmp             CRLF
1108
 
1109
;==============================================================================
1110
; Monitor
1111
;==============================================================================
1112
;
1113
StartMon:
1114
Monitor:
1115
;       lea             STACK,a7                ; reset the stack pointer
1116
        clr.w   KeybdEcho               ; turn off keyboard echo
1117
PromptLn:
1118
        bsr             CRLF
1119
        move.b  #'$',d1
1120
        bsr             DisplayChar
1121
 
1122
; Get characters until a CR is keyed
1123
;
1124
Prompt3:
1125
        bsr             GetKey
1126
        cmpi.b  #CR,d1
1127
        beq             Prompt1
1128
        bsr             DisplayChar
1129
        bra             Prompt3
1130
 
1131
; Process the screen line that the CR was keyed on
1132
;
1133
Prompt1:
1134
        clr.w   CursorCol               ; go back to the start of the line
1135
        bsr             CalcScreenLoc   ; a0 = screen memory location
1136
        move.w  (a0)+,d1
1137
        bsr             ScreenToAscii
1138
        cmpi.b  #'$',d1                 ; skip over '$' prompt character
1139
        bne             Prompt2
1140
        move.w  (a0)+,d1
1141
        bsr             ScreenToAscii
1142
 
1143
; Dispatch based on command character
1144
;
1145
Prompt2:
1146
        cmpi.b  #':',d1                 ; $: - edit memory
1147
        beq             EditMem
1148
        cmpi.b  #'D',d1                 ; $D - dump memory
1149
        beq             DumpMem
1150
        cmpi.b  #'B',d1                 ; $B - start tiny basic
1151
        beq             START
1152
        cmpi.b  #'J',d1                 ; $J - execute code
1153
        beq             ExecuteCode
1154
        cmpi.b  #'L',d1                 ; $L - load S19 file
1155
        beq             LoadS19
1156
        cmpi.b  #'?',d1                 ; $? - display help
1157
        beq             DisplayHelp
1158
        cmpi.b  #'C',d1                 ; $C - clear screen
1159
        beq             TestCLS
1160
        bra             Monitor
1161
 
1162
TestCLS:
1163
        move.w  (a0)+,d1
1164
        bsr             ScreenToAscii
1165
        cmpi.b  #'L',d1
1166
        bne             Monitor
1167
        move.w  (a0)+,d1
1168
        bsr             ScreenToAscii
1169
        cmpi.b  #'S',d1
1170
        bne             Monitor
1171
        bsr             ClearScreen
1172
        bra             Monitor
1173
 
1174
DisplayHelp:
1175
        lea             HelpMsg,a1
1176
        jsr             DisplayString
1177
        bra             Monitor
1178
 
1179
HelpMsg:
1180
        dc.b    "? = Display help",CR,LF
1181
        dc.b    "CLS = clear screen",CR,LF
1182
        dc.b    ": = Edit memory bytes",CR,LF
1183
        dc.b    "L = Load S19 file",CR,LF
1184
        dc.b    "D = Dump memory",CR,LF
1185
        dc.b    "B = start tiny basic",CR,LF
1186
        dc.b    "J = Jump to code",CR,LF,0
1187
        even
1188
 
1189
;------------------------------------------------------------------------------
1190
;------------------------------------------------------------------------------
1191
;
1192
ignBlanks:
1193
        move.w  (a0)+,d1
1194
        bsr             ScreenToAscii
1195
        cmpi.b  #' ',d1
1196
        beq             ignBlanks
1197
        subq    #2,a0
1198
        rts
1199
 
1200
;------------------------------------------------------------------------------
1201
; Edit memory byte.
1202
;------------------------------------------------------------------------------
1203
;
1204
EditMem:
1205
        bsr             ignBlanks
1206
        bsr             GetHexNumber
1207
        move.l  d1,a1
1208
edtmem1:
1209
        bsr             ignBlanks
1210
        bsr             GetHexNumber
1211
        move.b  d1,(a1)+
1212
        bsr             ignBlanks
1213
        bsr             GetHexNumber
1214
        move.b  d1,(a1)+
1215
        bsr             ignBlanks
1216
        bsr             GetHexNumber
1217
        move.b  d1,(a1)+
1218
        bsr             ignBlanks
1219
        bsr             GetHexNumber
1220
        move.b  d1,(a1)+
1221
        bsr             ignBlanks
1222
        bsr             GetHexNumber
1223
        move.b  d1,(a1)+
1224
        bsr             ignBlanks
1225
        bsr             GetHexNumber
1226
        move.b  d1,(a1)+
1227
        bsr             ignBlanks
1228
        bsr             GetHexNumber
1229
        move.b  d1,(a1)+
1230
        bsr             ignBlanks
1231
        bsr             GetHexNumber
1232
        move.b  d1,(a1)+
1233
        bra             Monitor
1234
 
1235
;------------------------------------------------------------------------------
1236
; Execute code at the specified address.
1237
;------------------------------------------------------------------------------
1238
;
1239
ExecuteCode:
1240
        bsr             ignBlanks
1241
        bsr             GetHexNumber
1242
        move.l  d1,a0
1243
        jsr             (a0)
1244
        bra     Monitor
1245
 
1246
;------------------------------------------------------------------------------
1247
; Do a memory dump of the requested location.
1248
;------------------------------------------------------------------------------
1249
;
1250
DumpMem:
1251
        bsr             ignBlanks
1252
        bsr             GetHexNumber
1253
        move.l  d1,a0
1254
        jsr             CRLF
1255
        bsr             DisplayMem
1256
        bsr             DisplayMem
1257
        bsr             DisplayMem
1258
        bsr             DisplayMem
1259
        bsr             DisplayMem
1260
        bsr             DisplayMem
1261
        bsr             DisplayMem
1262
        bsr             DisplayMem
1263
        bra             Monitor
1264
 
1265
;------------------------------------------------------------------------------
1266
; Get a hexidecimal number. Maximum of eight digits.
1267
;------------------------------------------------------------------------------
1268
;
1269
GetHexNumber:
1270
        movem.l d0/d2,-(a7)
1271
        clr.l   d2
1272
        moveq   #7,d0
1273
gthxn2:
1274
        move.w  (a0)+,d1
1275
        bsr             ScreenToAscii
1276
        bsr             AsciiToHexNybble
1277
        cmp.b   #0xff,d1
1278
        beq             gthxn1
1279
        lsl.l   #4,d2
1280
        andi.l  #0x0f,d1
1281
        or.l    d1,d2
1282
        dbra    d0,gthxn2
1283
gthxn1:
1284
        move.l  d2,d1
1285
        movem.l (a7)+,d0/d2
1286
        rts
1287
 
1288
;------------------------------------------------------------------------------
1289
; Convert ASCII character in the range '0' to '9', 'a' tr 'f' or 'A' to 'F'
1290
; to a hex nybble.
1291
;------------------------------------------------------------------------------
1292
;
1293
AsciiToHexNybble:
1294
        cmpi.b  #'0',d1
1295
        blo             gthx3
1296
        cmpi.b  #'9',d1
1297
        bhi             gthx5
1298
        subi.b  #'0',d1
1299
        rts
1300
gthx5:
1301
        cmpi.b  #'A',d1
1302
        blo             gthx3
1303
        cmpi.b  #'F',d1
1304
        bhi             gthx6
1305
        subi.b  #'A',d1
1306
        addi.b  #10,d1
1307
        rts
1308
gthx6:
1309
        cmpi.b  #'a',d1
1310
        blo             gthx3
1311
        cmpi.b  #'f',d1
1312
        bhi             gthx3
1313
        subi.b  #'a',d1
1314
        addi.b  #10,d1
1315
        rts
1316
gthx3:
1317
        moveq   #-1,d1          ; not a hex number
1318
        rts
1319
 
1320
;==============================================================================
1321
; Load an S19 format file
1322
;==============================================================================
1323
;
1324
LoadS19:
1325
        bra             ProcessRec
1326
NextRec:
1327
        bsr             sGetChar
1328
        cmpi.b  #LF,d0
1329
        bne             NextRec
1330
ProcessRec
1331
        bsr             sGetChar
1332
        move.b  d0,d4
1333
        cmpi.b  #26,d4          ; CTRL-Z ?
1334
        beq             Monitor
1335
        cmpi.b  #'S',d4
1336
        bne             NextRec
1337
        bsr             sGetChar
1338
        move.b  d0,d4
1339
        cmpi.b  #'0',d4
1340
        blo             NextRec
1341
        cmpi.b  #'9',d4         ; d4 = record type
1342
        bhi             NextRec
1343
        bsr             sGetChar
1344
        bsr             AsciiToHexNybble
1345
        move.b  d1,d2
1346
        bsr             sGetChar
1347
        bsr             AsciiToHexNybble
1348
        lsl.b   #4,d2
1349
        or.b    d2,d1           ; d1 = byte count
1350
        move.b  d1,d3           ; d3 = byte count
1351
        cmpi.b  #'0',d4         ; manufacturer ID record, ignore
1352
        beq             NextRec
1353
        cmpi.b  #'1',d4
1354
        beq             ProcessS1
1355
        cmpi.b  #'2',d4
1356
        beq             ProcessS2
1357
        cmpi.b  #'3',d4
1358
        beq             ProcessS3
1359
        cmpi.b  #'5',d4         ; record count record, ignore
1360
        beq             NextRec
1361
        cmpi.b  #'7',d4
1362
        beq             ProcessS7
1363
        cmpi.b  #'8',d4
1364
        beq             ProcessS8
1365
        cmpi.b  #'9',d4
1366
        beq             ProcessS9
1367
        bra             NextRec
1368
 
1369
pcssxa
1370
        andi.w  #0xff,d3
1371
        subi.w  #1,d3                   ; one less for dbra
1372
pcss1a
1373
        clr.l   d2
1374
        bsr             sGetChar
1375
        bsr             AsciiToHexNybble
1376
        lsl.l   #4,d2
1377
        or.b    d1,d2
1378
        bsr             sGetChar
1379
        bsr             AsciiToHexNybble
1380
        lsl.l   #4,d2
1381
        or.b    d1,d2
1382
        move.b  d2,(a1)+
1383
        dbra    d3,pcss1a
1384
; Get the checksum byte
1385
        clr.l   d2
1386
        bsr             sGetChar
1387
        bsr             AsciiToHexNybble
1388
        lsl.l   #4,d2
1389
        or.b    d1,d2
1390
        bsr             sGetChar
1391
        bsr             AsciiToHexNybble
1392
        lsl.l   #4,d2
1393
        or.b    d1,d2
1394
        bra             NextRec
1395
 
1396
ProcessS1:
1397
        bsr             S19Get16BitAddress
1398
        bra             pcssxa
1399
ProcessS2:
1400
        bsr             S19Get24BitAddress
1401
        bra             pcssxa
1402
ProcessS3:
1403
        bsr             S19Get32BitAddress
1404
        bra             pcssxa
1405
ProcessS7:
1406
        bsr             S19Get32BitAddress
1407
        move.l  a1,S19StartAddress
1408
        bra             Monitor
1409
ProcessS8:
1410
        bsr             S19Get24BitAddress
1411
        move.l  a1,S19StartAddress
1412
        bra             Monitor
1413
ProcessS9:
1414
        bsr             S19Get16BitAddress
1415
        move.l  a1,S19StartAddress
1416
        bra             Monitor
1417
 
1418
S19Get16BitAddress:
1419
        clr.l   d2
1420
        bsr             sGetChar
1421
        bsr             AsciiToHexNybble
1422
        move.b  d1,d2
1423
        bra             S1932b
1424
 
1425
S19Get24BitAddress:
1426
        clr.l   d2
1427
        bsr             sGetChar
1428
        bsr             AsciiToHexNybble
1429
        move.b  d1,d2
1430
        bra             S1932a
1431
 
1432
S19Get32BitAddress:
1433
        clr.l   d2
1434
        bsr             sGetChar
1435
        bsr             AsciiToHexNybble
1436
        move.b  d1,d2
1437
        bsr             sGetChar
1438
        bsr             AsciiToHexNybble
1439
        lsl.l   #4,d2
1440
        or.b    d1,d2
1441
        bsr             sGetChar
1442
        bsr             AsciiToHexNybble
1443
        lsl.l   #4,d2
1444
        or.b    d1,d2
1445
S1932a:
1446
        bsr             sGetChar
1447
        bsr             AsciiToHexNybble
1448
        lsl.l   #4,d2
1449
        or.b    d1,d2
1450
        bsr             sGetChar
1451
        bsr             AsciiToHexNybble
1452
        lsl.l   #4,d2
1453
        or.b    d1,d2
1454
S1932b:
1455
        bsr             sGetChar
1456
        bsr             AsciiToHexNybble
1457
        lsl.l   #4,d2
1458
        or.b    d1,d2
1459
        bsr             sGetChar
1460
        bsr             AsciiToHexNybble
1461
        lsl.l   #4,d2
1462
        or.b    d1,d2
1463
        bsr             sGetChar
1464
        bsr             AsciiToHexNybble
1465
        lsl.l   #4,d2
1466
        or.b    d1,d2
1467
        clr.l   d4
1468
        move.l  d2,a1
1469
        rts
1470
 
1471
;------------------------------------------------------------------------------
1472
; Get a character from auxillary input, checking the keyboard status for a
1473
; CTRL-C
1474
;------------------------------------------------------------------------------
1475
;
1476
sGetChar:
1477
        bsr             CheckForKey
1478
        beq             sgc1
1479
        bsr             GetKey
1480
        cmpi.b  #CTRLC,d1
1481
        beq             Monitor
1482
sgc1:
1483
        bsr             AUXIN
1484
        beq             sGetChar
1485
        move.b  d0,d1
1486
        rts
1487
 
1488
;==============================================================================
1489
;==============================================================================
1490
 
1491
;------------------------------------------------------------------------------
1492
; Sound a tone for a second.
1493
;------------------------------------------------------------------------------
1494
;
1495
Beep:
1496
        move.w  #15,PSG_MASTVOL                 ; set master volume
1497
        move.w  #16667,PSG_FREQUENCY0   ; 1000 Hz
1498
        clr.w   PSG_PULSEWIDTH0                 ; not used
1499
        clr.w   PSG_ATTACK0                             ; zero attack time
1500
        clr.w   PSG_DECAY0                              ; zero decay time
1501
        move.w  #255,PSG_SUSTAIN0               ; max sustain level
1502
        clr.w   PSG_RELEASE0                    ; zero release time
1503
        move.w  #0x1104,PSG_CTRL0               ; gate on, output enabled, triangle waveform
1504
 
1505
        move.l  #8000000,d0                     ; delay a couple of seconds
1506
Beep1:
1507
        sub.l   #1,d0
1508
        bne             Beep1
1509
        clr.w   PSG_CTRL0                               ; shut off the tone
1510
        move.w  #0,PSG_MASTVOL
1511
        rts
1512
 
1513
;------------------------------------------------------------------------------
1514
;------------------------------------------------------------------------------
1515
;
1516
ReadTemp:
1517
        move.w  #0x5151,d0              ; start conversion command
1518
        move.w  d0,TMPPMOD              ;
1519
rdtmp1:
1520
        btst    #7,TMPPMOD+3    ; is transfer done ?
1521
        bne             rdtmp1
1522
 
1523
;       clr.l   d0
1524
;       move.l  d0,-(a7)                ; create a space for error code
1525
;       lea             (a7),a1
1526
;       move.l  #1000,d1                ; delay 1000 ms (1 s)
1527
;       move.l  #AOS_DELAY,d0
1528
;       trap    #1
1529
;       move.l  (a7)+,d0                ; pop error code
1530
 
1531
        ; delay 1 second
1532
        move.l  #8000000,d0
1533
rdtmp2:
1534
        subi.l  #1,d0
1535
        bne             rdtmp2
1536
 
1537
        move.w  #0xACAC,d0              ; read config reg
1538
        move.w  d0,TMPPMOD
1539
rdtmp4:
1540
        btst    #7,TMPPMOD+3
1541
        bne             rdtmp4
1542
        move.w  TMPPMOD+2,d0
1543
        swap    d0
1544
 
1545
        move.w  #0xAAAA,d0              ; issue read temp command
1546
        move.w  d0,TMPPMOD
1547
rdtmp3:
1548
        btst    #7,TMPPMOD+3    ; is transfer done ?
1549
        bne             rdtmp3
1550
        move.w  TMPPMOD+2,d0    ; read the temp
1551
        rts
1552
 
1553
 
1554
DisplayDecNumber:
1555
        movem.l d0/d1/a1/a5,-(a7)
1556
        move.l  #scratch1,a5
1557
        move.l  d1,d0
1558
        bsr             HEX2DEC
1559
        move.l  #scratch1,a1
1560
        bsr     DisplayString
1561
        movem.l (a7)+,d0/d1/a1/a5
1562
        rts
1563
 
1564
;------------------------------------------------------------------------------
1565
;------------------------------------------------------------------------------
1566
;
1567
DisplayHexNumber:
1568
        movem.l d0/d2/d3,-(a7)
1569
        move.w  #7,d2           ; number-1 of digits to display
1570
disphnum1:
1571
        move.b  d1,d0           ; get digit into d0.b
1572
        andi.w  #0x0f,d0
1573
        cmpi.w  #0x09,d0
1574
        bls             disphnum2
1575
        addi.w  #0x7,d0
1576
disphnum2:
1577
        addi.w  #0x130,d0       ; convert to display char
1578
        move.w  d2,d3           ; char count into d3
1579
        asl.w   #1,d3           ; scale * 2
1580
        move.w  d0,(a1,d3.w)
1581
        ror.l   #4,d1           ; rot to next digit
1582
        dbeq    d2,disphnum1
1583
        movem.l (a7)+,d0/d2/d3
1584
        rts
1585
 
1586
;===============================================================================
1587
;    Perform ram test. (Uses checkerboard testing).
1588
;
1589
;    Return address must be stored in a3 since the stack cannot be used (it
1590
; would get overwritten in test). Note this routine uses no ram at all.
1591
;===============================================================================
1592
ramtest:
1593
        movea.l #8,a0
1594
        move.l #0xaaaa5555,d0
1595
;-----------------------------------------------------------
1596
;   Write checkerboard pattern to ram then read it back to
1597
; find the highest usable ram address (maybe). This address
1598
; must be lower than the start of the rom (0xe00000).
1599
;-----------------------------------------------------------
1600
        lea             TEXTSCR+20,a1
1601
ramtest1:
1602
        move.l  d0,(a0)
1603
        cmp.l   (a0)+,d0
1604
        bne.s   ramtest6
1605
        move.l  a0,d1
1606
        tst.w   d1
1607
        bne             rmtst1
1608
        jsr             DisplayHexNumber
1609
rmtst1:
1610
        cmpa.l  #0xFFFFFC,a0
1611
        blo.s   ramtest1
1612
;------------------------------------------------------
1613
;   Save maximum useable address for later comparison.
1614
;------------------------------------------------------
1615
ramtest6:
1616
        movea.l a0,a2
1617
        movea.l #8,a0
1618
;--------------------------------------------
1619
;   Read back checkerboard pattern from ram.
1620
;--------------------------------------------
1621
ramtest2:
1622
        move.l (a0)+,d0
1623
        move.l  a0,d1
1624
        tst.w   d1
1625
        bne             rmtst2
1626
        jsr             DisplayHexNumber
1627
rmtst2:
1628
        cmpi.l  #0xaaaa5555,d0
1629
        beq.s   ramtest2
1630
;---------------------------------------
1631
;   Check for matching maximum address.
1632
;---------------------------------------
1633
        cmpa.l a0,a2
1634
        bne.s ramtest7
1635
;---------------------------------------------------
1636
;   The following section does the same test except
1637
; with the checkerboard order switched around.
1638
;---------------------------------------------------
1639
ramtest3:
1640
        movea.l #8,a0
1641
        move.l  #0x5555aaaa,d0
1642
ramtest4:
1643
        move.l  d0,(a0)
1644
        cmp.l   (a0)+,d0
1645
        bne.s   ramtest8
1646
        move.l  a0,d1
1647
        tst.w   d1
1648
        bne     rmtst3
1649
        jsr             DisplayHexNumber
1650
rmtst3:
1651
        cmpa.l  #0xFFFFFC,a0
1652
        blo.s   ramtest4
1653
ramtest8:
1654
        movea.l a0,a2
1655
        movea.l #8,a0
1656
ramtest5:
1657
        move.l  (a0)+,d0
1658
        move.l  a0,d1
1659
        tst.w   d1
1660
        bne             rmtst4
1661
        jsr             DisplayHexNumber
1662
rmtst4:
1663
        cmpi.l  #0x5555aaaa,d0
1664
        beq.s   ramtest5
1665
        cmpa.l  a0,a2
1666
        bne.s   ramtest7
1667
;---------------------------------------------------
1668
;   Save last ram address in end of memory pointer.
1669
;---------------------------------------------------
1670
        move.l a0,memend
1671
;-----------------------------------
1672
;   Create very first memory block.
1673
;-----------------------------------
1674
        suba.l  #12,a0
1675
        move.l  a0,0x0404
1676
        move.l  #0x46524545,0x0400
1677
        move.l  #0x408,0x408                    ; point back-link to self
1678
        jmp     (a3)
1679
;----------------------------------
1680
; Error in ram - go no farther.
1681
;----------------------------------
1682
ramtest7:
1683
                jmp     (a3)
1684
        bra.s   ramtest7
1685
 
1686
AddressError:
1687
        movem.l a0/a1/d0/d1/d2/d3,-(a7)
1688
        lea             MSG_ADDRESS_ERROR,a1
1689
        jsr             DisplayString
1690
        movem.l (a7)+,a0/a1/d0/d1/d2/d3
1691
        rte
1692
BusError:
1693
        movem.l a0/a1/d0/d1/d2/d3,-(a7)
1694
        lea             MSG_BUS_ERROR,a1
1695
        jsr             DisplayString
1696
        movem.l (a7)+,a0/a1/d0/d1/d2/d3
1697
        rte
1698
IllegalInstruction:
1699
        movem.l a0/a1/d0/d1/d2/d3,-(a7)
1700
        lea             MSG_ILLEGAL_INSN,a1
1701
        jsr             DisplayString
1702
        movem.l (a7)+,a0/a1/d0/d1/d2/d3
1703
        rte
1704
 
1705
MSG_ADDRESS_ERROR:
1706
        dc.b    "Address error",0
1707
MSG_BUS_ERROR:
1708
        dc.b    "Bus error",0
1709
MSG_ILLEGAL_INSN:
1710
        dc.b    "Illegal instruction",0
1711
MSG_DIVIDE_BY_ZERO:
1712
        dc.b    "Divide by zero",0
1713
;
1714
 
1715
;*****************************************************************
1716
;                                                                *
1717
;               Tiny BASIC for the Motorola MC68000              *
1718
;                                                                *
1719
; Derived from Palo Alto Tiny BASIC as published in the May 1976 *
1720
; issue of Dr. Dobb's Journal.  Adapted to the 68000 by:         *
1721
;       Gordon Brandly                                           *
1722
;       12147 - 51 Street                                        *
1723
;       Edmonton AB  T5W 3G8                                     *
1724
;       Canada                                                   *
1725
;       (updated mailing address for 1996)                       *
1726
;                                                                *
1727
; This version is for MEX68KECB Educational Computer Board I/O.  *
1728
;                                                                *
1729
;*****************************************************************
1730
;    Copyright (C) 1984 by Gordon Brandly. This program may be   *
1731
;    freely distributed for personal use only. All commercial    *
1732
;                      rights are reserved.                      *
1733
;*****************************************************************
1734
 
1735
; Vers. 1.0  1984/7/17  - Original version by Gordon Brandly
1736
;       1.1  1984/12/9  - Addition of '$' print term by Marvin Lipford
1737
;       1.2  1985/4/9   - Bug fix in multiply routine by Rick Murray
1738
 
1739
;       OPT     FRS,BRS         forward ref.'s & branches default to short
1740
 
1741
BUFLEN  EQU     80      ;       length of keyboard input buffer
1742
 
1743
;*
1744
;* Internal variables follow:
1745
;*
1746
        BSS
1747
        ORG             0x600
1748
RANPNT:
1749
        DC.L    START   ;       random number pointer
1750
CURRNT:
1751
        DC.L    1               ;Current line pointer
1752
STKGOS:
1753
        DC.L    1               ;Saves stack pointer in 'GOSUB'
1754
STKINP:
1755
        DC.L    1               ;Saves stack pointer during 'INPUT'
1756
LOPVAR:
1757
        DC.L    1               ;'FOR' loop save area
1758
LOPINC:
1759
        DC.L    1               ;increment
1760
LOPLMT:
1761
        DC.L    1               ;limit
1762
LOPLN:
1763
        DC.L    1               ;line number
1764
LOPPT:
1765
        DC.L    1               ;text pointer
1766
TXTUNF:
1767
        DC.L    1               ;points to unfilled text area
1768
VARBGN:
1769
        DC.L    1               ;points to variable area
1770
STKLMT:
1771
        DC.L    1               ;holds lower limit for stack growth
1772
BUFFER:
1773
        FILL.B  BUFLEN,0x00     ;       Keyboard input buffer
1774
 
1775
TXT     EQU     $               ;Beginning of program area
1776
 
1777
        CODE
1778
        even
1779
        ORG     0xFFFF2400
1780
;*
1781
;* Standard jump table. You can change these addresses if you are
1782
;* customizing this interpreter for a different environment.
1783
;*
1784
START:
1785
                BRA.L   CSTART          ;Cold Start entry point
1786
GOWARM: BRA.L   WSTART          ;Warm Start entry point
1787
GOOUT:  BRA.L   OUTC            ;Jump to character-out routine
1788
GOIN:   BRA.L   INC             ;Jump to character-in routine
1789
GOAUXO: BRA.L   AUXOUT          ;Jump to auxiliary-out routine
1790
GOAUXI: BRA.L   AUXIN           ;Jump to auxiliary-in routine
1791
GOBYE:  BRA.L   BYEBYE          ;Jump to monitor, DOS, etc.
1792
;*
1793
;* Modifiable system constants:
1794
;*
1795
; Give Tiny Basic 3MB
1796
TXTBGN  DC.L    0xC00000        ;beginning of program memory
1797
ENDMEM  DC.L    0xF00000        ;       end of available memory
1798
;*
1799
;* The main interpreter starts here:
1800
;*
1801
CSTART:
1802
        LEA             START,A0
1803
        MOVE.L  A0,RANPNT
1804
        MOVE.L  ENDMEM,SP       ;initialize stack pointer
1805
        LEA             INITMSG,A6      ;tell who we are
1806
        BSR.L   PRMESG
1807
        MOVE.L  TXTBGN,TXTUNF   ;init. end-of-program pointer
1808
        MOVE.L  ENDMEM,D0       ;get address of end of memory
1809
        SUB.L   #2048,D0        ;reserve 2K for the stack
1810
        MOVE.L  D0,STKLMT
1811
        SUB.L   #4104,D0        ;reserve variable area (27 long words)
1812
        MOVE.L  D0,VARBGN
1813
WSTART:
1814
        CLR.L   D0              ;initialize internal variables
1815
        MOVE.L  D0,LOPVAR
1816
        MOVE.L  D0,STKGOS
1817
        MOVE.L  D0,CURRNT       ;current line number pointer = 0
1818
        MOVE.L  ENDMEM,SP       ;init S.P. again, just in case
1819
        LEA     OKMSG,A6        ;display "OK"
1820
        BSR.L   PRMESG
1821
ST3:
1822
        MOVE.B  #'>',D0  ;       Monitor with a '>' and
1823
        BSR.L   GETLN   ;       read a line.
1824
        BSR.L   TOUPBUF ;       convert to upper case
1825
        MOVE.L  A0,A4   ;       save pointer to end of line
1826
        LEA     BUFFER,A0       ;point to the beginning of line
1827
        BSR.L   TSTNUM  ;       is there a number there?
1828
        BSR.L   IGNBLK  ;       skip trailing blanks
1829
        TST     D1              ;does line no. exist? (or nonzero?)
1830
        BEQ.L   DIRECT  ;       if not, it's a direct statement
1831
        CMP.L   #0xFFFF,D1      ;see if line no. is <= 16 bits
1832
        BCC.L   QHOW            ;if not, we've overflowed
1833
        MOVE.B  D1,-(A0)        ;store the binary line no.
1834
        ROR     #8,D1           ;(Kludge to store a word on a
1835
        MOVE.B  D1,-(A0)        ;possible byte boundary)
1836
        ROL     #8,D1
1837
        BSR.L   FNDLN   ;       find this line in save area
1838
        MOVE.L  A1,A5   ;       save possible line pointer
1839
        BNE     ST4                             ;       if not found, insert
1840
        BSR.L   FNDNXT          ;find the next line (into A1)
1841
        MOVE.L  A5,A2           ;pointer to line to be deleted
1842
        MOVE.L  TXTUNF,A3       ;points to top of save area
1843
        BSR.L   MVUP            ;move up to delete
1844
        MOVE.L  A2,TXTUNF       ;update the end pointer
1845
ST4:
1846
        MOVE.L  A4,D0           ;calculate the length of new line
1847
        SUB.L   A0,D0
1848
        CMP.L   #3,D0           ;is it just a line no. & CR?
1849
        BEQ     ST3                             ;if so, it was just a delete
1850
        MOVE.L  TXTUNF,A3       ;compute new end
1851
        MOVE.L  A3,A6
1852
        ADD.L   D0,A3
1853
        MOVE.L  VARBGN,D0       ;see if there's enough room
1854
        CMP.L   A3,D0
1855
        BLS.L   QSORRY          ;if not, say so
1856
        MOVE.L  A3,TXTUNF       ;if so, store new end position
1857
        MOVE.L  A6,A1           ;points to old unfilled area
1858
        MOVE.L  A5,A2           ;points to beginning of move area
1859
        BSR.L   MVDOWN          ;move things out of the way
1860
        MOVE.L  A0,A1           ;set up to do the insertion
1861
        MOVE.L  A5,A2
1862
        MOVE.L  A4,A3
1863
        BSR.L   MVUP            ;do it
1864
        BRA     ST3             ;go back and get another line
1865
 
1866
;*
1867
;*******************************************************************
1868
;*
1869
;* *** Tables *** DIRECT *** EXEC ***
1870
;*
1871
;* This section of the code tests a string against a table. When
1872
;* a match is found, control is transferred to the section of
1873
;* code according to the table.
1874
;*
1875
;* At 'EXEC', A0 should point to the string, A1 should point to
1876
;* the character table, and A2 should point to the execution
1877
;* table. At 'DIRECT', A0 should point to the string, A1 and
1878
;* A2 will be set up to point to TAB1 and TAB1.1, which are
1879
;* the tables of all direct and statement commands.
1880
;*
1881
;* A '.' in the string will terminate the test and the partial
1882
;* match will be considered as a match, e.g. 'P.', 'PR.','PRI.',
1883
;* 'PRIN.', or 'PRINT' will all match 'PRINT'.
1884
;*
1885
;* There are two tables: the character table and the execution
1886
;* table. The character table consists of any number of text items.
1887
;* Each item is a string of characters with the last character's
1888
;* high bit set to one. The execution table holds a 16-bit
1889
;* execution addresses that correspond to each entry in the
1890
;* character table.
1891
;*
1892
;* The end of the character table is a 0 byte which corresponds
1893
;* to the default routine in the execution table, which is
1894
;* executed if none of the other table items are matched.
1895
;*
1896
;* Character-matching tables:
1897
TAB1:
1898
        DC.B    'LIS',('T'+0x80) ;        Direct commands
1899
        DC.B    'LOA',('D'+0x80)
1900
        DC.B    'NE',('W'+0x80)
1901
        DC.B    'RU',('N'+0x80)
1902
        DC.B    'SAV',('E'+0x80)
1903
        DC.B    'CL',('S'+0x80)
1904
TAB2:
1905
        DC.B    'NEX',('T'+0x80)  ;       Direct / statement
1906
        DC.B    'LE',('T'+0x80)
1907
        DC.B    'I',('F'+0x80)
1908
        DC.B    'GOT',('O'+0x80)
1909
        DC.B    'GOSU',('B'+0x80)
1910
        DC.B    'RETUR',('N'+0x80)
1911
        DC.B    'RE',('M'+0x80)
1912
        DC.B    'FO',('R'+0x80)
1913
        DC.B    'INPU',('T'+0x80)
1914
        DC.B    'PRIN',('T'+0x80)
1915
        DC.B    'POK',('E'+0x80)
1916
        DC.B    'STO',('P'+0x80)
1917
        DC.B    'BY',('E'+0x80)
1918
        DC.B    'CAL',('L'+0x80)
1919
        DC.B    'LIN',('E'+0x80)
1920
        DC.B    'POIN',('T'+0x80)
1921
        DC.B    'PENCOLO',('R'+0x80)
1922
        DC.B    'FILLCOLO',('R'+0x80)
1923
        DC.B    0
1924
TAB4:
1925
        DC.B    'PEE',('K'+0x80)   ;      Functions
1926
        DC.B    'RN',('D'+0x80)
1927
        DC.B    'AB',('S'+0x80)
1928
        DC.B    'SIZ',('E'+0x80)
1929
        DC.B    'TIC',('K'+0x80)
1930
        DC.B    'TEM',('P'+0x80)
1931
        DC.B    'SG',('N'+0x80)
1932
        DC.B    0
1933
TAB5:
1934
        DC.B    'T',('O'+0x80)      ;     "TO" in "FOR"
1935
        DC.B    0
1936
TAB6:
1937
        DC.B    'STE',('P'+0x80)     ;    "STEP" in "FOR"
1938
        DC.B    0
1939
TAB8:
1940
        DC.B    '>',('='+0x80)        ;   Relational operators
1941
        DC.B    '<',('>'+0x80)
1942
        DC.B    ('>'+0x80)
1943
        DC.B    ('='+0x80)
1944
        DC.B    '<',('='+0x80)
1945
        DC.B    ('<'+0x80)
1946
        DC.B    0
1947
;       DC.B    0        ;<- for aligning on a word boundary
1948
 
1949
        even
1950
 
1951
;* Execution address tables:
1952
TAB1_1:
1953
        DC.W    LIST_                   ;Direct commands
1954
        DC.W    LOAD
1955
        DC.W    NEW
1956
        DC.W    RUN
1957
        DC.W    SAVE
1958
        DC.W    CLS
1959
TAB2_1:
1960
        DC.W    NEXT                    ;Direct / statement
1961
        DC.W    LET
1962
        DC.W    IF
1963
        DC.W    GOTO
1964
        DC.W    GOSUB
1965
        DC.W    RETURN
1966
        DC.W    REM
1967
        DC.W    FOR
1968
        DC.W    INPUT
1969
        DC.W    PRINT
1970
        DC.W    POKE
1971
        DC.W    STOP_
1972
        DC.W    GOBYE
1973
        DC.W    CALL
1974
        DC.W    LINE
1975
        DC.W    POINT
1976
        DC.W    PENCOLOR
1977
        DC.W    FILLCOLOR
1978
        DC.W    DEFLT
1979
TAB4_1:
1980
        DC.W    PEEK                    ;Functions
1981
        DC.W    RND
1982
        DC.W    ABS
1983
        DC.W    SIZE_
1984
        DC.W    TICK
1985
        DC.W    TEMP
1986
        DC.W    SGN
1987
        DC.W    XP40
1988
TAB5_1:
1989
        DC.W    FR1             ;       "TO" in "FOR"
1990
        DC.W    QWHAT
1991
TAB6_1:
1992
        DC.W    FR2             ;       "STEP" in "FOR"
1993
        DC.W    FR3
1994
TAB8_1:
1995
        DC.W    XP11;   >=              Relational operators
1996
        DC.W    XP12    ;<>
1997
        DC.W    XP13    ;>
1998
        DC.W    XP15    ;=
1999
        DC.W    XP14    ;<=
2000
        DC.W    XP16    ;<
2001
        DC.W    XP17
2002
;*
2003
DIRECT:
2004
        LEA     TAB1,A1
2005
        LEA     TAB1_1,A2
2006
EXEC:
2007
        BSR.L   IGNBLK;         ignore leading blanks
2008
        MOVE.L  A0,A3           ;save the pointer
2009
        CLR.B   D2              ;clear match flag
2010
EXLP:
2011
        MOVE.B  (A0)+,D0;       get the program character
2012
        MOVE.B  (A1),D1         ;get the table character
2013
        BNE     EXNGO           ;If end of table,
2014
        MOVE.L  A3,A0   ;;      restore the text pointer and...
2015
        BRA     EXGO            ;execute the default.
2016
EXNGO:
2017
        MOVE.B  D0,D3   ;       Else check for period...
2018
        AND.B   D2,D3           ;and a match.
2019
        CMP.B   #'.',D3
2020
        BEQ     EXGO            ;if so, execute
2021
        AND.B   #0x7F,D1 ;      ignore the table's high bit
2022
        CMP.B   D0,D1   ;       is there a match?
2023
        BEQ     EXMAT
2024
        ADDQ.L  #2,A2   ;       if not, try the next entry
2025
        MOVE.L  A3,A0   ;       reset the program pointer
2026
        CLR.B   D2              ;sorry, no match
2027
EX1:
2028
        TST.B   (A1)+   ;       get to the end of the entry
2029
        BPL     EX1
2030
        BRA     EXLP            ;back for more matching
2031
EXMAT:
2032
        MOVEQ   #-1,D2;         we've got a match so far
2033
        TST.B   (A1)+   ;       end of table entry?
2034
        BPL     EXLP            ;if not, go back for more
2035
EXGO:
2036
        LEA             0xFFFF0000,A3   ;       execute the appropriate routine
2037
        move.w  (a2),a2
2038
        JMP     (A3,A2.W)
2039
 
2040
CLS:
2041
        jsr             ClearScreen
2042
        clr.w   CursorRow
2043
        clr.w   CursorCol
2044
        bra             WSTART
2045
;*
2046
;*******************************************************************
2047
;*
2048
;* What follows is the code to execute direct and statement
2049
;* commands. Control is transferred to these points via the command
2050
;* table lookup code of 'DIRECT' and 'EXEC' in the last section.
2051
;* After the command is executed, control is transferred to other
2052
;* sections as follows:
2053
;*
2054
;* For 'LIST', 'NEW', and 'STOP': go back to the warm start point.
2055
;* For 'RUN': go execute the first stored line if any; else go
2056
;* back to the warm start point.
2057
;* For 'GOTO' and 'GOSUB': go execute the target line.
2058
;* For 'RETURN' and 'NEXT'; go back to saved return line.
2059
;* For all others: if 'CURRNT' is 0, go to warm start; else go;
2060
;* execute next command. (This is done in 'FINISH'.)
2061
;*
2062
;*******************************************************************
2063
;*
2064
;* *** NEW *** STOP *** RUN (& friends) *** GOTO ***
2065
;*
2066
;* 'NEW' sets TXTUNF to point to TXTBGN
2067
;*
2068
;* 'STOP' goes back to WSTART
2069
;*
2070
;* 'RUN' finds the first stored line, stores its address
2071
;* in CURRNT, and starts executing it. Note that only those
2072
;* commands in TAB2 are legal for a stored program.
2073
;*
2074
;* There are 3 more entries in 'RUN':
2075
;* 'RUNNXL' finds next line, stores it's address and executes it.
2076
;* 'RUNTSL' stores the address of this line and executes it.
2077
;* 'RUNSML' continues the execution on same line.
2078
;*
2079
;* 'GOTO expr' evaluates the expression, finds the target
2080
;* line, and jumps to 'RUNTSL' to do it.
2081
;*
2082
NEW:
2083
        BSR.L   ENDCHK
2084
        MOVE.L  TXTBGN,TXTUNF   ;set the end pointer
2085
 
2086
STOP_:
2087
        BSR.L   ENDCHK
2088
        BRA     WSTART
2089
 
2090
RUN:
2091
        BSR.L   ENDCHK
2092
        MOVE.L  TXTBGN,A0       ;set pointer to beginning
2093
        MOVE.L  A0,CURRNT
2094
 
2095
RUNNXL:
2096
        TST.L   CURRNT  ;       executing a program?
2097
        BEQ.L   WSTART          ;if not, we've finished a direct stat.
2098
        CLR.L   D1              ;else find the next line number
2099
        MOVE.L  A0,A1
2100
        BSR.L   FNDLNP
2101
        BCS     WSTART          ;if we've fallen off the end, stop
2102
 
2103
RUNTSL:
2104
        MOVE.L  A1,CURRNT       ;set CURRNT to point to the line no.
2105
        MOVE.L  A1,A0           ;set the text pointer to
2106
        ADDQ.L  #2,A0           ;the start of the line text
2107
 
2108
RUNSML:
2109
        BSR.L   CHKIO   ;       see if a control-C was pressed
2110
        LEA     TAB2,A1         ;find command in TAB2
2111
        LEA     TAB2_1,A2
2112
        BRA     EXEC            ;and execute it
2113
 
2114
GOTO:
2115
        BSR.L   EXPR    ;       evaluate the following expression
2116
        BSR.L   ENDCHK          ;must find end of line
2117
        MOVE.L  D0,D1
2118
        BSR.L   FNDLN           ;find the target line
2119
        BNE.L   QHOW            ;no such line no.
2120
        BRA     RUNTSL          ;go do it
2121
 
2122
;*
2123
;*******************************************************************
2124
;*
2125
;* *** LIST *** PRINT ***
2126
;*
2127
;* LIST has two forms:
2128
;* 'LIST' lists all saved lines
2129
;* 'LIST #' starts listing at the line #
2130
;* Control-S pauses the listing, control-C stops it.
2131
;*
2132
;* PRINT command is 'PRINT ....:' or 'PRINT ....'
2133
;* where '....' is a list of expressions, formats, back-arrows,
2134
;* and strings. These items a separated by commas.
2135
;*
2136
;* A format is a pound sign followed by a number.  It controls
2137
;* the number of spaces the value of an expression is going to
2138
;* be printed in.  It stays effective for the rest of the print
2139
;* command unless changed by another format.  If no format is
2140
;* specified, 11 positions will be used.
2141
;*
2142
;* A string is quoted in a pair of single- or double-quotes.
2143
;*
2144
;* An underline (back-arrow) means generate a  without a 
2145
;*
2146
;* A  is generated after the entire list has been printed
2147
;* or if the list is empty.  If the list ends with a semicolon,
2148
;* however, no  is generated.
2149
;*
2150
 
2151
LIST_:
2152
        BSR.L   TSTNUM  ;       see if there's a line no.
2153
        BSR.L   ENDCHK          ;if not, we get a zero
2154
        BSR.L   FNDLN           ;find this or next line
2155
LS1:
2156
        BCS     WSTART          ;warm start if we passed the end
2157
        BSR.L   PRTLN   ;       print the line
2158
        BSR.L   CHKIO   ;       check for listing halt request
2159
        BEQ     LS3
2160
        CMP.B   #CTRLS,D0       ;pause the listing?
2161
        BNE     LS3
2162
LS2:
2163
        BSR.L   CHKIO           ;if so, wait for another keypress
2164
        BEQ     LS2
2165
LS3:
2166
        BSR.L   FNDLNP          ;find the next line
2167
        BRA     LS1
2168
 
2169
PRINT:
2170
        MOVE    #11,D4  ;       D4 = number of print spaces
2171
        BSR.L   TSTC            ;if null list and ":"
2172
        DC.B    ':',PR2-$
2173
        BSR.L   CRLF1           ;give CR-LF and continue
2174
        BRA     RUNSML          ;execution on the same line
2175
PR2:
2176
        BSR.L   TSTC            ;if null list and 
2177
        DC.B    CR,PR0-$
2178
        BSR.L   CRLF1           ;also give CR-LF and
2179
        BRA     RUNNXL          ;execute the next line
2180
PR0:
2181
        BSR.L   TSTC            ;else is it a format?
2182
        DC.B    '#',PR1-$
2183
        BSR.L   EXPR            ;yes, evaluate expression
2184
        MOVE    D0,D4           ;and save it as print width
2185
        BRA     PR3             ;look for more to print
2186
PR1:
2187
        BSR.L   TSTC            ;is character expression? (MRL)
2188
        DC.B    '$',PR4-$
2189
        BSR.L   EXPR            ;yep. Evaluate expression (MRL)
2190
        BSR     GOOUT           ;print low byte (MRL)
2191
        BRA     PR3             ;look for more. (MRL)
2192
PR4:
2193
        BSR.L   QTSTG   ;       is it a string?
2194
        BRA.S   PR8             ;if not, must be an expression
2195
PR3:
2196
        BSR.L   TSTC    ;       if ",", go find next
2197
        DC.B    ',',PR6-$
2198
        BSR.L   FIN             ;in the list.
2199
        BRA     PR0
2200
PR6:
2201
        BSR.L   CRLF1   ;       list ends here
2202
        BRA     FINISH
2203
PR8:
2204
        MOVE    D4,-(SP)        ;save the width value
2205
        BSR.L   EXPR            ;evaluate the expression
2206
        MOVE    (SP)+,D4        ;restore the width
2207
        MOVE.L  D0,D1
2208
        BSR.L   PRTNUM          ;print its value
2209
        BRA     PR3             ;more to print?
2210
 
2211
FINISH:
2212
        BSR.L   FIN     ;       Check end of command
2213
        BRA.L   QWHAT   ;       print "What?" if wrong
2214
 
2215
;*
2216
;*******************************************************************
2217
;*
2218
;* *** GOSUB *** & RETURN ***
2219
;*
2220
;* 'GOSUB expr:' or 'GOSUB expr' is like the 'GOTO' command,
2221
;* except that the current text pointer, stack pointer, etc. are
2222
;* saved so that execution can be continued after the subroutine
2223
;* 'RETURN's.  In order that 'GOSUB' can be nested (and even
2224
;* recursive), the save area must be stacked.  The stack pointer
2225
;* is saved in 'STKGOS'.  The old 'STKGOS' is saved on the stack.
2226
;* If we are in the main routine, 'STKGOS' is zero (this was done
2227
;* in the initialization section of the interpreter), but we still
2228
;* save it as a flag for no further 'RETURN's.
2229
;*
2230
;* 'RETURN' undoes everything that 'GOSUB' did, and thus
2231
;* returns the execution to the command after the most recent
2232
;* 'GOSUB'.  If 'STKGOS' is zero, it indicates that we never had
2233
;* a 'GOSUB' and is thus an error.
2234
;*
2235
GOSUB:
2236
        BSR.L   PUSHA   ;       save the current 'FOR' parameters
2237
        BSR.L   EXPR            ;get line number
2238
        MOVE.L  A0,-(SP)        ;save text pointer
2239
        MOVE.L  D0,D1
2240
        BSR.L   FNDLN           ;find the target line
2241
        BNE.L   AHOW            ;if not there, say "How?"
2242
        MOVE.L  CURRNT,-(SP)    ;found it, save old 'CURRNT'...
2243
        MOVE.L  STKGOS,-(SP)    ;and 'STKGOS'
2244
        CLR.L   LOPVAR          ;load new values
2245
        MOVE.L  SP,STKGOS
2246
        BRA     RUNTSL
2247
 
2248
RETURN:
2249
        BSR.L   ENDCHK  ;       there should be just a 
2250
        MOVE.L  STKGOS,D1       ;get old stack pointer
2251
        BEQ.L   QWHAT           ;if zero, it doesn't exist
2252
        MOVE.L  D1,SP           ;else restore it
2253
        MOVE.L  (SP)+,STKGOS    ;and the old 'STKGOS'
2254
        MOVE.L  (SP)+,CURRNT    ;and the old 'CURRNT'
2255
        MOVE.L  (SP)+,A0        ;and the old text pointer
2256
        BSR.L   POPA            ;and the old 'FOR' parameters
2257
        BRA     FINISH          ;and we are back home
2258
 
2259
;*
2260
;*******************************************************************
2261
;*
2262
;* *** FOR *** & NEXT ***
2263
;*
2264
;* 'FOR' has two forms:
2265
;* 'FOR var=exp1 TO exp2 STEP exp1' and 'FOR var=exp1 TO exp2'
2266
;* The second form means the same thing as the first form with a
2267
;* STEP of positive 1.  The interpreter will find the variable 'var'
2268
;* and set its value to the current value of 'exp1'.  It also
2269
;* evaluates 'exp2' and 'exp1' and saves all these together with
2270
;* the text pointer, etc. in the 'FOR' save area, which consisits of
2271
;* 'LOPVAR', 'LOPINC', 'LOPLMT', 'LOPLN', and 'LOPPT'.  If there is
2272
;* already something in the save area (indicated by a non-zero
2273
;* 'LOPVAR'), then the old save area is saved on the stack before
2274
;* the new values are stored.  The interpreter will then dig in the
2275
;* stack and find out if this same variable was used in another
2276
;* currently active 'FOR' loop.  If that is the case, then the old
2277
;* 'FOR' loop is deactivated. (i.e. purged from the stack)
2278
;*
2279
;* 'NEXT var' serves as the logical (not necessarily physical) end
2280
;* of the 'FOR' loop.  The control variable 'var' is checked with
2281
;* the 'LOPVAR'.  If they are not the same, the interpreter digs in
2282
;* the stack to find the right one and purges all those that didn't
2283
;* match.  Either way, it then adds the 'STEP' to that variable and
2284
;* checks the result with against the limit value.  If it is within
2285
;* the limit, control loops back to the command following the
2286
;* 'FOR'.  If it's outside the limit, the save area is purged and
2287
;* execution continues.
2288
;*
2289
FOR:
2290
        BSR.L   PUSHA           ;save the old 'FOR' save area
2291
        BSR.L   SETVAL          ;set the control variable
2292
        MOVE.L  A6,LOPVAR       ;save its address
2293
        LEA     TAB5,A1         ;use 'EXEC' to test for 'TO'
2294
        LEA     TAB5_1,A2
2295
        BRA     EXEC
2296
FR1:
2297
        BSR.L   EXPR            ;evaluate the limit
2298
        MOVE.L  D0,LOPLMT       ;save that
2299
        LEA     TAB6,A1         ;use 'EXEC' to look for the
2300
        LEA     TAB6_1,A2       ;word 'STEP'
2301
        BRA     EXEC
2302
FR2:
2303
        BSR.L   EXPR    ;       found it, get the step value
2304
        BRA     FR4
2305
FR3:
2306
        MOVEQ   #1,D0   ;       not found, step defaults to 1
2307
FR4:
2308
        MOVE.L  D0,LOPINC       ;save that too
2309
FR5:
2310
        MOVE.L  CURRNT,LOPLN    ;save address of current line number
2311
        MOVE.L  A0,LOPPT        ;and text pointer
2312
        MOVE.L  SP,A6           ;dig into the stack to find 'LOPVAR'
2313
        BRA     FR7
2314
FR6:
2315
        ADD.L   #20,A6          ;look at next stack frame
2316
FR7:
2317
        MOVE.L  (A6),D0         ;is it zero?
2318
        BEQ     FR8             ;if so, we're done
2319
        CMP.L   LOPVAR,D0       ;same as current LOPVAR?
2320
        BNE     FR6             ;nope, look some more
2321
        MOVE.L  SP,A2   ;       Else remove 5 long words from...
2322
        MOVE.L  A6,A1   ;       inside the stack.
2323
        LEA     20,A3
2324
        ADD.L   A1,A3
2325
        BSR.L   MVDOWN
2326
        MOVE.L  A3,SP   ;       set the SP 5 long words up
2327
FR8:
2328
        BRA     FINISH          ;and continue execution
2329
 
2330
NEXT:
2331
        BSR.L   TSTV;           get address of variable
2332
        BCS.L   QWHAT   ;       if no variable, say "What?"
2333
        MOVE.L  D0,A1   ;       save variable's address
2334
NX0:
2335
        MOVE.L  LOPVAR,D0;      If 'LOPVAR' is zero, we never...
2336
        BEQ.L   QWHAT   ;       had a FOR loop, so say "What?"
2337
        CMP.L   D0,A1   ;;      else we check them
2338
        BEQ     NX3     ;       OK, they agree
2339
        BSR.L   POPA    ;       nope, let's see the next frame
2340
        BRA     NX0
2341
NX3:
2342
        MOVE.L  (A1),D0 ;       get control variable's value
2343
        ADD.L   LOPINC,D0;      add in loop increment
2344
        BVS.L   QHOW    ;       say "How?" for 32-bit overflow
2345
        MOVE.L  D0,(A1) ;       save control variable's new value
2346
        MOVE.L  LOPLMT,D1;      get loop's limit value
2347
        TST.L   LOPINC
2348
        BPL     NX1     ;       branch if loop increment is positive
2349
        EXG     D0,D1
2350
NX1:
2351
        CMP.L   D0,D1;          test against limit
2352
        BLT     NX2;            branch if outside limit
2353
        MOVE.L  LOPLN,CURRNT    ;Within limit, go back to the...
2354
        MOVE.L  LOPPT,A0        ;saved 'CURRNT' and text pointer.
2355
        BRA     FINISH
2356
NX2:
2357
        BSR.L   POPA            ;purge this loop
2358
        BRA     FINISH
2359
 
2360
;*
2361
;*******************************************************************
2362
;*
2363
;* *** REM *** IF *** INPUT *** LET (& DEFLT) ***
2364
;*
2365
;* 'REM' can be followed by anything and is ignored by the
2366
;* interpreter.
2367
;*
2368
;* 'IF' is followed by an expression, as a condition and one or
2369
;* more commands (including other 'IF's) separated by colons.
2370
;* Note that the word 'THEN' is not used.  The interpreter evaluates
2371
;* the expression.  If it is non-zero, execution continues.  If it
2372
;* is zero, the commands that follow are ignored and execution
2373
;* continues on the next line.
2374
;*
2375
;* 'INPUT' is like the 'PRINT' command, and is followed by a list
2376
;* of items.  If the item is a string in single or double quotes,
2377
;* or is an underline (back arrow), it has the same effect as in
2378
;* 'PRINT'.  If an item is a variable, this variable name is
2379
;* printed out followed by a colon, then the interpreter waits for
2380
;* an expression to be typed in.  The variable is then set to the
2381
;* value of this expression.  If the variable is preceeded by a
2382
;* string (again in single or double quotes), the string will be
2383
;* displayed followed by a colon.  The interpreter the waits for an
2384
;* expression to be entered and sets the variable equal to the
2385
;* expression's value.  If the input expression is invalid, the
2386
;* interpreter will print "What?", "How?", or "Sorry" and reprint
2387
;* the prompt and redo the input.  The execution will not terminate
2388
;* unless you press control-C.  This is handled in 'INPERR'.
2389
;*
2390
;* 'LET' is followed by a list of items separated by commas.
2391
;* Each item consists of a variable, an equals sign, and an
2392
;* expression.  The interpreter evaluates the expression and sets
2393
;* the variable to that value.  The interpreter will also handle
2394
;* 'LET' commands without the word 'LET'.  This is done by 'DEFLT'.
2395
;*
2396
REM:
2397
        BRA     IF2             ;skip the rest of the line
2398
 
2399
IF:
2400
        BSR.L   EXPR    ;       evaluate the expression
2401
IF1:
2402
        TST.L   D0              ;is it zero?
2403
        BNE     RUNSML          ;if not, continue
2404
IF2:
2405
        MOVE.L  A0,A1
2406
        CLR.L   D1
2407
        BSR.L   FNDSKP  ;       if so, skip the rest of the line
2408
        BCC     RUNTSL          ;and run the next line
2409
        BRA.L   WSTART  ;       if no next line, do a warm start
2410
 
2411
INPERR:
2412
        MOVE.L  STKINP,SP;      restore the old stack pointer
2413
        MOVE.L  (SP)+,CURRNT;   and old 'CURRNT'
2414
        ADDQ.L  #4,SP
2415
        MOVE.L  (SP)+,A0        ;and old text pointer
2416
 
2417
INPUT:
2418
        MOVE.L  A0,-(SP);       save in case of error
2419
        BSR.L   QTSTG           ;is next item a string?
2420
        BRA.S   IP2             ;nope
2421
        BSR.L   TSTV    ;       yes, but is it followed by a variable?
2422
        BCS     IP4             ;if not, branch
2423
        MOVE.L  D0,A2   ;       put away the variable's address
2424
        BRA     IP3             ;if so, input to variable
2425
IP2:
2426
        MOVE.L  A0,-(SP);       save for 'PRTSTG'
2427
        BSR.L   TSTV    ;       must be a variable now
2428
        BCS.L   QWHAT   ;       "What?" it isn't?
2429
        MOVE.L  D0,A2   ;       put away the variable's address
2430
        MOVE.B  (A0),D2 ;       get ready for 'PRTSTG'
2431
        CLR.B   D0
2432
        MOVE.B  D0,(A0)
2433
        MOVE.L  (SP)+,A1
2434
        BSR.L   PRTSTG  ;       print string as prompt
2435
        MOVE.B  D2,(A0) ;       restore text
2436
IP3:
2437
        MOVE.L  A0,-(SP);       save in case of error
2438
        MOVE.L  CURRNT,-(SP)    ;also save 'CURRNT'
2439
        MOVE.L  #-1,CURRNT      ;flag that we are in INPUT
2440
        MOVE.L  SP,STKINP       ;save the stack pointer too
2441
        MOVE.L  A2,-(SP)        ;save the variable address
2442
        MOVE.B  #':',D0     ;    print a colon first
2443
        BSR.L   GETLN           ;then get an input line
2444
        LEA     BUFFER,A0       ;point to the buffer
2445
        BSR.L   EXPR    ;       evaluate the input
2446
        MOVE.L  (SP)+,A2        ;restore the variable address
2447
        MOVE.L  D0,(A2)         ;save value in variable
2448
        MOVE.L  (SP)+,CURRNT    ;restore old 'CURRNT'
2449
        MOVE.L  (SP)+,A0;       and the old text pointer
2450
IP4:
2451
        ADDQ.L  #4,SP   ;       clean up the stack
2452
        BSR.L   TSTC    ;       is the next thing a comma?
2453
        DC.B    ',',IP5-$
2454
        BRA     INPUT   ;       yes, more items
2455
IP5:
2456
        BRA     FINISH
2457
 
2458
DEFLT:
2459
        CMP.B   #CR,(A0);       empty line is OK
2460
        BEQ     LT1             ;else it is 'LET'
2461
 
2462
LET:
2463
        BSR.L   SETVAL          ;do the assignment
2464
        BSR.L   TSTC            ;check for more 'LET' items
2465
        DC.B    ',',LT1-$
2466
        BRA     LET
2467
LT1:
2468
        BRA     FINISH          ;until we are finished.
2469
 
2470
;*
2471
;*******************************************************************
2472
;*
2473
;* *** LOAD *** & SAVE ***
2474
;*
2475
;* These two commands transfer a program to/from an auxiliary
2476
;* device such as a cassette, another computer, etc.  The program
2477
;* is converted to an easily-stored format: each line starts with
2478
;* a colon, the line no. as 4 hex digits, and the rest of the line.
2479
;* At the end, a line starting with an '@' sign is sent.  This
2480
;* format can be read back with a minimum of processing time by
2481
;* the 68000.
2482
;*
2483
LOAD:
2484
        MOVE.L  TXTBGN,A0       ;set pointer to start of prog. area
2485
        MOVE.B  #CR,D0          ;For a CP/M host, tell it we're ready...
2486
        BSR     GOAUXO          ;by sending a CR to finish PIP command.
2487
LOD1:
2488
        BSR     GOAUXI  ;       look for start of line
2489
        BEQ     LOD1
2490
        CMP.B   #'@',D0  ;       end of program?
2491
        BEQ     LODEND
2492
        CMP.B   #':',D0   ;      if not, is it start of line?
2493
        BNE     LOD1                    ;if not, wait for it
2494
        BSR     GBYTE                   ;get first byte of line no.
2495
        MOVE.B  D1,(A0)+        ;store it
2496
        BSR     GBYTE                   ;get 2nd bye of line no.
2497
        MOVE.B  D1,(A0)+        ;       store that, too
2498
LOD2:
2499
        BSR     GOAUXI  ;       get another text char.
2500
        BEQ     LOD2
2501
        MOVE.B  D0,(A0)+        ;store it
2502
        CMP.B   #CR,D0          ;is it the end of the line?
2503
        BNE     LOD2            ;if not, go back for more
2504
        BRA     LOD1            ;if so, start a new line
2505
LODEND:
2506
        MOVE.L  A0,TXTUNF       ;set end-of program pointer
2507
        BRA     WSTART          ;back to direct mode
2508
 
2509
GBYTE:
2510
        MOVEQ   #1,D2   ;               get two hex characters from auxiliary
2511
        CLR     D1                      ;and store them as a byte in D1
2512
GBYTE1:
2513
        BSR     GOAUXI          ;       get a char.
2514
        BEQ     GBYTE1
2515
        CMP.B   #'A',D0
2516
        BCS     GBYTE2
2517
        SUBQ.B  #7,D0   ;       if greater than 9, adjust
2518
GBYTE2:
2519
        AND.B   #0xF,D0         ;strip ASCII
2520
        LSL.B   #4,D1           ;put nybble into the result
2521
        OR.B    D0,D1
2522
        DBRA    D2,GBYTE1       ;get another char.
2523
        RTS
2524
 
2525
SAVE:
2526
        MOVE.L  TXTBGN,A0;      set pointer to start of prog. area
2527
        MOVE.L  TXTUNF,A1       ;set pointer to end of prog. area
2528
SAVE1:
2529
        MOVE.B  #CR,D0  ;       send out a CR & LF (CP/M likes this)
2530
        BSR     GOAUXO
2531
        MOVE.B  #LF,D0
2532
        BSR     GOAUXO
2533
        CMP.L   A0,A1           ;are we finished?
2534
        BLS     SAVEND
2535
        MOVE.B  #':',D0      ;   if not, start a line
2536
        BSR     GOAUXO
2537
        MOVE.B  (A0)+,D1        ;send first half of line no.
2538
        BSR     PBYTE
2539
        MOVE.B  (A0)+,D1        ;and send 2nd half
2540
        BSR     PBYTE
2541
SAVE2:
2542
        MOVE.B  (A0)+,D0;       get a text char.
2543
        CMP.B   #CR,D0          ;is it the end of the line?
2544
        BEQ     SAVE1           ;if so, send CR & LF and start new line
2545
        BSR     GOAUXO          ;send it out
2546
        BRA     SAVE2           ;go back for more text
2547
SAVEND:
2548
        MOVE.B  #'@',D0 ;        send end-of-program indicator
2549
        BSR     GOAUXO
2550
        MOVE.B  #CR,D0  ;       followed by a CR & LF
2551
        BSR     GOAUXO
2552
        MOVE.B  #LF,D0
2553
        BSR     GOAUXO
2554
        MOVE.B  #0x1A,D0        ;and a control-Z to end the CP/M file
2555
        BSR     GOAUXO
2556
        BRA     WSTART          ;then go do a warm start
2557
 
2558
PBYTE:
2559
        MOVEQ   #1,D2   ;       send two hex characters from D1's low byte
2560
PBYTE1:
2561
        ROL.B   #4,D1   ;       get the next nybble
2562
        MOVE.B  D1,D0
2563
        AND.B   #0xF,D0 ;       strip off garbage
2564
        ADD.B   #'0',D0   ;      make it into ASCII
2565
        CMP.B   #'9',D0
2566
        BLS     PBYTE2
2567
        ADDQ.B  #7,D0           ;adjust if greater than 9
2568
PBYTE2:
2569
        BSR     GOAUXO          ;send it out
2570
        DBRA    D2,PBYTE1       ;then send the next nybble
2571
        RTS
2572
 
2573
;*
2574
;*******************************************************************
2575
;*
2576
;* *** POKE *** & CALL ***
2577
;*
2578
;* 'POKE expr1,expr2' stores the byte from 'expr2' into the memory
2579
;* address specified by 'expr1'.
2580
;*
2581
;* 'CALL expr' jumps to the machine language subroutine whose
2582
;* starting address is specified by 'expr'.  The subroutine can use
2583
;* all registers but must leave the stack the way it found it.
2584
;* The subroutine returns to the interpreter by executing an RTS.
2585
;*
2586
POKE:
2587
        BSR     EXPR            ;get the memory address
2588
        BSR.L   TSTC            ;it must be followed by a comma
2589
        DC.B    ',',PKER-$
2590
        MOVE.L  D0,-(SP)        ;save the address
2591
        BSR     EXPR            ;get the byte to be POKE'd
2592
        MOVE.L  (SP)+,A1        ;get the address back
2593
        MOVE.B  D0,(A1)         ;store the byte in memory
2594
        BRA     FINISH
2595
PKER:
2596
        BRA.L   QWHAT   ;       if no comma, say "What?"
2597
 
2598
POINT:
2599
        BSR EXPR
2600
        BSR     TSTC
2601
        DC.B    ',',PKER-$
2602
        MOVE.L  D0,-(SP)
2603
        BSR     EXPR
2604
        MOVE.L  (SP)+,D1
2605
        MOVE.L  D0,D2
2606
        BSR DrawPixel
2607
        BRA FINISH
2608
 
2609
PENCOLOR:
2610
        BSR     EXPR
2611
        MOVE.L  d0,GRAPHICS
2612
        BRA FINISH
2613
FILLCOLOR:
2614
        BSR     EXPR
2615
        MOVE.L  d0,GRAPHICS+4
2616
        BRA FINISH
2617
 
2618
LINE:
2619
        BSR     EXPR
2620
        BSR     TSTC
2621
        DC.B    ',',LINEERR1-$
2622
        MOVE.L  D0,-(SP)
2623
        BSR     EXPR
2624
        BSR     TSTC
2625
        DC.B    ',',LINEERR2-$
2626
        MOVE.L  D0,-(SP)
2627
        BSR     EXPR
2628
        BSR     TSTC
2629
        DC.B    ',',LINEERR3-$
2630
        MOVE.L  D0,-(SP)
2631
        BSR     EXPR
2632
;       MOVE.L  D0,D4
2633
;       MOVE.L  (SP)+,D3
2634
;       MOVE.L  (SP)+,D2
2635
;       MOVE.L  (SP)+,D1
2636
;       BSR             DrawLine
2637
        MOVE.W  d0,GRAPHICS+14
2638
        MOVE.L  (SP)+,d0
2639
        MOVE.W  d0,GRAPHICS+12
2640
        MOVE.L  (SP)+,d0
2641
        MOVE.W  d0,GRAPHICS+10
2642
        MOVE.L  (SP)+,d0
2643
        MOVE.W  d0,GRAPHICS+8
2644
        MOVE.W  #G_DRAWLINE,GRAPHICS+30
2645
        BRA             FINISH
2646
 
2647
LINEERR1:
2648
        BRA.L   QWHAT
2649
LINEERR2:
2650
        ADDQ    #4,SP
2651
        BRA.L   QWHAT
2652
LINEERR3:
2653
        ADD.L   #8,SP
2654
        BRA.L   QWHAT
2655
 
2656
CALL:
2657
        BSR     EXPR            ;get the subroutine's address
2658
        TST.L   D0              ;make sure we got a valid address
2659
        BEQ.L   QHOW    ;       if not, say "How?"
2660
        MOVE.L  A0,-(SP);       save the text pointer
2661
        MOVE.L  D0,A1
2662
        JSR     (A1)            ;jump to the subroutine
2663
        MOVE.L  (SP)+,A0        ;restore the text pointer
2664
        BRA     FINISH
2665
;*
2666
;*******************************************************************
2667
;*
2668
;* *** EXPR ***
2669
;*
2670
;* 'EXPR' evaluates arithmetical or logical expressions.
2671
;* ::=
2672
;*         
2673
;* where  is one of the operators in TAB8 and the result
2674
;* of these operations is 1 if true and 0 if false.
2675
;* ::=(+,-,&,|)(+,-,&,|)(...
2676
;* where () are optional and (... are optional repeats.
2677
;* ::=( <* or /> )(...
2678
;* ::=
2679
;*          
2680
;*          ()
2681
;*  is recursive so that the variable '@' can have an 
2682
;* as an index, functions can have an  as arguments, and
2683
;*  can be an  in parenthesis.
2684
;*
2685
EXPR:
2686
        BSR     EXPR2
2687
        MOVE.L  D0,-(SP);       save  value
2688
        LEA     TAB8,A1         ;look up a relational operator
2689
        LEA     TAB8_1,A2
2690
        BRA     EXEC            ;go do it
2691
 
2692
XP11:
2693
        BSR     XP18    ;       is it ">="?
2694
        BLT     XPRT0           ;no, return D0=0
2695
        BRA     XPRT1           ;else return D0=1
2696
 
2697
XP12:
2698
        BSR     XP18    ;       is it "<>"?
2699
        BEQ     XPRT0           ;no, return D0=0
2700
        BRA     XPRT1           ;else return D0=1
2701
 
2702
XP13:
2703
        BSR     XP18    ;       is it ">"?
2704
        BLE     XPRT0           ;no, return D0=0
2705
        BRA     XPRT1           ;else return D0=1
2706
 
2707
XP14:
2708
        BSR     XP18    ;       is it "<="?
2709
        BGT     XPRT0           ;no, return D0=0
2710
        BRA     XPRT1           ;else return D0=1
2711
 
2712
XP15:
2713
        BSR     XP18    ;       is it "="?
2714
        BNE     XPRT0           ;if not, return D0=0
2715
        BRA     XPRT1           ;else return D0=1
2716
XP15RT:
2717
        RTS
2718
 
2719
XP16:
2720
        BSR     XP18    ;       is it "<"?
2721
        BGE     XPRT0           ;if not, return D0=0
2722
        BRA     XPRT1           ;else return D0=1
2723
XP16RT:
2724
        RTS
2725
 
2726
XPRT0:
2727
        CLR.L   D0      ;       return D0=0 (false)
2728
        RTS
2729
 
2730
XPRT1:
2731
        MOVEQ   #1,D0;          return D0=1 (true)
2732
        RTS
2733
 
2734
XP17:
2735
        MOVE.L  (SP)+,D0        ;it's not a rel. operator
2736
        RTS                     ;return D0=
2737
 
2738
XP18:
2739
        MOVE.L  (SP)+,D0        ;reverse the top two stack items
2740
        MOVE.L  (SP)+,D1
2741
        MOVE.L  D0,-(SP)
2742
        MOVE.L  D1,-(SP)
2743
        BSR     EXPR2           ;do second 
2744
        MOVE.L  (SP)+,D1
2745
        CMP.L   D0,D1   ;       compare with the first result
2746
        RTS                     ;return the result
2747
 
2748
EXPR2:
2749
        BSR.L   TSTC            ;negative sign?
2750
        DC.B    '-',XP20-$
2751
        CLR.L   D0      ;       yes, fake '0-'
2752
        BRA     XP26
2753
XP20:
2754
        BSR.L   TSTC
2755
        DC.B    '!',XP21-$
2756
        CLR.L   D0
2757
        MOVE.L  D0,-(SP)
2758
        BSR             EXPR3
2759
        NOT.L   D0
2760
        JMP             XP24
2761
XP21:
2762
        BSR.L   TSTC    ;       positive sign? ignore it
2763
        DC.B    '+',XP22-$
2764
XP22:
2765
        BSR     EXPR3           ;first 
2766
XP23:
2767
        BSR.L   TSTC    ;       add?
2768
        DC.B    '+',XP25-$
2769
        MOVE.L  D0,-(SP)        ;yes, save the value
2770
        BSR     EXPR3           ;get the second 
2771
XP24:
2772
        MOVE.L  (SP)+,D1
2773
        ADD.L   D1,D0   ;       add it to the first 
2774
        BVS.L   QHOW    ;       branch if there's an overflow
2775
        BRA     XP23    ;       else go back for more operations
2776
XP25:
2777
        BSR.L   TSTC            ;subtract?
2778
        DC.B    '-',XP27-$      ; was XP42-$
2779
XP26:
2780
        MOVE.L  D0,-(SP)        ;yes, save the result of 1st 
2781
        BSR     EXPR3           ;get second 
2782
        NEG.L   D0              ;change its sign
2783
        JMP     XP24            ;and do an addition
2784
XP27:
2785
        BSR.L   TSTC
2786
        DC.B    '&',XP28-$
2787
        MOVE.L  D0,-(SP)
2788
        BSR     EXPR3
2789
        MOVE.L  (SP)+,D1
2790
        AND.L   D1,D0
2791
        BRA             XP23
2792
XP28:
2793
        BSR.L   TSTC
2794
        DC.B    '|',XP42-$
2795
        MOVE.L  D0,-(SP)
2796
        BSR     EXPR3
2797
        MOVE.L  (SP)+,D1
2798
        OR.L    D1,D0
2799
        BRA             XP23
2800
 
2801
EXPR3:
2802
        BSR     EXPR4           ;get first 
2803
XP31:
2804
        BSR.L   TSTC    ;       multiply?
2805
        DC.B    '*',XP34-$
2806
        MOVE.L  D0,-(SP);       yes, save that first result
2807
        BSR     EXPR4           ;get second 
2808
        MOVE.L  (SP)+,D1
2809
        BSR.L   MULT32  ;       multiply the two
2810
        BRA     XP31            ;then look for more terms
2811
XP34:
2812
        BSR.L   TSTC;           divide?
2813
        DC.B    '/',XP42-$
2814
        MOVE.L  D0,-(SP);       save result of 1st 
2815
        BSR     EXPR4           ;get second 
2816
        MOVE.L  (SP)+,D1
2817
        EXG     D0,D1
2818
        BSR.L   DIV32   ;       do the division
2819
        BRA     XP31            ;go back for any more terms
2820
 
2821
EXPR4:
2822
        LEA     TAB4,A1 ;       find possible function
2823
        LEA     TAB4_1,A2
2824
        BRA     EXEC
2825
XP40:
2826
        BSR     TSTV    ;       nope, not a function
2827
        BCS     XP41            ;nor a variable
2828
        MOVE.L  D0,A1
2829
        CLR.L   D0
2830
        MOVE.L  (A1),D0 ;       if a variable, return its value in D0
2831
EXP4RT:
2832
        RTS
2833
XP41:
2834
        BSR.L   TSTNUM  ;       or is it a number?
2835
        MOVE.L  D1,D0
2836
        TST     D2              ;(if not, # of digits will be zero)
2837
        BNE     EXP4RT  ;       if so, return it in D0
2838
PARN:
2839
        BSR.L   TSTC    ;       else look for ( EXPR )
2840
        DC.B    '(',XP43-$
2841
        BSR     EXPR
2842
        BSR.L   TSTC
2843
        DC.B    ')',XP43-$
2844
XP42:
2845
        RTS
2846
XP43:
2847
        BRA.L   QWHAT   ;       else say "What?"
2848
 
2849
;*
2850
;* ===== Test for a valid variable name.  Returns Carry=1 if not
2851
;*      found, else returns Carry=0 and the address of the
2852
;*      variable in D0.
2853
 
2854
TSTV:
2855
        BSR.L   IGNBLK
2856
        CLR.L   D0
2857
        MOVE.B  (A0),D0 ;       look at the program text
2858
        SUB.B   #'@',D0
2859
        BCS     TSTVRT  ;       C=1: not a variable
2860
        BNE     TV1             ;branch if not "@" array
2861
        ADDQ    #1,A0   ;       If it is, it should be
2862
        BSR     PARN            ;followed by (EXPR) as its index.
2863
        ADD.L   D0,D0
2864
        BCS.L   QHOW    ;       say "How?" if index is too big
2865
        ADD.L   D0,D0
2866
        BCS.L   QHOW
2867
        MOVE.L  D0,-(SP)        ;save the index
2868
        BSR.L   SIZE_           ;get amount of free memory
2869
        MOVE.L  (SP)+,D1        ;get back the index
2870
        CMP.L   D1,D0           ;see if there's enough memory
2871
        BLS.L   QSORRY          ;if not, say "Sorry"
2872
        MOVE.L  VARBGN,D0       ;put address of array element...
2873
        SUB.L   D1,D0           ;into D0
2874
        RTS
2875
TV1:
2876
        CMP.B   #27,D0          ;if not @, is it A through Z?
2877
        EOR     #1,CCR
2878
        BCS     TSTVRT          ;if not, set Carry and return
2879
        ADDQ    #1,A0   ;       else bump the text pointer
2880
;
2881
        CLR.L   D1
2882
        MOVE.B  (a0),D1
2883
        BSR             CVT26
2884
        cmpi.b  #0xff,d1
2885
        beq             tv2
2886
        ADDQ    #1,A0   ; bump text pointer
2887
        asl.l   #5,D1
2888
        ADD.L   D1,D0
2889
tv2:
2890
        ADD     D0,D0           ;compute the variable's address
2891
        ADD     D0,D0
2892
        MOVE.L  VARBGN,D1
2893
        ADD     D1,D0           ;and return it in D0 with Carry=0
2894
TSTVRT:
2895
        RTS
2896
 
2897
CVT26:
2898
        cmpi.b  #'A',d1
2899
        blo             CVT26a
2900
        cmpi.b  #'Z',d1
2901
        bhi             CVT26a
2902
        subi.b  #'A',d1
2903
        rts
2904
CVT26a:
2905
        moveq   #-1,d1
2906
        rts
2907
;*
2908
;* ===== Multiplies the 32 bit values in D0 and D1, returning
2909
;*      the 32 bit result in D0.
2910
;*
2911
MULT32:
2912
        MOVE.L  D1,D4
2913
        EOR.L   D0,D4   ;       see if the signs are the same
2914
        TST.L   D0              ;take absolute value of D0
2915
        BPL     MLT1
2916
        NEG.L   D0
2917
MLT1:
2918
        TST.L   D1      ;       take absolute value of D1
2919
        BPL     MLT2
2920
        NEG.L   D1
2921
MLT2:
2922
        CMP.L   #0xFFFF,D1      ;is second argument <= 16 bits?
2923
        BLS     MLT3    ;       OK, let it through
2924
        EXG     D0,D1   ;       else swap the two arguments
2925
        CMP.L   #0xFFFF,D1      ;and check 2nd argument again
2926
        BHI.L   QHOW            ;one of them MUST be 16 bits
2927
MLT3:
2928
        MOVE    D0,D2   ;       prepare for 32 bit X 16 bit multiply
2929
        MULU    D1,D2           ;multiply low word
2930
        SWAP    D0
2931
        MULU    D1,D0           ;multiply high word
2932
        SWAP    D0
2933
;*** Rick Murray's bug correction follows:
2934
        TST     D0              ;if lower word not 0, then overflow
2935
        BNE.L   QHOW    ;       if overflow, say "How?"
2936
        ADD.L   D2,D0   ;       D0 now holds the product
2937
        BMI.L   QHOW    ;       if sign bit set, it's an overflow
2938
        TST.L   D4              ;were the signs the same?
2939
        BPL     MLTRET
2940
        NEG.L   D0              ;if not, make the result negative
2941
MLTRET:
2942
        RTS
2943
 
2944
;*
2945
;* ===== Divide the 32 bit value in D0 by the 32 bit value in D1.
2946
;*      Returns the 32 bit quotient in D0, remainder in D1.
2947
;*
2948
DIV32:
2949
        TST.L   D1              ;check for divide-by-zero
2950
        BEQ.L   QHOW            ;if so, say "How?"
2951
        MOVE.L  D1,D2
2952
        MOVE.L  D1,D4
2953
        EOR.L   D0,D4           ;see if the signs are the same
2954
        TST.L   D0              ;take absolute value of D0
2955
        BPL     DIV1
2956
        NEG.L   D0
2957
DIV1:
2958
        TST.L   D1      ;       take absolute value of D1
2959
        BPL     DIV2
2960
        NEG.L   D1
2961
DIV2:
2962
        MOVEQ   #31,D3  ;       iteration count for 32 bits
2963
        MOVE.L  D0,D1
2964
        CLR.L   D0
2965
DIV3:
2966
        ADD.L   D1,D1   ;       (This algorithm was translated from
2967
        ADDX.L  D0,D0           ;the divide routine in Ron Cain's
2968
        BEQ     DIV4            ;Small-C run time library.)
2969
        CMP.L   D2,D0
2970
        BMI     DIV4
2971
        ADDQ.L  #1,D1
2972
        SUB.L   D2,D0
2973
DIV4:
2974
        DBRA    D3,DIV3
2975
        EXG     D0,D1   ;       put rem. & quot. in proper registers
2976
        TST.L   D4      ;       were the signs the same?
2977
        BPL     DIVRT
2978
        NEG.L   D0      ;       if not, results are negative
2979
        NEG.L   D1
2980
DIVRT:
2981
        RTS
2982
 
2983
;*
2984
;* ===== The PEEK function returns the byte stored at the address
2985
;*      contained in the following expression.
2986
;*
2987
PEEK:
2988
        BSR     PARN    ;       get the memory address
2989
        MOVE.L  D0,A1
2990
        CLR.L   D0              ;upper 3 bytes will be zero
2991
        MOVE.B  (A1),D0 ;       get the addressed byte
2992
        RTS                     ;and return it
2993
 
2994
;*
2995
;* ===== The RND function returns a random number from 1 to
2996
;*      the value of the following expression in D0.
2997
;*
2998
RND:
2999
        BSR     PARN    ;       get the upper limit
3000
        TST.L   D0      ;       it must be positive and non-zero
3001
        BEQ.L   QHOW
3002
        BMI.L   QHOW
3003
 
3004
;       move.l  d0,-(a7)
3005
;       move.l  RANPNT,D1
3006
;       move.l  #16807,d0
3007
;       bsr             MULT32
3008
;       move.l  d0,RANPNT
3009
;       move.l  (a7)+,d1
3010
        MOVE.L  D0,D1
3011
        MOVE.W  RANDOM+2,D0
3012
        SWAP    D0
3013
        MOVE.W  RANDOM,D0
3014
 
3015
;       MOVE.L  D0,D1
3016
;       MOVE.L  RANPNT,A1       ;get memory as a random number
3017
;       CMP.L   #LSTROM,A1
3018
;       BCS     RA1
3019
;       LEA     START,A1        ;wrap around if end of program
3020
;RA1:
3021
;       MOVE.L  (A1)+,D0;       get the slightly random number
3022
        BCLR    #31,D0  ;       make sure it's positive
3023
;       MOVE.L  A1,RANPNT       ;(even I can do better than this!)
3024
        BSR     DIV32           ;RND(n)=MOD(number,n)+1
3025
        MOVE.L  D1,D0   ;       MOD is the remainder of the div.
3026
        ADDQ.L  #1,D0
3027
        RTS
3028
 
3029
;*
3030
;* ===== The ABS function returns an absolute value in D0.
3031
;*
3032
ABS:
3033
        BSR     PARN            ;get the following expr.'s value
3034
        TST.L   D0
3035
        BPL     ABSRT
3036
        NEG.L   D0              ;if negative, complement it
3037
        BMI.L   QHOW    ;       if still negative, it was too big
3038
ABSRT:
3039
        RTS
3040
 
3041
;* RTF
3042
;* ===== The SGN function returns the sign value in D0.
3043
;*
3044
SGN:
3045
        BSR             PARN    ;get the following expr.'s value
3046
        TST.L   D0
3047
        BEQ             SGNRT
3048
        BMI             SGNMI
3049
        MOVEQ   #1,d0
3050
SGNRT:
3051
        RTS
3052
SGNMI:
3053
        MOVEQ   #-1,d0
3054
        RTS
3055
 
3056
;*
3057
;* ===== The SIZE function returns the size of free memory in D0.
3058
;*
3059
SIZE_:
3060
        MOVE.L  VARBGN,D0       ;get the number of free bytes...
3061
        SUB.L   TXTUNF,D0       ;between 'TXTUNF' and 'VARBGN'
3062
        RTS                     ;return the number in D0
3063
 
3064
;* RTF
3065
;* ===== return the millisecond time value
3066
;*
3067
TICK:
3068
        move.l  Milliseconds,d0
3069
        rts
3070
 
3071
TEMP:
3072
        bsr             ReadTemp
3073
        andi.l  #0xffff,d0
3074
        rts
3075
 
3076
;*
3077
;*******************************************************************
3078
;*
3079
;* *** SETVAL *** FIN *** ENDCHK *** ERROR (& friends) ***
3080
;*
3081
;* 'SETVAL' expects a variable, followed by an equal sign and then
3082
;* an expression.  It evaluates the expression and sets the variable
3083
;* to that value.
3084
;*
3085
;* 'FIN' checks the end of a command.  If it ended with ":",
3086
;* execution continues. If it ended with a CR, it finds the
3087
;* the next line and continues from there.
3088
;*
3089
;* 'ENDCHK' checks if a command is ended with a CR. This is
3090
;* required in certain commands, such as GOTO, RETURN, STOP, etc.
3091
;*
3092
;* 'ERROR' prints the string pointed to by A0. It then prints the
3093
;* line pointed to by CURRNT with a "?" inserted at where the
3094
;* old text pointer (should be on top of the stack) points to.
3095
;* Execution of Tiny BASIC is stopped and a warm start is done.
3096
;* If CURRNT is zero (indicating a direct command), the direct
3097
;* command is not printed. If CURRNT is -1 (indicating
3098
;* 'INPUT' command in progress), the input line is not printed
3099
;* and execution is not terminated but continues at 'INPERR'.
3100
;*
3101
;* Related to 'ERROR' are the following:
3102
;* 'QWHAT' saves text pointer on stack and gets "What?" message.
3103
;* 'AWHAT' just gets the "What?" message and jumps to 'ERROR'.
3104
;* 'QSORRY' and 'ASORRY' do the same kind of thing.
3105
;* 'QHOW' and 'AHOW' also do this for "How?".
3106
;*
3107
SETVAL:
3108
        BSR     TSTV    ;       variable name?
3109
        BCS     QWHAT           ;if not, say "What?"
3110
        MOVE.L  D0,-(SP);       save the variable's address
3111
        BSR.L   TSTC    ;       get past the "=" sign
3112
        DC.B    '=',SV1-$
3113
        BSR     EXPR    ;       evaluate the expression
3114
        MOVE.L  (SP)+,A6
3115
        MOVE.L  D0,(A6) ;       and save its value in the variable
3116
        RTS
3117
SV1:
3118
        BRA     QWHAT   ;       if no "=" sign
3119
 
3120
FIN:
3121
        BSR.L   TSTC    ;       *** FIN ***
3122
        DC.B    ':',FI1-$
3123
        ADDQ.L  #4,SP   ;       if ":", discard return address
3124
        BRA     RUNSML  ;       continue on the same line
3125
FI1:
3126
        BSR.L   TSTC    ;       not ":", is it a CR?
3127
        DC.B    CR,FI2-$
3128
        ADDQ.L  #4,SP   ;       yes, purge return address
3129
        BRA     RUNNXL          ;execute the next line
3130
FI2:
3131
        RTS                     ;else return to the caller
3132
 
3133
ENDCHK:
3134
        BSR.L   IGNBLK
3135
        CMP.B   #CR,(A0);       does it end with a CR?
3136
        BNE     QWHAT   ;       if not, say "WHAT?"
3137
        RTS
3138
 
3139
QWHAT:
3140
        MOVE.L  A0,-(SP)
3141
AWHAT:
3142
        LEA     WHTMSG,A6
3143
ERROR:
3144
        BSR.L   PRMESG  ;       display the error message
3145
        MOVE.L  (SP)+,A0        ;restore the text pointer
3146
        MOVE.L  CURRNT,D0       ;get the current line number
3147
        BEQ     WSTART          ;if zero, do a warm start
3148
        CMP.L   #-1,D0          ;is the line no. pointer = -1?
3149
        BEQ     INPERR          ;if so, redo input
3150
        MOVE.B  (A0),-(SP)      ;save the char. pointed to
3151
        CLR.B   (A0)            ;put a zero where the error is
3152
        MOVE.L  CURRNT,A1       ;point to start of current line
3153
        BSR.L   PRTLN           ;display the line in error up to the 0
3154
        MOVE.B  (SP)+,(A0)      ;restore the character
3155
        MOVE.B  #'?',D0     ;    display a "?"
3156
        BSR     GOOUT
3157
        CLR     D0
3158
        SUBQ.L  #1,A1           ;point back to the error char.
3159
        BSR.L   PRTSTG          ;display the rest of the line
3160
        BRA     WSTART          ;and do a warm start
3161
QSORRY:
3162
        MOVE.L  A0,-(SP)
3163
ASORRY:
3164
        LEA     SRYMSG,A6
3165
        BRA     ERROR
3166
QHOW:
3167
        MOVE.L  A0,-(SP)        ;Error: "How?"
3168
AHOW:
3169
        LEA     HOWMSG,A6
3170
        BRA     ERROR
3171
;*
3172
;*******************************************************************
3173
;*
3174
;* *** GETLN *** FNDLN (& friends) ***
3175
;*
3176
;* 'GETLN' reads in input line into 'BUFFER'. It first prompts with
3177
;* the character in D0 (given by the caller), then it fills the
3178
;* buffer and echos. It ignores LF's but still echos
3179
;* them back. Control-H is used to delete the last character
3180
;* entered (if there is one), and control-X is used to delete the
3181
;* whole line and start over again. CR signals the end of a line,
3182
;* and causes 'GETLN' to return.
3183
;*
3184
GETLN:
3185
        BSR     GOOUT           ;display the prompt
3186
        MOVE.B  #' ',D0      ;   and a space
3187
        BSR     GOOUT
3188
        LEA     BUFFER,A0;      A0 is the buffer pointer
3189
GL1:
3190
        BSR.L   CHKIO;          check keyboard
3191
        BEQ     GL1     ;       wait for a char. to come in
3192
        CMP.B   #CTRLH,D0       ;delete last character?
3193
        BEQ     GL3     ;       if so
3194
        CMP.B   #CTRLX,D0;      delete the whole line?
3195
        BEQ     GL4     ;       if so
3196
        CMP.B   #CR,D0  ;       accept a CR
3197
        BEQ     GL2
3198
        CMP.B   #' ',D0  ;       if other control char., discard it
3199
        BCS     GL1
3200
GL2:
3201
        MOVE.B  D0,(A0)+;       save the char.
3202
        BSR     GOOUT           ;echo the char back out
3203
        CMP.B   #CR,D0  ;       if it's a CR, end the line
3204
        BEQ     GL7
3205
        CMP.L   #(BUFFER+BUFLEN-1),A0   ;any more room?
3206
        BCS     GL1     ;       yes: get some more, else delete last char.
3207
GL3:
3208
        MOVE.B  #CTRLH,D0       ;delete a char. if possible
3209
        BSR     GOOUT
3210
        MOVE.B  #' ',D0
3211
        BSR     GOOUT
3212
        CMP.L   #BUFFER,A0      ;any char.'s left?
3213
        BLS     GL1             ;if not
3214
        MOVE.B  #CTRLH,D0;      if so, finish the BS-space-BS sequence
3215
        BSR     GOOUT
3216
        SUBQ.L  #1,A0   ;       decrement the text pointer
3217
        BRA     GL1             ;back for more
3218
GL4:
3219
        MOVE.L  A0,D1   ;       delete the whole line
3220
        SUB.L   #BUFFER,D1;     figure out how many backspaces we need
3221
        BEQ     GL6             ;if none needed, branch
3222
        SUBQ    #1,D1   ;       adjust for DBRA
3223
GL5:
3224
        MOVE.B  #CTRLH,D0       ;and display BS-space-BS sequences
3225
        BSR     GOOUT
3226
        MOVE.B  #' ',D0
3227
        BSR     GOOUT
3228
        MOVE.B  #CTRLH,D0
3229
        BSR     GOOUT
3230
        DBRA    D1,GL5
3231
GL6:
3232
        LEA     BUFFER,A0       ;reinitialize the text pointer
3233
        BRA     GL1             ;and go back for more
3234
GL7:
3235
        MOVE.B  #LF,D0  ;       echo a LF for the CR
3236
        BSR     GOOUT
3237
        RTS
3238
 
3239
;*
3240
;*******************************************************************
3241
;*
3242
;* *** FNDLN (& friends) ***
3243
;*
3244
;* 'FNDLN' finds a line with a given line no. (in D1) in the
3245
;* text save area.  A1 is used as the text pointer. If the line
3246
;* is found, A1 will point to the beginning of that line
3247
;* (i.e. the high byte of the line no.), and flags are NC & Z.
3248
;* If that line is not there and a line with a higher line no.
3249
;* is found, A1 points there and flags are NC & NZ. If we reached
3250
;* the end of the text save area and cannot find the line, flags
3251
;* are C & NZ.
3252
;* 'FNDLN' will initialize A1 to the beginning of the text save
3253
;* area to start the search. Some other entries of this routine
3254
;* will not initialize A1 and do the search.
3255
;* 'FNDLNP' will start with A1 and search for the line no.
3256
;* 'FNDNXT' will bump A1 by 2, find a CR and then start search.
3257
;* 'FNDSKP' uses A1 to find a CR, and then starts the search.
3258
;*
3259
FNDLN:
3260
        CMP.L   #0xFFFF,D1      ;line no. must be < 65535
3261
        BCC     QHOW
3262
        MOVE.L  TXTBGN,A1       ;init. the text save pointer
3263
 
3264
FNDLNP:
3265
        MOVE.L  TXTUNF,A2       ;check if we passed the end
3266
        SUBQ.L  #1,A2
3267
        CMPA.L  A1,A2
3268
        BCS     FNDRET  ;       if so, return with Z=0 & C=1
3269
        MOVE.B  (A1),D2 ;if not, get a line no.
3270
        LSL.W   #8,D2
3271
        MOVE.B  1(A1),D2
3272
        CMP.W   D1,D2           ;is this the line we want?
3273
        BCS     FNDNXT          ;no, not there yet
3274
FNDRET:
3275
        RTS                     ;return the cond. codes
3276
 
3277
FNDNXT:
3278
        ADDQ.L  #2,A1;          find the next line
3279
 
3280
FNDSKP:
3281
        CMP.B   #CR,(A1)+       ;try to find a CR
3282
        BNE     FNDSKP          ;keep looking
3283
        BRA     FNDLNP          ;check if end of text
3284
 
3285
;*
3286
;*******************************************************************
3287
;*
3288
;* *** MVUP *** MVDOWN *** POPA *** PUSHA ***
3289
;*
3290
;* 'MVUP' moves a block up from where A1 points to where A2 points
3291
;* until A1=A3
3292
;*
3293
;* 'MVDOWN' moves a block down from where A1 points to where A3
3294
;* points until A1=A2
3295
;*
3296
;* 'POPA' restores the 'FOR' loop variable save area from the stack
3297
;*
3298
;* 'PUSHA' stacks for 'FOR' loop variable save area onto the stack
3299
;*
3300
MVUP:
3301
        CMP.L   A1,A3   ;       see the above description
3302
        BEQ     MVRET
3303
        MOVE.B  (A1)+,(A2)+
3304
        BRA     MVUP
3305
MVRET:
3306
        RTS
3307
 
3308
MVDOWN:
3309
        CMP.L   A1,A2   ;       see the above description
3310
        BEQ     MVRET
3311
        MOVE.B  -(A1),-(A3)
3312
        BRA     MVDOWN
3313
 
3314
POPA:
3315
        MOVE.L  (SP)+,A6        ;A6 = return address
3316
        MOVE.L  (SP)+,LOPVAR    ;restore LOPVAR, but zero means no more
3317
        BEQ     PP1
3318
        MOVE.L  (SP)+,LOPINC    ;if not zero, restore the rest
3319
        MOVE.L  (SP)+,LOPLMT
3320
        MOVE.L  (SP)+,LOPLN
3321
        MOVE.L  (SP)+,LOPPT
3322
PP1:
3323
        JMP     (A6)    ;       return
3324
 
3325
PUSHA:
3326
        MOVE.L  STKLMT,D1       ;Are we running out of stack room?
3327
        SUB.L   SP,D1
3328
        BCC             QSORRY          ;if so, say we're sorry
3329
        MOVE.L  (SP)+,A6        ;else get the return address
3330
        MOVE.L  LOPVAR,D1       ;save loop variables
3331
        BEQ             PU1             ;if LOPVAR is zero, that's all
3332
        MOVE.L  LOPPT,-(SP)     ;else save all the others
3333
        MOVE.L  LOPLN,-(SP)
3334
        MOVE.L  LOPLMT,-(SP)
3335
        MOVE.L  LOPINC,-(SP)
3336
PU1:
3337
        MOVE.L  D1,-(SP)
3338
        JMP     (A6)            ;return
3339
 
3340
;*
3341
;*******************************************************************
3342
;*
3343
;* *** PRTSTG *** QTSTG *** PRTNUM *** PRTLN ***
3344
;*
3345
;* 'PRTSTG' prints a string pointed to by A1. It stops printing
3346
;* and returns to the caller when either a CR is printed or when
3347
;* the next byte is the same as what was passed in D0 by the
3348
;* caller.
3349
;*
3350
;* 'QTSTG' looks for an underline (back-arrow on some systems),
3351
;* single-quote, or double-quote.  If none of these are found, returns
3352
;* to the caller.  If underline, outputs a CR without a LF.  If single
3353
;* or double quote, prints the quoted string and demands a matching
3354
;* end quote.  After the printing, the next 2 bytes of the caller are
3355
;* skipped over (usually a short branch instruction).
3356
;*
3357
;* 'PRTNUM' prints the 32 bit number in D1, leading blanks are added if
3358
;* needed to pad the number of spaces to the number in D4.
3359
;* However, if the number of digits is larger than the no. in
3360
;* D4, all digits are printed anyway. Negative sign is also
3361
;* printed and counted in, positive sign is not.
3362
;*
3363
;* 'PRTLN' prints the saved text line pointed to by A1
3364
;* with line no. and all.
3365
;*
3366
PRTSTG:
3367
        MOVE.B  D0,D1   ;       save the stop character
3368
PS1:
3369
        MOVE.B  (A1)+,D0        ;get a text character
3370
        CMP.B   D0,D1           ;same as stop character?
3371
        BEQ             PRTRET          ;if so, return
3372
        BSR             GOOUT           ;display the char.
3373
        CMP.B   #CR,D0          ;;is it a C.R.?
3374
        BNE             PS1             ;no, go back for more
3375
        MOVE.B  #LF,D0  ;       yes, add a L.F.
3376
        BSR             GOOUT
3377
PRTRET:
3378
        RTS                     ;then return
3379
 
3380
QTSTG:
3381
        BSR.L   TSTC;           *** QTSTG ***
3382
        DC.B    '"',QT3-$
3383
        MOVE.B  #'"',D0  ;       it is a "
3384
QT1:
3385
        MOVE.L  A0,A1
3386
        BSR     PRTSTG          ;print until another
3387
        MOVE.L  A1,A0
3388
        MOVE.L  (SP)+,A1;       pop return address
3389
        CMP.B   #LF,D0  ;       was last one a CR?
3390
        BEQ     RUNNXL          ;if so, run next line
3391
QT2:
3392
        ADDQ.L  #2,A1   ;       skip 2 bytes on return
3393
        JMP     (A1)            ;return
3394
QT3:
3395
        BSR.L   TSTC    ;       is it a single quote?
3396
        DC.B    '\'',QT4-$
3397
        MOVE.B  #'''',D0  ;      if so, do same as above
3398
        BRA     QT1
3399
QT4:
3400
        BSR.L   TSTC            ;is it an underline?
3401
        DC.B    '_',QT5-$
3402
        MOVE.B  #CR,D0          ;if so, output a CR without LF
3403
        BSR.L   GOOUT
3404
        MOVE.L  (SP)+,A1        ;pop return address
3405
        BRA     QT2
3406
QT5:
3407
        RTS                     ;none of the above
3408
 
3409
PRTNUM:
3410
        movem.l d0/d1/d4/a1/a5,-(a7)
3411
        lea             scratch1,a5
3412
        move.l  d1,d0
3413
        jsr             HEX2DEC
3414
        lea             scratch1,a5
3415
PN8:
3416
        move.b  (a5)+,d0
3417
        beq             PN7
3418
        dbra    d4,PN8
3419
PN7:
3420
        tst.w   d4
3421
        bmi             PN9
3422
        MOVE.B  #' ',D0  ;       display the required leading spaces
3423
        BSR             GOOUT
3424
        DBRA    D4,PN7
3425
PN9:
3426
        lea             scratch1,a1
3427
        jsr             DisplayString
3428
        movem.l (a7)+,d0/d1/d4/a1/a5
3429
        rts
3430
 
3431
;PRTNUM
3432
;       MOVE.L  D1,D3   ;       save the number for later
3433
;       MOVE.L  D4,-(SP)        ;save the width value
3434
;       MOVE.W  #0xFFFF,-(SP)   ;flag for end of digit string
3435
;       TST.L   D1              ;is it negative?
3436
;       BPL     PN1             ;if not
3437
;       NEG.L   D1      ;       else make it positive
3438
;       SUBQ    #1,D4   ;       one less for width count
3439
;PN1:
3440
;       DIVU    #10,D1  ;       get the next digit
3441
;       BVS     PNOV    ;       overflow flag set?
3442
;       MOVE.L  D1,D0   ;       if not, save remainder
3443
;       AND.L   #0xFFFF,D1      ;strip the remainder
3444
;       BRA     TOASCII         ;skip the overflow stuff
3445
;PNOV:
3446
;       MOVE    D1,D0   ;       prepare for long word division
3447
;       CLR.W   D1              ;zero out low word
3448
;       SWAP    D1              ;high word into low
3449
;       DIVU    #10,D1  ;       divide high word
3450
;       MOVE    D1,D2   ;       save quotient
3451
;       MOVE    D0,D1   ;       low word into low
3452
;       DIVU    #10,D1  ;       divide low word
3453
;       MOVE.L  D1,D0   ;       D0 = remainder
3454
;       SWAP    D1              ;       R/Q becomes Q/R
3455
;       MOVE    D2,D1   ;       D1 is low/high
3456
;       SWAP    D1              ;       D1 is finally high/low
3457
;TOASCII:
3458
;       SWAP    D0              ;       get remainder
3459
;       MOVE.W  D0,-(SP);       stack it as a digit
3460
;       SWAP    D0
3461
;       SUBQ    #1,D4   ;       decrement width count
3462
;       TST.L   D1              ;if quotient is zero, we're done
3463
;       BNE     PN1
3464
;       SUBQ    #1,D4   ;       adjust padding count for DBRA
3465
;       BMI     PN4             ;skip padding if not needed
3466
;PN3:
3467
;       MOVE.B  #' ',D0  ;       display the required leading spaces
3468
;       BSR     GOOUT
3469
;       DBRA    D4,PN3
3470
;PN4:
3471
;       TST.L   D3              ;is number negative?
3472
;       BPL     PN5
3473
;       MOVE.B  #'-',D0  ;       if so, display the sign
3474
;       BSR     GOOUT
3475
;PN5:
3476
;       MOVE.W  (SP)+,D0        ;now unstack the digits and display
3477
;       BMI     PNRET           ;until the flag code is reached
3478
;       ADD.B   #'0',D0   ;      make into ASCII
3479
;       BSR     GOOUT
3480
;       BRA     PN5
3481
;PNRET:
3482
;       MOVE.L  (SP)+,D4        ;restore width value
3483
;       RTS
3484
 
3485
PRTLN:
3486
        CLR.L   D1
3487
        MOVE.B  (A1)+,D1        ;get the binary line number
3488
        LSL     #8,D1
3489
        MOVE.B  (A1)+,D1
3490
        MOVEQ   #5,D4           ;display a 5 digit line no.
3491
        BSR     PRTNUM
3492
        MOVE.B  #' ',D0      ;   followed by a blank
3493
        BSR     GOOUT
3494
        CLR     D0              ;stop char. is a zero
3495
        BRA     PRTSTG  ;       display the rest of the line
3496
 
3497
;*
3498
;* ===== Test text byte following the call to this subroutine. If it
3499
;*      equals the byte pointed to by A0, return to the code following
3500
;*      the call. If they are not equal, branch to the point
3501
;*      indicated by the offset byte following the text byte.
3502
;*
3503
TSTC:
3504
        BSR     IGNBLK          ;ignore leading blanks
3505
        MOVE.L  (SP)+,A1        ;get the return address
3506
        MOVE.B  (A1)+,D1        ;get the byte to compare
3507
        CMP.B   (A0),D1         ;is it = to what A0 points to?
3508
        BEQ     TC1             ;if so
3509
        CLR.L   D1              ;If not, add the second
3510
        MOVE.B  (A1),D1 ;       byte following the call to
3511
        ADD.L   D1,A1   ;       the return address.
3512
        JMP     (A1)            ;jump to the routine
3513
TC1:
3514
        ADDQ.L  #1,A0   ;       if equal, bump text pointer
3515
        ADDQ.L  #1,A1   ;       Skip the 2 bytes following
3516
        JMP     (A1)            ;the call and continue.
3517
 
3518
;*
3519
;* ===== See if the text pointed to by A0 is a number. If so,
3520
;*      return the number in D1 and the number of digits in D2,
3521
;*      else return zero in D1 and D2.
3522
;*
3523
TSTNUM:
3524
        CLR.L   D1              ;initialize return parameters
3525
        CLR     D2
3526
        BSR     IGNBLK          ;skip over blanks
3527
TN1:
3528
        CMP.B   #'0',(A0) ;      is it less than zero?
3529
        BCS     TSNMRET         ;if so, that's all
3530
        CMP.B   #'9',(A0) ;      is it greater than nine?
3531
        BHI     TSNMRET         ;if so, return
3532
        CMP.L   #214748364,D1   ;see if there's room for new digit
3533
        BCC     QHOW            ;if not, we've overflowd
3534
        MOVE.L  D1,D0   ;       quickly multiply result by 10
3535
        ADD.L   D1,D1
3536
        ADD.L   D1,D1
3537
        ADD.L   D0,D1
3538
        ADD.L   D1,D1
3539
        MOVE.B  (A0)+,D0        ;add in the new digit
3540
        AND.L   #0xF,D0
3541
        ADD.L   D0,D1
3542
        ADDQ    #1,D2           ;increment the no. of digits
3543
        BRA     TN1
3544
TSNMRET:
3545
        RTS
3546
 
3547
;*
3548
;* ===== Skip over blanks in the text pointed to by A0.
3549
;*
3550
IGNBLK:
3551
        CMP.B   #' ',(A0)   ;    see if it's a space
3552
        BNE     IGBRET          ;if so, swallow it
3553
IGB1:
3554
        ADDQ.L  #1,A0   ;       increment the text pointer
3555
        BRA     IGNBLK
3556
IGBRET:
3557
        RTS
3558
 
3559
;*
3560
;* ===== Convert the line of text in the input buffer to upper
3561
;*      case (except for stuff between quotes).
3562
;*
3563
TOUPBUF:
3564
        LEA     BUFFER,A0       ;set up text pointer
3565
        CLR.B   D1              ;clear quote flag
3566
TOUPB1:
3567
        MOVE.B  (A0)+,D0        ;get the next text char.
3568
        CMP.B   #CR,D0          ;is it end of line?
3569
        BEQ     TOUPBRT         ;if so, return
3570
        CMP.B   #'"',D0  ;       a double quote?
3571
        BEQ     DOQUO
3572
        CMP.B   #'''',D0  ;      or a single quote?
3573
        BEQ     DOQUO
3574
        TST.B   D1              ;inside quotes?
3575
        BNE     TOUPB1          ;if so, do the next one
3576
        BSR     TOUPPER         ;convert to upper case
3577
        MOVE.B  D0,-(A0);       store it
3578
        ADDQ.L  #1,A0
3579
        BRA     TOUPB1          ;and go back for more
3580
TOUPBRT:
3581
        RTS
3582
 
3583
DOQUO:
3584
        TST.B   D1      ;       are we inside quotes?
3585
        BNE     DOQUO1
3586
        MOVE.B  D0,D1   ;       if not, toggle inside-quotes flag
3587
        BRA     TOUPB1
3588
DOQUO1:
3589
        CMP.B   D0,D1   ;       make sure we're ending proper quote
3590
        BNE     TOUPB1          ;if not, ignore it
3591
        CLR.B   D1              ;else clear quote flag
3592
        BRA     TOUPB1
3593
 
3594
;*
3595
;* ===== Convert the character in D0 to upper case
3596
;*
3597
TOUPPER:
3598
        CMP.B   #'a',D0   ;      is it < 'a'?
3599
        BCS     TOUPRET
3600
        CMP.B   #'z',D0        ; or > 'z'?
3601
        BHI     TOUPRET
3602
        SUB.B   #32,D0          ;if not, make it upper case
3603
TOUPRET:
3604
        RTS
3605
 
3606
;*
3607
;* 'CHKIO' checks the input. If there's no input, it will return
3608
;* to the caller with the Z flag set. If there is input, the Z
3609
;* flag is cleared and the input byte is in D0. However, if a
3610
;* control-C is read, 'CHKIO' will warm-start BASIC and will not
3611
;* return to the caller.
3612
;*
3613
CHKIO:
3614
        BSR.L   GOIN    ;       get input if possible
3615
        BEQ     CHKRET          ;if Zero, no input
3616
        CMP.B   #CTRLC,D0       ;is it control-C?
3617
        BNE     CHKRET          ;if not
3618
        BRA.L   WSTART          ;if so, do a warm start
3619
CHKRET:
3620
        RTS
3621
 
3622
;*
3623
;* ===== Display a CR-LF sequence
3624
;*
3625
CRLF1:
3626
        LEA     CLMSG,A6
3627
 
3628
;*
3629
;* ===== Display a zero-ended string pointed to by register A6
3630
;*
3631
PRMESG:
3632
        MOVE.B  (A6)+,D0        ;get the char.
3633
        BEQ     PRMRET          ;if it's zero, we're done
3634
        BSR     GOOUT           ;else display it
3635
        BRA     PRMESG
3636
PRMRET:
3637
        RTS
3638
 
3639
;******************************************************
3640
;* The following routines are the only ones that need *
3641
;* to be changed for a different I/O environment.     *
3642
;******************************************************
3643
 
3644
;UART           EQU             0xFFDC0A00
3645
;UART_LS                EQU             UART+1
3646
;UART_CTRL      EQU             UART+7
3647
;KEYBD          EQU             0xFFDC0000
3648
 
3649
 
3650
;*
3651
;* ===== Output character to the console (Port 1) from register D0
3652
;*      (Preserves all registers.)
3653
;*
3654
OUTC:
3655
        MOVEM.L D0/D1,-(SP)
3656
        MOVE.L  D0,D1
3657
        JSR             DisplayChar
3658
        MOVEM.L (SP)+,D0/D1
3659
        RTS
3660
 
3661
;*
3662
;* ===== Input a character from the console into register D0 (or
3663
;*      return Zero status if there's no character available).
3664
;*
3665
INC:
3666
        MOVE.W  KEYBD,D0        ;is character ready?
3667
        BPL             INCRET0         ;if not, return Zero status
3668
        CLR.W   KEYBD+2         ; clear keyboard strobe line
3669
        AND.W   #0xFF,D0        ;zero out the high bit
3670
        RTS
3671
INCRET0
3672
        MOVEQ   #0,D0
3673
        RTS
3674
 
3675
;*
3676
;* ===== Output character to the host (Port 2) from register D0
3677
;*      (Preserves all registers.)
3678
;*
3679
AUXOUT:
3680
        BTST    #5,UART_LS      ;is port ready for a character?
3681
        BEQ             AUXOUT          ;if not, wait for it
3682
        MOVE.B  D0,UART         ;out it goes.
3683
        RTS
3684
 
3685
;*
3686
;* ===== Input a character from the host into register D0 (or
3687
;*      return Zero status if there's no character available).
3688
;*
3689
AUXIN:
3690
        BTST    #0,UART_LS      ;is character ready?
3691
        BEQ             AXIRET          ;if not, return Zero status
3692
        MOVE.B  UART,D0         ;else get the character
3693
        AND.B   #0x7F,D0        ;zero out the high bit
3694
AXIRET:
3695
        RTS
3696
 
3697
;*
3698
;* ===== Return to the resident monitor, operating system, etc.
3699
;*
3700
BYEBYE:
3701
        JMP             Monitor
3702
;    MOVE.B     #228,D7         ;return to Tutor
3703
;       TRAP    #14
3704
 
3705
INITMSG:
3706
        DC.B    CR,LF,'Gordo\'s MC68000 Tiny BASIC, v1.3',CR,LF,LF,0
3707
OKMSG:
3708
        DC.B    CR,LF,'OK',CR,LF,0
3709
HOWMSG:
3710
        DC.B    'How?',CR,LF,0
3711
WHTMSG:
3712
        DC.B    'What?',CR,LF,0
3713
SRYMSG:
3714
        DC.B    'Sorry.'
3715
CLMSG:
3716
        DC.B    CR,LF,0
3717
;       DC.B    0        ;<- for aligning on a word boundary
3718
        even
3719
 
3720
LSTROM  EQU             $
3721
        ;       end of possible ROM area
3722
 
3723
;**************************************************************************
3724
; The portion of code within STAR lines are modified from Tutor source code
3725
;
3726
;
3727
; HEX2DEC   HEX2DEC convert hex to decimal
3728
; CONVERT BINARY TO DECIMAL  REG D0 PUT IN (A5) BUFFER AS ASCII
3729
 
3730
HEX2DEC  MOVEM.L D1/D2/D3/D4/D5/D6/D7,-(SP)   ;SAVE REGISTERS
3731
         MOVE.L  D0,D7               ;SAVE IT HERE
3732
         BPL.S   HX2DC
3733
         NEG.L   D7             ;CHANGE TO POSITIVE
3734
         BMI.S   HX2DC57        ;SPECIAL CASE (-0)
3735
         MOVE.B  #'-',(A5)+     ;PUT IN NEG SIGN
3736
HX2DC    CLR.W   D4             ;FOR ZERO SURPRESS
3737
         MOVEQ.L   #10,D6         ;COUNTER
3738
HX2DC0   MOVEQ.L   #1,D2          ;VALUE TO SUB
3739
         MOVE.L  D6,D1          ;COUNTER
3740
         SUBQ.L  #1,D1          ;ADJUST - FORM POWER OF TEN
3741
         BEQ.S   HX2DC2         ;IF POWER IS ZERO
3742
HX2DC1   MOVE.W  D2,D3          ;D3=LOWER WORD
3743
         MULU.W    #10,D3
3744
         SWAP.W    D2             ;D2=UPPER WORD
3745
         MULU.W    #10,D2
3746
         SWAP.W    D3             ;ADD UPPER TO UPPER
3747
         ADD.W   D3,D2
3748
         SWAP.W    D2             ;PUT UPPER IN UPPER
3749
         SWAP.W    D3             ;PUT LOWER IN LOWER
3750
         MOVE.W  D3,D2          ;D2=UPPER & LOWER
3751
         SUBQ.L  #1,D1
3752
         BNE     HX2DC1
3753
HX2DC2   CLR.L   D0             ;HOLDS SUB AMT
3754
HX2DC22  CMP.L   D2,D7
3755
         BLT.S   HX2DC3         ;IF NO MORE SUB POSSIBLE
3756
         ADDQ.L  #1,D0          ;BUMP SUBS
3757
         SUB.L   D2,D7          ;COUNT DOWN BY POWERS OF TEN
3758
         BRA.S   HX2DC22        ;DO MORE
3759
HX2DC3   TST.B   D0             ;ANY VALUE?
3760
         BNE.S   HX2DC4
3761
         TST.W   D4             ;ZERO SURPRESS
3762
         BEQ.S   HX2DC5
3763
HX2DC4   ADDI.B  #0x30,D0        ;BINARY TO ASCII
3764
         MOVE.B  D0,(A5)+       ;PUT IN BUFFER
3765
         MOVE.B  D0,D4          ;MARK AS NON ZERO SURPRESS
3766
HX2DC5   SUBQ.L  #1,D6          ;NEXT POWER
3767
         BNE     HX2DC0
3768
         TST.W   D4             ;SEE IF ANYTHING PRINTED
3769
         BNE.S   HX2DC6
3770
HX2DC57  MOVE.B  #'0',(A5)+     ;PRINT AT LEST A ZERO
3771
HX2DC6   MOVE.B  #0,(A5)        ; PUT TERMINATOR
3772
         MOVEM.L (SP)+,D1/D2/D3/D4/D5/D6/D7   ;RESTORE REGISTERS
3773
         RTS                    ;END OF ROUTINE
3774
 
3775
;******************************************************************************

powered by: WebSVN 2.1.0

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