-
Notifications
You must be signed in to change notification settings - Fork 0
/
UMONITOR.X68
executable file
·1887 lines (1804 loc) · 89.5 KB
/
UMONITOR.X68
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
* CECS 525 Group 1 Firmware for the Minimal Computer System 11/4/2011
ORG $0000
DC.L STACK,RESET
DC.L BUS_ER,ADD_ER,IL_ER,DIV0_ER
* $0018
DC.L X_UN,X_UN * Next memory location is $0020
* $0020
DC.L PRV_ER
* $0024
DC.L X_UN,X_UN
DC.L FTRAP,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN * Next memory location is $0074
* $0074
DC.L LVL5_IR,LVL6_IR *initialize autovectors for level 5 and 6 interrupts
DC.L X_UN * Next memory location is $0080
* $0080
DC.L TRAP_0
* $0084
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
* Next memory location is $00B8
* $00B8
DC.L BRKPT,WARM
* $00C0
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
* Next memory location is $0100
* $0100
DC.L LPINTR
* Exception vectors for Unhandled exception (point to general unhandled exception handler)
* $0104
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
DC.L X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN,X_UN
* Next memory location is $0400
* Symbol equates
BS EQU $08 Back_space
CR EQU $0D Carriage_return
LF EQU $0A Line_feed
SPACE EQU $20 Space
WAIT EQU 'W' Wait character (to suspend output)
ESC EQU $1B ASCII escape character (used by TM)
CTRL_A EQU $01 Control_A forces return to monitor
* Device addresses
STACK EQU $4400 Stack_pointer
USTACK EQU $4800 User Stack Pointer
ACIA_1 EQU $8001 Console ACIA control
ACIA_2 EQU ACIA_1 Auxilary ACIA control
ACIAC_2 EQU $80001 Auxilary ACIA control
ACIAD_2 EQU $80003 Auxilary ACIA Data
TRAP_14 EQU $4E4E Code for TRAP #14
MAXCHR EQU 64 Length of input line buffer
CS_PIA EQU $8020 CS_PIA register
PIT EQU $080000 Base address of the PI/T
PGCR EQU PIT+1 Port general control register
PSRR EQU PIT+3 Port service request register
PADDR EQU PIT+5 Port A data direction register
PIVR EQU PIT+$B Port interrupt vector register
PACR EQU PIT+$D Port A control register
PADR EQU PIT+$11 Port A data register
PCDR EQU PIT+$19 Port C data register
PSR EQU PIT+$1B Port status register
***********************************************************************
*
* THESE ARE THE MC68881 INTERNAL REGISTERS FOR THE BASE
* ADDRESS $80000 (MC68881 ADAPTER BOARD)
*
***********************************************************************
MC68881 EQU $80000 MC68881 BASE ADDRESS
COMMAND EQU $0A COMMAND REGISTER
RESPONSE EQU $00 RESPONSE REGISTER
OPER EQU $10 OPERAND REGISTER
COND EQU $0E CONDITION REGISTER
SAVE EQU $04 SAVE REGISTER
RESTOREFPU EQU $06 RESTORE REGISTER
REGSEL EQU $14 REGISTER SELECT
CONTROL EQU $9000 MC68881 CONTROL REGISTER
STATUS EQU $8800 MC68881 STATUS REGISTER
IADDRESS EQU $8400 MC68881 INSTRUCTION ADDRESS REGISTER
TFBIT EQU $0 TRUE/FALSE BIT OF THE RESPONSE REGISTER
DATA EQU $4800 Data origin
LNBUFF DS.B MAXCHR Input line buffer
BUFFEND EQU LNBUFF+MAXCHR-1 End of line buffer
BUFFPT DS.L 1 Pointer to line buffer
PARAMTR DS.L 1 Last parameter from line buffer
ECHO DS.B 1 When clear this enable input echo
U_CASE DS.B 1 Flag for upper case conversion
UTAB DS.L 1 Pointer to user command table
CN_IVEC DS.L 1 Pointer to console input DCB
CN_OVEC DS.L 1 Pointer to console output DCB
TSK_T DS.W 37 Frame for D0-D7, A0-A6, USP, SSP, SW, PC
BP_TAB DS.W 24 Breakpoint table
FIRST DS.B 512 DCB area
BUFFER DS.B 256 256 bytes for I/O buffer
SAVSTAT DS.W 1 Saved status register
SAVPC DS.L 1 Saved Program Counter
FN2 DS.B 1 Variable to hold Fn-2 for Fibonacci sequence
FN1 DS.B 1 Variable to hold Fn-1 for Fibonacci sequence
IS_EMU DS.B 1 Variable to hold boolean to determine EMU or not
TIME DS.W 1 Global Variable to hold 10th of second since reset
BUFFIN DS.B 1 Variable to keep location of current buff2 Input
BUFFOUT DS.B 1 Variable to keep location of current buff2 Output
B2CNT DS.B 1 Variable to keep track of the amount of stuff in the buffer
BUFF2 DS.B 256 Buffer to hold ACIA_2 input characters when interrupted
DUMMY DS.W 1 DUMMY to read CS_PIA into
* Parallel printer-specific variables (Project 5)
BUFFADDR DS.L 1 Space for buffer pointer
BYTECNT DS.L 1 Space for byte counter
FINFLAG DS.B 1 Space for finish flag
*
*************************************************************************
*
* This is the main program which assembles a command in the line
* buffer, removes leading/embedded spaces and interprets it by matching
* it with a command in the user table or the built-in table COMTAB
* All variables are specified with respect to A6
*
ORG $1000 Monitor Origin
RESET: EQU *
LEA.L DATA,A6 A6 points to data area
MOVE.L A6,TSK_T+56(A6) pseudo register A6 in TSK_T must also point to data area (by Eugene)
LEA.L USTACK,A5
MOVE.L A5,USP A7 points to stack register
MOVE.B #0,IS_EMU(A6) If 1 this monitor is for the emulator, 0 is for the hardware
CLR.L UTAB(A6) Reset pointer to user extension table
CLR.B ECHO(A6) Set automatic character echo
CLR.B U_CASE(A6) Clear case conversion flag (UC<-LC)
BSR SETACIA Setup ACIAs
BSR.L SET_DCB Setup DCB table in RAM
BSR CBKPT
*BSR LPOPEN Setup printer
CLR.L TIME(A6) Reset Timer! (make time=0)
CLR.B BUFFIN(A6) Clear the ACIA_2 buff input index
CLR.B BUFFOUT(A6) Clear the ACIA_2 buff output index
CLR.B B2CNT(A6) Clear the ACIA_2 buff data count
BSR NEWLINE
LEA.L BANNER(PC),A4
BSR PSTRING
BSR NEWLINE
LEA.L MODIFY(PC),A4
BSR PSTRING
BSR NEWLINE
LEA.L WHY(PC),A4
BSR PSTRING
BSR NEWLINE
LEA.L WHERE(PC),A4
BSR PSTRING
BSR NEWLINE
LEA.L ADDRE(PC),A4
BSR PSTRING
BSR NEWLINE
MOVE.L #$3000,A0 A0 points to extension ROM
MOVE.L (A0),D0 Read first longword in extension ROM
CMP.L #'ROM2',D0 If extension begins with 'ROM2' then
BNE.S NO_EXT call the subroutine at EXT_ROM+8
JSR 8(A0) else continue
NO_EXT: NOP Two NOPs to allow for a future
NOP call to an initialization routine
CLR.L D7 Warm entry point - clear error flag
BSR NEWLINE Print a newline
*BSR LOGIN Make sure user logs in with a valid u/p
ORI.W #$0700,SR Initialize the interrupt mask to DISABLE interrupts
WARM: CLR.L D7 Warm entry point - clear error flag
BSR NEWLINE Print a newline
BSR GETLINE Get a command line
BSR TIDY Tidy up input buffer contents
BSR EXECUTE Interpret command
BRA WARM Repeat indefinitely
*
* LOGIN - Authenticate before allowing use of the 68k
* To-do:
* - Validate username
* - Get password
* - Make password display as all *'s
* - validate password
* - if 3 failed attempts, infinite loop
* - Fix backspacing problem in GETLINE
*
* ASKUNAME DC.B 'Username: ',0,0
* ASKPWORD DC.B 'Password: ',0,0
* VUNAME DC.B 'group1',0
* VPWORD DC.B 'password',0
* INVUN DC.B 'Invalid username...",0,0
* INVPW DC.B 'Invalid password...",0,0
LOGIN EQU *
MOVE.L #0,D5 Use D5 to store the number of incorrect attempts
ASKUN BSR NEWLINE
LEA.L ASKUNAME,A4 Ask for a username
BSR PSTRING
CLR.B ECHO(A6)
BSR GETLINE Get username
LEA VUNAME,A4 Load the address of the valid username to A4
BSR VALID8 Validate the username
CMP #1,D0 Is it valid?
BEQ PWO If so, ask for the password
BSR NEWLINE Otherwise, ask for them to try again
LEA.L INVUN,A4
BSR PSTRING
ADDQ #1,D5 Increment the number of incorrect attempts
CMP #3,D5 Have we reached max attempts?
BNE STOK
BSR LOCKUP If the number of incorrect attempts is 3, lock up
STOK BRA ASKUN
PWO MOVE.L #0,D5 Reset incorrect attempts - 3 tries each @ username and pw
ASKPW BSR NEWLINE
LEA.L ASKPWORD(PC),A4
BSR PSTRING Ask for a password
MOVE.B #2,ECHO(A6)
BSR GETLINE
CLR.B ECHO(A6)
LEA VPWORD,A4 Load the address of the valid password to A4
BSR VALID8 Validate the password
CMP #1,D0 Is it valid?
BEQ ALLGOOD Then, we've successfully authenticated
BSR NEWLINE Otherwise, ask for them to try again
LEA.L INVPW,A4
BSR PSTRING
ADDQ #1,D5 Increment the number of incorrect attempts
CMP #3,D5 Have we reached max attempts?
BNE STOK2
BSR LOCKUP If the number of incorrect attempts is 3, lock up
STOK2 BRA ASKPW
ALLGOOD RTS
*
***************************************************************************
* LOCKUP - Tells the user theyve been locked out and enters an infinite loop
*
LOCKUP EQU *
BSR NEWLINE
LEA.L LOCKED(PC),A4 ; Tell the user they've been locked out
BSR PSTRING
LOCKLP NOP ; Infinite loop
BRA LOCKLP
RTS ; Just to be safe
*
*************************************************************************
* VALID8 - Validate the entered username from the LOGIN subroutine
* Preconditions:
* 1. GETLINE was executed immediately before branching to this
* subroutine. (Implies A1 points to start
* of GETLINE buffer, A2 points to end of buffer, and
* A3 points to the next available spot in the buffer)
* 2. VUSER is a valid null-terminated string that
* defines the valid username for the 68k firmware, and
* VPWORD is a valid null-terminated string that
* defines the valid password for the 68k firmware.
* 3. A4 contains the start address of the string we're comparing the
* user input to
* Postconditions:
* 3. D0 will be either a 1 or 0 indicating TRUE or
* FALSE, respectively.
* Pseudocode:
* Set D0 to true; If we find a discrepancy, we'll set to false
* Set offset to 0; Offset from beginning of uname string and test string
* Loop until nul char is reached in either test str or uname str
* if str[offset] == uname[offset] then increment offset and continue;
* else set D0 to false and branch to END of subroutine
* END LOOP
* Is str[offset] == uname[offset == null_char?
* yes - branch to END of subroutine (true)
* no - set D0 to false
* RTS
*
VALID8 EQU *
MOVE.L #1,D0 Set D0 to true to start
VLOOP CMP.B #0,(A4) Check to see if character in string is null
BNE NOTNULL If its not null, continue
CMP.B #$0D,(A1) Check to see if the user input is newline
BEQ DONE If it is, then we are done, return true...
MOVE.L #0,D0 If str1[char] is null, and str2[char] is not new line, return false
BRA DONE
NOTNULL CMP.B (A1)+,(A4)+ Compare the characters and postincrement
BNE SETF If they're not equal, set false flag
BRA VLOOP Loop
SETF MOVE.L #0,D0 Sets our D0 flag to false
DONE RTS
*
*************************************************************************
*
* Some initialization and basic routines
*
SETACIA EQU * Setup ACIA parameters
LEA.L ACIA_1,A0 A0 points to console ACIA
MOVE.B #$03,(A0) Reset ACIA1
MOVE.B #$03,1(A0) Reset ACIA2
MOVE.B #$19,(A0) Set up ACIA1 constants (no IRQ,
MOVE.B #$19,1(A0) RTS* low, 8 bit, no parity, 1 stop)
*MOVE.B #$03,ACIAC_2 Reset ACIA2
*MOVE.B #$99,ACIAC_2 Set up ACIA2 constants (use IRQ, RTS* low, 8 bit, no parity, 1 stop)
RTS Return
*
NEWLINE EQU * Move cursor to start of newline
MOVEM.L A4,-(A7) Save A4
LEA.L CRLF(PC),A4 Point to CR/LF string
BSR.S PSTRING Print it
MOVEM.L (A7)+,A4 Restore A4
RTS Return
*
PSTRING EQU * Display the string pointed at by A4
MOVE.L D0,-(A7) Save D0
PS1 MOVE.B (A4)+,D0 Get character to be printed
BEQ.S PS2 If null then return
BSR PUTCHAR Else print it
BRA PS1 Continue
PS2 MOVE.L (A7)+,D0 Restore D0 and exit
RTS
*
HEADING BSR NEWLINE Same as PSTRING but with newline
BSR PSTRING
BRA NEWLINE
*
*************************************************************************
*
* GETLINE inputs a string of characters into a line buffer
* A3 points to next free entry in line buffer
* A2 points to end of buffer
* A1 points to start of buffer
* D0 holds character to be stored
*
GETLINE LEA.L LNBUFF(A6),A1 A1 points to start of line buffer
LEA.L (A1),A3 A3 points to start (initially)
LEA.L MAXCHR(A1),A2 A2 points to end of buffer
GETLN2 BSR GETCHAR Get a character
CMP.B #CTRL_A,D0 If control_A then reject this line
BEQ.S GETLN5 and get another line
CMP.B #BS,D0 If back_space then move back pointer
BNE.S GETLN3 Else skip past wind-back routine
CMP.L A1,A3 First check for empty buffer
BEQ GETLN2 If buffer empty then continue
LEA -1(A3),A3 Else decrement buffer pointer
BRA GETLN2 and continue with next character
GETLN3 MOVE.B D0,(A3)+ Store character and update pointer
CMP.B #CR,D0 Test for command terminator
BNE.S GETLN4 If not CR then skip past exit
BRA NEWLINE Else new line before next operation
GETLN4 CMP.L A2,A3 Test for buffer overflow
BNE GETLN2 If buffer not full then continue
GETLN5 BSR NEWLINE Else move to next line and
BRA GETLINE repeat this routine
*
*************************************************************************
*
* TIDY cleans up the line buffer by removing leading spaces and multiple
* spaces between parameters. At the end of TIDY, BUFFPT points to
* the first parameter following the command.
* A0 = pointer to line buffer. A1 = pointer to cleaned up buffer
*
TIDY LEA.L LNBUFF(A6),A0 A0 points to line buffer
LEA.L (A0),A1 A1 points to start of line buffer
TIDY1 MOVE.B (A0)+,D0 Read character from line buffer
CMP.B #SPACE,D0 Repeat until the first non-space
BEQ TIDY1 character is found
LEA.L -1(A0),A0 Move pointer back to first char
TIDY2 MOVE.B (A0)+,D0 Move the string left to remove
MOVE.B D0,(A1)+ any leading spaces
CMP.B #SPACE,D0 Test for embedded space
BNE.S TIDY4 If not space then test for EOL
TIDY3 CMP.B #SPACE,(A0)+ If space skip multiple embedded
BEQ TIDY3 spaces
LEA.L -1(A0),A0 Move back pointer
TIDY4 CMP.B #CR,D0 Test for end_of_line (EOL)
BNE TIDY2 If not EOL then read next char
LEA.L LNBUFF(A6),A0 Restore buffer pointer
TIDY5 CMP.B #CR,(A0) Test for EOL
BEQ.S TIDY6 If EOL then exit
CMP.B #SPACE,(A0)+ Test for delimiter
BNE TIDY5 Repeat until delimiter or EOL
TIDY6 MOVE.L A0,BUFFPT(A6) Update buffer pointer
RTS
*
*************************************************************************
*
* EXECUTE matches the first command in the line buffer with the
* commands in a command table. An external table pointed at by
* UTAB is searched first and then the in-built table, COMTAB.
*
EXECUTE TST.L UTAB(A6) Test pointer to user table
BEQ.S EXEC1 If clear then try built-in table
MOVE.L UTAB(A6),A3 Else pick up pointer to user table
BSR.S SEARCH Look for command in user table
BCC.S EXEC1 If not found then try internal table
MOVE.L (A3),A3 Else get absolute address of command
JMP (A3) from user table and execute it
*
EXEC1 LEA.L COMTAB(PC),A3 Try built-in command table
BSR.S SEARCH Look for command in built-in table
BCS.S EXEC2 If found then execute command
LEA.L ERMES2(PC),A4 Else print "invalid command"
BRA.L PSTRING and return
EXEC2 MOVE.L (A3),A3 Get the relative command address
LEA.L COMTAB(PC),A4 pointed at by A3 and add it to
ADD.L A4,A3 the PC to generate the actual
JMP (A3) command address. Then execute it.
*
SEARCH EQU * Match the command in the line buffer
CLR.L D0 with command table pointed at by A3
MOVE.B (A3),D0 Get the first character in the
BEQ.S SRCH7 current entry. If zero then exit
LEA.L 6(A3,D0.W),A4 Else calculate address of next entry
MOVE.B 1(A3),D1 Get number of characters to match
LEA.L LNBUFF(A6),A5 A5 points to command in line buffer
MOVE.B 2(A3),D2 Get first character in this entry
CMP.B (A5)+,D2 from the table and match with buffer
BEQ.S SRCH3 If match then try rest of string
SRCH2 MOVE.L A4,A3 Else get address of next entry
BRA SEARCH and try the next entry in the table
SRCH3 SUB.B #1,D1 One less character to match
BEQ.S SRCH6 If match counter zero then all done
LEA.L 3(A3),A3 Else point to next character in table
SRCH4 MOVE.B (A3)+,D2 Now match a pair of characters
CMP.B (A5)+,D2
BNE SRCH2 If no match then try next entry
SUB.B #1,D1 Else decrement match counter and
BNE SRCH4 repeat until no chars left to match
SRCH6 LEA.L -4(A4),A3 Calculate address of command entry
OR.B #1,CCR point. Mark carry flag as success
RTS and return
SRCH7 AND.B #$FE,CCR Fail - clear carry to indicate
RTS command not found and return
*************************************************************************
*
* FIBGEN: Generates and displays the Fibonaci sequence with the sequence
* length specified by the user, this function is fun as task #17 of Trap 0
*
FIBGEN LEA.L FMES1(PC),A4 Point to first of FibGen Instruction strings, store in A4
BSR PSTRING Print string pointed to in A4
BSR NEWLINE Print NewLine
LEA.L FMES2(PC),A4 Point to second of FibGen Instruction strings, store in A4
BSR PSTRING Print string pointed to in A4
BSR NEWLINE Print NewLine
LEA.L FMES3(PC),A4 Point to third of FibGen Instruction strings, store in A4
BSR PSTRING Print string pointed to in A4
BSR NEWLINE Print NewLine
LEA.L FMES4(PC),A4 Point to fourth of FibGen Instruction strings, store in A4
BSR PSTRING Print string pointed to in A4
BSR NEWLINE Print NewLine
FIBLOOP BSR NEWLINE Print NewLine
LEA.L FMES5(PC),A4 Point to user input prompt string, store in A4
BSR PSTRING Print string pointed to in A4
BSR GETCHAR Get a character from input device
SUB.B #$30,D0 Convert to binary
CMP #0,D0 if user chose "0" exit and end
BEQ FIBEND
BSR NEWLINE Print newline
CMP #7,D0 Compare the user input (in DO)
BGT BADINPUT to 7, if greather than, they gave bad input
CMP #0,D0 Compare the user input (in D0)
BLT BADINPUT to 0, if less than, they gave bad input
MOVE.B #0,FN2(A6) intialize fibonacci counters
MOVE.B #1,FN1(A6) Fn-2 = 0, Fn-1 = 1
MOVE.B D0,D3 COUNT = D0 (the users choice of lines)
MOVE.B #'0',D0 print the first character of the sequence
BSR PUTCHAR
CMP.B #2,D3 if COUNT < 2 then COUNT = 1
BLT FIBLOOP we're done so ask for input again
MOVE.B #' ',D0 print the second character of the sequence
BSR PUTCHAR and a space
MOVE.B #'1',D0
BSR PUTCHAR
CMP.B #2,D3 If count == 2, we're done so ask for input a again
BEQ FIBLOOP
SUBI.B #2,D3 subtract 2 from the count the user gave us
*to make up for the first 2 numbers in the sequence already being printed
FIBFOR CMP.B #0,D3 If D3 == 0, then we've printed the entire seqence
BEQ FIBLOOP So ask for input from the user again
SUBI.B #1,D3 If D3 != 0, then decrement D3 and print next value in sequence
MOVE.B #' ',D0 display a blank space between number
BSR PUTCHAR using PUTCHAR
CLR D0 Clear D0
ADD.B FN2(A6),D0 add FN2 to FN1
ADD.B FN1(A6),D0 store this sum in D0 to display
ADD.B #$30,D0 Max number an ASCII character
BSR PUTCHAR Display character
SUB.B #$30,D0 convert ASCII back to value
MOVE.B FN1(A6),FN2(A6) FN2= previous FN1
MOVE.B D0,FN1(A6) FN1= prevous fibonacci number
BRA FIBFOR Branch always to the start of the For loop
BADINPUT BSR NEWLINE Print newline
LEA.L FMES6(PC),A4 Move pointer to bad input error message
BSR PSTRING Print string pointed to in A4
BSR NEWLINE Print NewLine
BRA FIBLOOP User entered bad data so ask for input again
FIBEND BSR NEWLINE Print newline
RTS
*
*************************************************************************
*
* Basic input routines
* HEX = Get one hexadecimal character into D0
* BYTE = Get two hexadecimal characters into D0
* WORD = Get four hexadecimal characters into D0
* LONGWD = Get eight hexadecimal characters into D0
* PARAM = Get a longword from the line buffer into D0
* Bit 0 of D7 is set to indicate a hexadecimal input error
*
HEX BSR GETCHAR Get a character from input device
SUB.B #$30,D0 Convert to binary
BMI.S NOT_HEX If less than $30 then exit with error
CMP.B #$09,D0 Else test for number (0 to 9)
BLE.S HEX_OK If number then exit - success
SUB.B #$07,D0 Else convert letter to hex
CMP.B #$0F,D0 If character in range "A" to "F"
BLE.S HEX_OK then exit successfully
NOT_HEX OR.B #1,D7 Else set error flag
HEX_OK RTS and return
*
BYTE MOVE.L D1,-(A7) Save D1
BSR HEX Get first hex character
ASL.B #4,D0 Move it to MS nybble position
MOVE.B D0,D1 Save MS nybble in D1
BSR HEX Get second hex character
ADD.B D1,D0 Merge MS and LS nybbles
MOVE.L (A7)+,D1 Restore D1
RTS
*
WORD BSR BYTE Get upper order byte
ASL.W #8,D0 Move it to MS position
BRA BYTE Get LS byte and return
*
LONGWD BSR WORD Get upper order word
SWAP D0 Move it to MS position
BRA WORD Get lower order word and return
*
* PARAM reads a parameter from the line buffer and puts it in both
* PARAMTR(A6) and D0. Bit 1 of D7 is set on error.
*
PARAM MOVE.L D1,-(A7) Save D1
CLR.L D1 Clear input accumulator
MOVE.L BUFFPT(A6),A0 A0 points to parameter in buffer
PARAM1 MOVE.B (A0)+,D0 Read character from line buffer
CMP.B #SPACE,D0 Test for delimiter
BEQ.S PARAM4 The permitted delimiter is a
CMP.B #CR,D0 space or a carriage return
BEQ.S PARAM4 Exit on either space or C/R
ASL.L #4,D1 Shift accumulated result 4 bits left
SUB.B #$30,D0 Convert new character to hex
BMI.S PARAM5 If less than $30 then not-hex
CMP.B #$09,D0 If less than 10
BLE.S PARAM3 then continue
SUB.B #$07,D0 Else assume $A - $F
CMP.B #$0F,D0 If more than $F
BGT.S PARAM5 then exit to error on not-hex
PARAM3 ADD.B D0,D1 Add latest nybble to total in D1
BRA PARAM1 Repeat until delimiter found
PARAM4 MOVE.L A0,BUFFPT(A6) Save pointer in memory
MOVE.L D1,PARAMTR(A6) Save parameter in memory
MOVE.L D1,D0 Put parameter in D0 for return
BRA.S PARAM6 Return without error
PARAM5 OR.B #2,D7 Set error flag before return
PARAM6 MOVE.L (A7)+,D1 Restore working register
RTS Return with error
*
*************************************************************************
*
* Output routines
* OUT1X = print one hexadecimal character
* OUT2X = print two hexadecimal characters
* OUT4X = print four hexadecimal characters
* OUT8X = print eight hexadecimal characters
* In each case, the data to be printed is in D0
*
OUT1X MOVE.W D0,-(A7) Save D0
AND.B #$0F,D0 Mask off MS nybble
ADD.B #$30,D0 Convert to ASCII
CMP.B #$39,D0 ASCII = HEX + $30
BLS.S OUT1X1 If ASCII <= $39 then print and exit
ADD.B #$07,D0 Else ASCII := HEX + 7
OUT1X1 BSR PUTCHAR Print the character
MOVE.W (A7)+,D0 Restore D0
RTS
*
OUT2X ROR.B #4,D0 Get MS nybble in LS position
BSR OUT1X Print MS nybble
ROL.B #4,D0 Restore LS nybble
BRA OUT1X Print LS nybble and return
*
OUT4X ROR.W #8,D0 Get MS byte in LS position
BSR OUT2X Print MS byte
ROL.W #8,D0 Restore LS byte
BRA OUT2X Print LS byte and return
*
OUT8X SWAP D0 Get MS word in LS position
BSR OUT4X Print MS word
SWAP D0 Restore LS word
BRA OUT4X Print LS word and return
*
*************************************************************************
*
* JUMP causes execution to begin at the address in the line buffer
*
JUMP BSR PARAM Get address from buffer
TST.B D7 Test for input error
BNE.S JUMP1 If error flag not zero then exit
TST.L D0 Else test for missing address
BEQ.S JUMP1 field. If no address then exit
MOVE.L D0,A0 Put jump address in A0 and call the
JMP (A0) subroutine. User to supply RTS!!
JUMP1 LEA.L ERMES1(PC),A4 Here for error - display error
BRA PSTRING message and return
*
*************************************************************************
*
* Display the contents of a memory location and modify it
*
MEMORY BSR PARAM Get start address from line buffer
TST.B D7 Test for input error
BNE.S MEM3 If error then exit
MOVE.L D0,A3 A3 points to location to be opened
MEM1 BSR NEWLINE
BSR.S ADR_DAT Print current address and contents
BSR.S PSPACE update pointer, A3, and O/P space
BSR GETCHAR Input char to decide next action
CMP.B #CR,D0 If carriage return then exit
BEQ.S MEM3 Exit
CMP.B #'-',D0 If "-" then move back
BNE.S MEM2 Else skip wind-back procedure
LEA.L -4(A3),A3 Move pointer back 2+2
BRA MEM1 Repeat until carriage return
MEM2 CMP.B #SPACE,D0 Test for space (= new entry)
BNE.S MEM1 If not space then repeat
BSR WORD Else get new word to store
TST.B D7 Test for input error
BNE.S MEM3 If error then exit
MOVE.W D0,-2(A3) Store new word
BRA MEM1 Repeat until carriage return
MEM3 RTS
*
ADR_DAT MOVE.L D0,-(A7) Print the contents of A3 and the
MOVE.L A3,D0 word pointed at by A3.
BSR OUT8X and print current address
BSR.S PSPACE Insert delimiter
MOVE.W (A3),D0 Get data at this address in D0
BSR OUT4X and print it
LEA.L 2(A3),A3 Point to next address to display
MOVE.L (A7)+,D0 Restore D0
RTS
*
PSPACE MOVE.B D0,-(A7) Print a single space
MOVE.B #SPACE,D0
BSR PUTCHAR
MOVE.B (A7)+,D0
RTS
*
*************************************************************************
*
* LOAD Loads data formatted in hexadecimal "S" format from Port 2
* NOTE - I/O is automatically redirected to the aux port for
* loader functions. S1 or S2 records accepted
*
LOAD MOVE.L CN_OVEC(A6),-(A7) Save current output device name
MOVE.L CN_IVEC(A6),-(A7) Save current input device name
MOVE.L #DCB4,CN_OVEC(A6) Set up aux ACIA as output
MOVE.L #DCB3,CN_IVEC(A6) Set up aux ACIA as input
ADD.B #1,ECHO(A6) Turn off character echo
BSR NEWLINE Send newline to host
BSR DELAY Wait for host to "settle"
BSR DELAY
MOVE.L BUFFPT(A6),A4 Any string in the line buffer is
LOAD1 MOVE.B (A4)+,D0 transmitted to the host computer
BSR PUTCHAR before the loading begins
CMP.B #CR,D0 Read from the buffer until EOL
BNE LOAD1
BSR NEWLINE Send newline before loading
LOAD2 BSR GETCHAR Records from the host must begin
CMP.B #'S',D0 with S1/S2 (data) or S9/S8 (term)
BNE.S LOAD2 Repeat GETCHAR until char = "S"
BSR GETCHAR Get character after "S"
CMP.B #'9',D0 Test for the two terminators S9/S8
BEQ.S LOAD3 If S9 record then exit else test
CMP.B #'8',D0 for S8 terminator. Fall through to
BNE.S LOAD6 exit on S8 else continue search
LOAD3 EQU * Exit point from LOAD
MOVE.L (A7)+,CN_IVEC(A6) Clean up by restoring input device
MOVE.L (A7)+,CN_OVEC(A6) and output device name
CLR.B ECHO(A6) Restore input character echo
BTST #0,D7 Test for input errors
BEQ.S LOAD4 If no I/P error then look at checksum
LEA.L ERMES1(PC),A4 Else point to error message
BSR PSTRING Print it
LOAD4 BTST #3,D7 Test for checksum error
BEQ.S LOAD5 If clear then exit
LEA.L ERMES3(PC),A4 Else point to error message
BSR PSTRING Print it and return
LOAD5 RTS
*
LOAD6 CMP.B #'1',D0 Test for S1 record
BEQ.S LOAD6A If S1 record then read it
CMP.B #'2',D0 Else test for S2 record
BNE.S LOAD2 Repeat until valid header found
CLR.B D3 Read the S2 byte count and address,
BSR.S LOAD8 clear the checksum
SUB.B #4,D0 Calculate size of data field
MOVE.B D0,D2 D2 contains data bytes to read
CLR.L D0 Clear address accumulator
BSR.S LOAD8 Read most sig byte of address
ASL.L #8,D0 Move it one byte left
BSR.S LOAD8 Read the middle byte of address
ASL.L #8,D0 Move it one byte left
BSR.S LOAD8 Read least sig byte of address
MOVE.L D0,A2 A2 points to destination of record
BRA.S LOAD7 Skip past S1 header loader
LOAD6A CLR.B D3 S1 record found - clear checksum
BSR.S LOAD8 Get byte and update checksum
SUB.B #3,D0 Subtract 3 from record length
MOVE.B D0,D2 Save byte count in D2
CLR.L D0 Clear address accumulator
BSR.S LOAD8 Get MS byte of load address
ASL.L #8,D0 Move it to MS position
BSR.S LOAD8 Get LS byte in D2
MOVE.L D0,A2 A2 points to destination of data
LOAD7 BSR.S LOAD8 Get byte of data for loading
MOVE.B D0,(A2)+ Store it
SUB.B #1,D2 Decrement byte counter
BNE LOAD7 Repeat until count = 0
BSR.S LOAD8 Read checksum
ADD.B #1,D3 Add 1 to total checksum
BEQ LOAD2 If zero then start next record
OR.B #%00001000,D7 Else set checksum error bit,
BRA LOAD3 restore I/O devices and return
*
LOAD8 BSR BYTE Get a byte
ADD.B D0,D3 Update checksum
RTS and return
*
*************************************************************************
*
* DUMP Transmit S1 formatted records to host computer
* A3 = Starting address of data block
* A2 = End address of data block
* D1 = Checksum, D2 = current record length
*
DUMP BSR RANGE Get start and end address
TST.B D7 Test for input error
BEQ.S DUMP1 If no error then continue
LEA.L ERMES1(PC),A4 Else point to error message,
BRA PSTRING print it and return
DUMP1 CMP.L A3,D0 Compare start and end addresses
BPL.S DUMP2 If positive then start < end
LEA.L ERMES7(PC),A4 Else print error message
BRA PSTRING and return
DUMP2 MOVE.L CN_OVEC(A6),-(A7) Save name of current output device
MOVE.L #DCB4,CN_OVEC(A6) Set up Port 2 as output device
BSR NEWLINE Send newline to host and wait
BSR.S DELAY
MOVE.L BUFFPT(A6),A4 Before dumping, send any string
DUMP3 MOVE.B (A4)+,D0 in the input buffer to the host
BSR PUTCHAR Repeat
CMP.B #CR,D0 Transmit char from buffer to host
BNE DUMP3 Until char = C/R
BSR NEWLINE
BSR.S DELAY Allow time for host to settle
ADDQ.L #1,A2 A2 contains length of record + 1
DUMP4 MOVE.L A2,D2 D2 points to end address
SUB.L A3,D2 D2 contains bytes left to print
CMP.L #17,D2 If this is not a full record of 16
BCS.S DUMP5 then load D2 with record size
MOVEQ #16,D2 Else preset byte count to 16
DUMP5 LEA.L HEADER(PC),A4 Point to record header
BSR PSTRING Print header
CLR.B D1 Clear checksum
MOVE.B D2,D0 Move record length to output register
ADD.B #3,D0 Length includes address + count
BSR.S DUMP7 Print number of bytes in record
MOVE.L A3,D0 Get start address to be printed
ROL.W #8,D0 Get MS byte in LS position
BSR.S DUMP7 Print MS byte of address
ROR.W #8,D0 Restore LS byte
BSR.S DUMP7 Print LS byte of address
DUMP6 MOVE.B (A3)+,D0 Get data byte to be printed
BSR.S DUMP7 Print it
SUB.B #1,D2 Decrement byte count
BNE DUMP6 Repeat until all this record printed
NOT.B D1 Complement checksum
MOVE.B D1,D0 Move to output register
BSR.S DUMP7 Print checksum
BSR NEWLINE
CMP.L A2,A3 Have all records been printed?
BNE DUMP4 Repeat until all done
LEA.L TAIL(PC),A4 Point to message tail (S9 record)
BSR PSTRING Print it
MOVE.L (A7)+,CN_OVEC(A6) Restore name of output device
RTS and return
*
DUMP7 ADD.B D0,D1 Update checksum, transmit byte
BRA OUT2X to host and return
*
RANGE EQU * Get the range of addresses to be
CLR.B D7 transmitted from the buffer
BSR PARAM Get starting address
MOVE.L D0,A3 Set up start address in A3
BSR PARAM Get end address
MOVE.L D0,A2 Set up end address in A2
RTS
*
DELAY EQU * Provide a time delay for the host
MOVEM.L D0/A4,-(A7) to settle. Save working registers
MOVE.L #$4000,D0 Set up delay constant
DELAY1 SUB.L #1,D0 Count down (8 clk cycles)
BNE DELAY1 Repeat until zero (10 clk cycles)
MOVEM.L (A7)+,D0/A4 Restore working registers
RTS
*
*************************************************************************
*
* TM Enter transparant mode (All communication to go from terminal to
* the host processor until escape sequence entered). End sequence
* = ESC, E. A newline is sent to the host to "clear it down".
*
TM MOVE.B #$55,ACIA_1 Force RTS* high to re-route data
ADD.B #1,ECHO(A6) Turn off character echo
TM1 BSR GETCHAR Get character
CMP.B #ESC,D0 Test for end of TM mode
BNE TM1 Repeat until first escape character
BSR GETCHAR Get second character
CMP.B #'E',D0 If second char = E then exit TM
BNE TM1 Else continue
MOVE.L CN_OVEC(A6),-(A7) Save output port device name
MOVE.L #DCB4,CN_OVEC(A6) Get name of host port (aux port)
BSR NEWLINE Send newline to host to clear it
MOVE.L (A7)+,CN_OVEC(A6) Restore output device port name
CLR.B ECHO(A6) Restore echo mode
MOVE.B #$15,ACIA_1 Restore normal ACIA mode (RTS* low)
RTS
*
*************************************************************************
*
* This routine sets up the system DCBs in RAM using the information
* stored in ROM at address DCB_LST. This is called at initialization.
* CN_IVEC contains the name "DCB1" and IO_VEC the name "DCB2"
*
SET_DCB MOVEM.L A0-A3/D0-D3,-(A7) Save all working registers
LEA.L FIRST(A6),A0 Pointer to first DCB destination in RAM
LEA.L DCB_LST(PC),A1 A1 points to DCB info block in ROM
MOVE.W #5,D0 6 DCBs to set up
ST_DCB1 MOVE.W #15,D1 16 bytes to move per DCB header
ST_DCB2 MOVE.B (A1)+,(A0)+ Move the 16 bytes of a DCB header
DBRA D1,ST_DCB2 from ROM to RAM
MOVE.W (A1)+,D3 Get size of parameter block (bytes)
MOVE.W D3,(A0) Store size in DCB in RAM
LEA.L 2(A0,D3.W),A0 A0 points to tail of DCB in RAM
LEA.L 4(A0),A3 A3 contains address of next DCB in RAM
MOVE.L A3,(A0) Store pointer to next DCB in this DCB
LEA.L (A3),A0 A0 now points at next DCB in RAM
DBRA D0,ST_DCB1 Repeat until all DCBs set up
LEA.L -4(A3),A3 Adjust A3 to point to last DCB pointer
CLR.L (A3) and force last pointer to zero
MOVE.L #DCB1,CN_IVEC(A6) Set up vector to console input DCB
MOVE.L #DCB2,CN_OVEC(A6) Set up vector to console output DCB
MOVEM.L (A7)+,A0-A3/D0-D3 Restore registers
RTS
*
*************************************************************************
*
* IO_REQ handles all input/output transactions. A0 points to DCB on
* entry. IO_REQ calls the device driver whose address is in the DCB.
*
IO_REQ MOVEM.L A0-A1,-(A7) Save working registers
LEA.L 8(A0),A1 A1 points to device handler field in DCB
MOVE.L (A1),A1 A1 contains device handler address
JSR (A1) Call device handler
MOVEM.L (A7)+,A0-A1 Restore working registers
RTS
*
*************************************************************************
*
* CON_IN handles input from the console device
* This is the device driver used by DCB1. Exit with input in D0
*
CON_IN MOVEM.L D1/A1,-(A7) Save working registers
LEA.L 12(A0),A1 Get pointer to ACIA from DCB
MOVE.L (A1),A1 Get address of ACIA in A1
CLR.B 19(A0) Clear logical error in DCB
CON_I1 MOVE.B (A1),D1 Read ACIA status
BTST #0,D1 Test RDRF
BEQ CON_I1 Repeat until RDRF true
MOVE.B D1,18(A0) Store physical status in DCB
AND.B #%011110100,D1 Mask to input error bits
BEQ.S CON_I2 If no error then skip update
MOVE.B #1,19(A0) Else update logical error
CON_I2 MOVE.B 2(A1),D0 Read input from ACIA
MOVEM.L (A7)+,A1/D1 Restore working registers
RTS
*
*************************************************************************
*
* This is the device driver used by DCB2. Output in D0
* The output can be halted or suspended
*
CON_OUT MOVEM.L A1/D1-D2,-(A7) Save working registers
LEA.L 12(A0),A1 Get pointer to ACIA from DCB
MOVE.L (A1),A1 Get address of ACIA in A1
CLR.B 19(A0) Clear logical error in DCB
CON_OT1 MOVE.B (A1),D1 Read ACIA status
BTST #0,D1 Test RDRF bit (any input?)
BEQ.S CON_OT3 If no input then test output status
MOVE.B 2(A1),D2 Else read the input
AND.B #%01011111,D2 Strip parity and bit 5
CMP.B #WAIT,D2 and test for a wait condition
BNE.S CON_OT3 If not wait then ignore and test O/P
CON_OT2 MOVE.B (A1),D2 Else read ACIA status register
BTST #0,D2 and poll ACIA until next char received
BEQ CON_OT2
CON_OT3 BTST #1,D1 Repeat
BEQ CON_OT1 until ACIA Tx ready
MOVE.B D1,18(A0) Store status in DCB physical error
MOVE.B D0,2(A1) Transmit output
MOVEM.L (A7)+,A1/D1-D2 Restore working registers
RTS
*
*************************************************************************
*
* AUX_IN and AUX_OUT are simplified versions of CON_IN and
* CON_OUT for use with the port to the host processor
*
AUX_IN LEA.L 12(A0),A1 Get pointer to aux ACIA from DCB
MOVE.L (A1),A1 Get address of aux ACIA
AUX_IN1 BTST.B #0,(A1) Test for data ready
BEQ AUX_IN1 Repeat until ready
MOVE.B 2(A1),D0 Read input
RTS
*
AUX_OUT LEA.L 12(A0),A1 Get pointer to aux ACIA from DCB
MOVE.L (A1),A1 Get address of aux ACIA
AUX_OT1 BTST.B #1,(A1) Test for ready to transmit
BEQ AUX_OT1 Repeat until transmitter ready
MOVE.B D0,2(A1) Transmit data
RTS
*
*************************************************************************
*
* GETCHAR gets a character from the console device
* This is the main input routine and uses the device whose name
* is stored in CN_IVEC. Changing this name redirects input.
*
GETCHAR CMP.B #1,IS_EMU(A6) If this get char is for the emulator
BEQ GETCHAR_EMU go to the emulator getchar routine,else continue
MOVE.L A0,-(A7) Save working register
MOVE.L CN_IVEC(A6),A0 A0 points to name of console DCB
BSR IO_OPEN Open console (get DCB address in A0)
BTST #3,D7 D7(3) set if open error
BNE.S GETCH3 If error then exit now
BSR IO_REQ Else execute I/O transaction
AND.B #$7F,D0 Strip msb of input
TST.B U_CASE(A6) Test for upper -> lower case conversion
BNE.S GETCH2 If flag not zero do not convert case
BTST #6,D0 Test input for lower case
BEQ.S GETCH2 If upper case then skip conversion
AND.B #%11011111,D0 Else clear bit 5 for upper case conv
GETCH2 CMP.B #1, ECHO(A6)
BEQ.S GETCH4
CMP.B #0, ECHO(A6)
BEQ.S GETCH3
MOVE.B D0,D2
MOVE.B #'*',D0
BSR.S PUTCHAR
MOVE D2,D0
BRA.S GETCH4
GETCH3 BSR.S PUTCHAR
GETCH4 MOVE.L (A7)+,A0 Restore working register
RTS and return
GETCHAR_EMU MOVE.L A0,-(A7) Save working register
MOVE.B #5,D0 Read single ASCII character into D1.B
TRAP #15
MOVE.B D1,D0