-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathsbug.asm
More file actions
1731 lines (1537 loc) · 43.7 KB
/
sbug.asm
File metadata and controls
1731 lines (1537 loc) · 43.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
title "SBUG18 MP-09 MONITOR"
list
;=====================================================
;
; MONITOR PROGRAM FOR THE SOUTHWEST TECHNICAL
; PRODUCTS MP-09 CPU BOARD AS COMMENTED BY....
;
; ALLEN CLARK WALLACE WATSON
; 2502 REGAL OAKS LANE 4815 EAST 97th AVE.
; LUTZ, FLA. 33549 TEMPLE TERRACE, FLA. 33617
; PH. 813-977-0347 PH. 813-985-1359
;
; MODIFIED TO SBUG09 VER 1.8 BY: RANDY JARRETT
; 2561 NANTUCKET DR APT. E
; ATLANTA, GA 30345
; PH. 404-320-1043
;
; Modified by Bob Applegate, bob@corshamtech.com in
; late 2014 to add some extra flexibility at build
; time. Also made it compatible with the AS09
; assembler.
;
; I've added notes in some sections of code while
; working through some of the logic, and left them in
; case they are helpful to others as well.
;
; 1.8.2 has the updated functions to do long sector
; read/writes and other support for NitrOS/9.
;
; Memory map note:
;
; At start-up, the only memory hard-wired to a
; specific address is from FF00 to FFFF which is
; mapped to the upper 256 bytes of the EPROM, probably
; containing SBUG.
;
; The code in the upper 256 bytes will do setup of the
; DAT registers, then the rest of the EPROM is availble.
;
; *** COMMANDS ***
; CONTROL A = ALTER THE "A" ACCUMULATOR
; CONTROL B = ALTER THE "B" ACCUMULATOR
; CONTROL C = ALTER THE CONDITION CODE REGISTER
; CONTROL D = ALTER THE DIRECT PAGE REGISTER
; CONTROL P = ALTER THE PROGRAM COUNTER
; CONTROL U = ALTER USER STACK POINTER
; CONTROL X = ALTER "X" INDEX REGISTER
; CONTROL Y = ALTER "Y" INDEX REGISTER
; B hhhh = SET BREAKPOINT AT LOCATION $hhhh
; D = BOOT A SWTPC 8 INCH FLOPPY SYSTEM
; U = BOOT A SWTPC 5 INCH FLOPPY SYSTEM
; E ssss-eeee = EXAMINE MEMORY FROM STARTING ADDRESS ssss
; -TO ENDING ADDRESS eeee.
; G = CONTINUE EXECUTION FROM BREAKPOINT OR SWI
; L = LOAD TAPE
; M hhhh = EXAMINE AND CHANGE MEMORY LOCATION hhhh
; P ssss-eeee = PUNCH TAPE, START ssss TO END eeee ADDR.
; Q ssss-eeee = TEST MEMORY FROM ssss TO eeee
; R = DISPLAY REGISTER CONTENTS
; S = DISPLAY STACK FROM ssss TO $DFC0
; X = REMOVE ALL BREAKPOINTS
;
; Useful constants
;
false equ 0
true equ ~false
;
;***************************************************
; This is so other files included (if any) can tell
; they are being assembled into SBUG. This should
; always be true.
;
IN_SBUG equ true
;
;***************************************************
; Allow S5 recognition for the L command. Some
; assemblers output S5 instead of S9, but it takes
; more space for S5 processing.
;
ALLOW_S5 equ true
;
;***************************************************
; Include Tiny BASIC in the lower 2K.
;
ENABLE_BASIC equ false
;
;***************************************************
; Include SD card drivers and commands. Note that
; the ENABLE_BASIC option ***MUST*** be false if
; this is true; there just isn't enough space for
; both sets of code.
;
SD_SUPPORT equ true
;
if SD_SUPPORT
if ENABLE_BASIC
error You cannot have both options on!
endif
endif
;
;***************************************************
; This enables/disables tape read control codes.
; This should be true to emulate the original SBUG,
; but false is fine for modern use.
;
READER_CONTROL equ false
;
;***************************************************
; This macro is used to verify that the current
; address meets a required value. Used mostly to
; guarantee changes don't cause entry points to
; move. These are used right before documented
; entry points.
;
VERIFY macro expected
if * != expected
fail Not at requested address (expected)
endif
endm
FORCE macro desired
if * > desired
fail Past expected address (desired)
else
if * < desired
ds desired-*
endif
endif
endm
;
; A test pattern used for sizing
;
TSTPAT equ $55AA ;TEST PATTERN
bss
org $dfc0
STACK ds 2 ;TOP OF INTERNAL STACK / USER VECTOR
SWI3 ds 2 ;SOFTWARE INTERRUPT VECTOR #3
SWI2 ds 2 ;SOFTWARE INTERRUPT VECTOR #2
FIRQ ds 2 ;FAST INTERRUPT VECTOR
IRQ ds 2 ;INTERRUPT VECTOR
SWI ds 2 ;SOFTWARE INTERRUPT VECTOR
SVCVO ds 2 ;SUPERVISOR CALL VECTOR ORGIN
SVCVL ds 2 ;SUPERVISOR CALL VECTOR LIMIT
LRARAM ds 16 ;LRA ADDRESSES
CPORT ds 2 ;RE-VECTORABLE CONTROL PORT
ECHO ds 1 ;ECHO FLAG
BPTBL ds 24 ;BREAKPOINT TABLE BASE ADDR
;
; The original code was hard coded for the I/O base address to
; be at E000, each slot occupied 4 bytes, and the MP-S card
; was always in slot 1. I've added EQUates to set these things.
;
IO_BASE equ $e000 ;usually $E000, but $8000 on unmodified motherboard
IO_SIZE equ 16 ;number of addresses per I/O slot
MPS_SLOT equ 1 ;which slot console MP-S is in
ACIAS equ (MPS_SLOT*IO_SIZE)+IO_BASE ;CONTROL PORT
;
; Disk drive options you can turn on/off. If you
; turn them off, then the command disappears from
; the list.
;
DMAF2 equ false ;SWTPC DMAf2 controller
DC_X equ false ;SWTPC DX-x disk controller
;
; This sets up disk drive addresses. The code
; appears to be suited to a controller occupying
; slots 5 and 6's address space.
;
if DC_X
DISK_SLOT equ 5
DISK_BASE equ (DISK_SLOT*IO_SIZE)+IO_BASE
Comreg equ DISK_BASE+4 ;COMMAND REGISTER
Drvreg equ DISK_BASE ;DRIVE REGISTER
Secreg equ DISK_BASE+6 ;SECTOR REGISTER
Datreg equ DISK_BASE+7 ;DATA REGISTER
endif
;
; Not sure what card this is for but it's in upper
; address space
;
if DMAF2
ADDREG equ $F000 ;ADDRESS REGISTER
CNTREG equ $F002 ;COUNT REGISTER
CCREG equ $F010 ;CHANNEL CONTROL REGISTER
PRIREG equ $F014 ;DMA PRIORITY REGISTER
AAAREG equ $F015 ;???
BBBREG equ $F016 ;???
COMREG equ $F020 ;1791 COMMAND REGISTER
SECREG equ $F022 ;SECTOR REGISTER
DRVREG equ $F024 ;DRIVE SELECT LATCH
CCCREG equ $F040 ;???
endif
;
; The Dynamic Address Translation (DAT) uses 16 write-
; only registers from FFF0 to FFFF. The lower 4 bits
; are the inverse of the values presented to A12-A15,
; while the upper 4 bits are the non-inverted bank
; select (A16-A19).
;
DATREGS equ $FFF0 ;DAT RAM CHIP
;
; Common ASCII characters
;
EOT equ $04
BS equ $08
LF equ $0a
CR equ $0d
;
; Since the Corsham Tech board takes 8K EPROMs but the
; memory space for the EPROM is only 4K, put something
; here so the EPROM programmer will locate the file
; properly in its memory.
;
code
org $e000
db "Don't put anything here"
;
; If you put in the jumper on the Corsham Tech CPU
; board for 4K of EPROM, then the code starts here
; for the lower 2K.
;
org $f000
if ENABLE_BASIC
include "basic.asm"
else
if SD_SUPPORT
jmp SdBoot ;load OS from SD Card
jmp xParInit ;init parallel interface
jmp xParSetWrite ;set for writing
jmp xParSetRead ;set for reading
jmp xParWriteByte ;write one byte
jmp xParReadByte
;
jmp DiskReadSector
jmp DiskWriteSector
jmp DiskStatus
jmp DiskGetDrives
jmp DiskGetMounted
jmp DiskNextMountedDrv
jmp DiskUnmount
jmp DiskMount
jmp DiskDir
jmp DiskDirNext
jmp DiskPing
;
jmp DiskReadLong
jmp DiskWriteLong
include "pario.asm"
include "diskfunc.asm"
else
db "You have 4K of EPROM enabled!"
endif
endif
;
; This is the real start of the 2K monitor...
;
; The vector table to handy functions. It's nice that
; SWTPC did this so the code can move around inside
; SBUG without breaking user programs.
;
code
org $f800
dw MONITOR
dw NEXTCMD
dw INCH
dw INCHE
dw INCHEK
dw OUTCH
dw PDATA
dw PCRLF
dw PSTRNG
dw LRA
;
; These are additional vectors to useful functions within
; SBUG that other programs can use.
;
dw OUT1S ;output a space
dw OUT2H ;output A as 2 hex characters
dw OUT4H ;output X as 4 hex characters
dw BYTE ;input 2 hex digits, return in A
dw IN1ADR ;input 4 hex digits, return in X
; MONITOR
; VECTOR ADDRESS STRING IS.....
; $F8A1-$F8A1-$F8A1-$F8A1-$F8A1-$FAB0-$FFFF-$FFFF
; VERIFY $f814
MONITOR ldx #RAMVEC ;POINT TO VECTOR ADDR. STRING
ldy #STACK ;POINT TO RAM VECTOR LOCATION
ldb #$10 ;BYTES TO MOVE = 16
LOOPA lda ,x+ ;GET VECTOR BYTE
sta ,y+ ;PUT VECTORS IN RAM / $DFC0-$DFCF
decb ;SUBTRACT 1 FROM NUMBER OF BYTES TO MOVE
bne LOOPA ;CONTINUE UNTIL ALL VECTORS MOVED
* CONTENTS FROM TO FUNCTION
* $F8A1 $FE40 $DFC0 USER-V
* $F8A1 $FE42 $DFC2 SWI3-V
* $F8A1 $FE44 $DFC4 SWI2-V
* $F8A1 $FE46 $DFC6 FIRQ-V
* $F8A1 $FE48 $DFC8 IRQ-V
* $FAB0 $FE4A $DFCA SWI-V
* $FFFF $FE4C $DFCC SVC-VO
* $FFFF $FE4E $DFCE SVC-VL
; VERIFY $f824
ldx #ACIAS ;GET CONTROL PORT ADDR.
stx CPORT ;STORE ADDR. IN RAM
lbsr XBKPNT ;CLEAR OUTSTANDING BREAKPOINTS
ldb #12 ;CLEAR 12 BYTES ON STACK
CLRSTK clr ,-s
decb
bne CLRSTK
leax MONITOR,pc ;SET PC TO SBUG-E ENTRY
stx 10,s ;ON STACK
lda #$D0 ;PRESET CONDITION CODES ON STACK
sta ,s
tfr s,u
lbsr ACINIZ ;INITIALIZE CONTROL PORT
ldx #MSG1 ;POINT TO 'SBUG 1.8' MESSAGE
lbsr PDATA ;PRINT MSG
ldx #LRARAM ;POINT TO LRA RAM STORAGE AREA
clra ;START TOTAL AT ZERO
ldb #13 ;TOTAL UP ALL ACTIVE RAM MEMORY
FNDREL tst b,x ;TEST FOR RAM AT NEXT LOC.
beq RELPAS ;IF NO RAM GO TO NEXT LOC.
adda #4 ;ELSE ADD 4K TO TOTAL
daa ;ADJ. TOTAL FOR DECIMAL
RELPAS decb ;SUB. 1 FROM LOCS. TO TEST
bpl FNDREL ;PRINT TOTAL OF RAM
lbsr OUT2H ;OUTPUT HEX BYTE AS ASCII
ldx #MSG2 ;POINT TO MSG 'K' CR/LF + 3 NULS
lbsr PDATA ;PRINT MSG
***** NEXTCMD *****
; VERIFY $f861
NEXTCMD ldx #MSG3 ;POINT TO MSG ">"
lbsr PSTRNG ;PRINT MSG
lbsr INCH ;GET ONE CHAR. FROM TERMINAL
anda #$7F ;STRIP PARITY FROM CHAR.
cmpa #$0D ;IS IT CARRIAGE RETURN ?
beq NEXTCMD ;IF CR THEN GET ANOTHER CHAR.
tfr a,b ;PUT CHAR. IN "B" ACCUM.
cmpa #$20 ;IS IT CONTROL OR DATA CHAR ?
bge PRTCMD ;IF CMD CHAR IS DATA, PRNT IT
lda #'^' ;ELSE CNTRL CHAR CMD SO...
lbsr OUTCH ;PRINT "^"
tfr b,a ;RECALL CNTRL CMD CHAR
adda #'A'-1 ;CONVERT IT TO ASCII LETTER
PRTCMD lbsr OUTCH ;PRNT CMD CHAR
lbsr OUT1S ;PRNT SPACE
cmpb #$60
ble NXTCH0
subb #$20
***** DO TABLE LOOKUP *****
* FOR COMMAND FUNCTIONS
; VERIFY $f88b
NXTCH0 ldx #JMPTAB ;POINT TO JUMP TABLE
NXTCHR cmpb ,x+ ;DOES COMMAND MATCH TABLE ENTRY ?
beq JMPCMD ;BRANCH IF MATCH FOUND
leax 2,x ;POINT TO NEXT ENTRY IN TABLE
cmpx #TABEND ;REACHED END OF TABLE YET ?
bne NXTCHR ;IF NOT END, CHECK NEXT ENTRY
ldx #MSG4 ;POINT TO MSG "WHAT?"
lbsr PDATA ;PRINT MSG
bra NEXTCMD ;IF NO MATCH, PRMPT FOR NEW CMD
JMPCMD jsr [,x] ;JUMP TO COMMAND ROUTINE
bra NEXTCMD ;PROMPT FOR NEW COMMAND
*
* "G" GO OR CONTINUE
; VERIFY $f8a5
GO tfr u,s
RTI rti
* "R" DISPLAY REGISTERS
; VERIFY $f8a8
REGSTR ldx #MSG5 ;POINT TO MSG " - "
lbsr PSTRNG ;PRINT MSG
lbsr PRTSP ;$FCBF
lbsr PRTUS ;$FCCA
lbsr PRTDP ;$FCD5
lbsr PRTIX ;$FCE0
lbsr PRTIY ;$FCEB
ldx #MSG5 ;POINT TO MSG " - "
lbsr PSTRNG ;PRINT MSG
lbsr PRTPC ;$FCF5
lbsr PRTA ;$FCFF
lbsr PRTB ;$FD09
lbra PRTCC ;$FD13
* ALTER "PC" PROGRAM COUNTER
; VERIFY $f8cf
ALTRPC lbsr PRTPC ;$FCF5 PRINT MSG " PC = "
lbsr OUT1S ;OUTPUT SPACE
lbsr IN1ADR ;GET NEW CONTENTS FOR "PC"
bvs ALTPCD ;EXIT IF INVALID HEX
stx 10,u ;POKE IN NEW CONTENTS
ALTPCD rts
* ALTER "U" USER STACK POINTER
; VERIFY $f8dd
ALTRU lbsr PRTUS ;$FCCA PRINT MSG " US = "
lbsr OUT1S ;OUTPUT SPACE
lbsr IN1ADR
bvs ALTUD
stx 8,u
ALTUD rts
*
* ALTER "Y" INDEX REGISTER
ALTRY lbsr PRTIY ;PRINT MSG " IY = "
lbsr OUT1S ;OUTPUT SPACE
lbsr IN1ADR
bvs ALTYD
stx 6,u ;$F8F0
ALTYD rts
* ALTER "X" INDEX REGISTER
ALTRX lbsr PRTIX ;$FCE0 PRINT MSG " IX = "
lbsr OUT1S ;OUTPUT SPACE
lbsr IN1ADR
bvs ALTXD
stx 4,u
ALTXD rts
* ALTER "DP" DIRECT PAGE REGISTER
ALTRDP lbsr PRTDP ;$FCD5 PRINT MSG " DP = "
lbsr OUT1S ;OUTPUT SPACE
lbsr BYTE ;INPUT BYTE (2 HEX CHAR)
bvs ALTDPD
sta 3,u
ALTDPD rts
* ALTER "B" ACCUMULATOR
ALTRB lbsr PRTB ;$FD09 PRINT MSG " B = "
lbsr OUT1S ;OUTPUT SPACE
lbsr BYTE ;INPUT BYTE (2 HEX CHAR)
bvs ALTBD
sta 2,u
ALTBD rts ;$F91C
* ALTER "A" ACCUMULATOR
*
ALTRA lbsr PRTA ;$FCFF RINT MSG " A = "
lbsr OUT1S ;OUTPUT SPACE
lbsr BYTE ;INPUT BYTE (2 HEX CHAR)
bvs ALTAD
sta 1,u
ALTAD rts
* ALTER "CC" REGISTER
ALTRCC lbsr PRTCC ;$FD13 PRINT MSG " CC: "
lbsr OUT1S ;OUTPUT SPACE
lbsr BYTE ;INPUT BYTE (2 HEX CHAR)
bvs ALTCCD
ora #$80 ;SETS "E" FLAG IN PRINT LIST
sta ,u
ALTCCD rts
***** "M" MEMORY EXAMINE AND CHANGE *****
; VERIFY $f941
MEMCHG lbsr IN1ADR ;INPUT ADDRESS
bvs CHRTN ;IF NOT HEX, RETURN
tfr x,y ;SAVE ADDR IN "Y"
MEMC2 ldx #MSG5 ;POINT TO MSG " - "
lbsr PSTRNG ;PRINT MSG
tfr y,x ;FETCH ADDRESS
lbsr OUT4H ;PRINT ADDR IN HEX
lbsr OUT1S ;OUTPUT SPACE
lda ,y ;GET CONTENTS OF CURRENT ADDR.
lbsr OUT2H ;OUTPUT CONTENTS IN ASCII
lbsr OUT1S ;OUTPUT SPACE
lbsr BYTE ;LOOP WAITING FOR OPERATOR INPUT
bvc CHANGE ;IF VALID HEX GO CHANGE MEM. LOC.
cmpa #8 ;IS IT A BACKSPACE (CNTRL H)?
beq MEMC2 ;PROMPT OPERATOR AGAIN
cmpa #$18 ;IS IT A CANCEL (CNTRL X)?
beq MEMC2 ;PROMPT OPERATOR AGAIN
cmpa #'^' ;IS IT AN UP ARROW?
beq BACK ;DISPLAY PREVIOUS BYTE
cmpa #$D ;IS IT A CR?
bne FORWRD ;DISPLAY NEXT BYTE
CHRTN rts ;EXIT ROUTINE
CHANGE sta ,y ;CHANGE BYTE IN MEMORY
cmpa ,y ;DID MEMORY BYTE CHANGE?
beq FORWRD ;$F972
lbsr OUT1S ;OUTPUT SPACE
lda #'?' ;LOAD QUESTION MARK
lbsr OUTCH ;PRINT IT
FORWRD leay 1,y ;POINT TO NEXT HIGHER MEM LOCATION
bra MEMC2 ;PRINT LOCATION & CONTENTS
BACK leay -1,y ;POINT TO LAST MEM LOCATION
bra MEMC2 ;PRINT LOCATION & CONTENTS
* "S" DISPLAY STACK
* HEX-ASCII DISPLAY OF CURRENT STACK CONTENTS FROM
* CURRENT STACK POINTER TO INTERNAL STACK LIMIT.
DISSTK lbsr PRTSP ;PRINT CURRENT STACK POINTER
tfr u,y
ldx #STACK ;LOAD INTERNAL STACK AS UPPER LIMIT
leax -1,x ;POINT TO CURRENT STACK
bra MDUMP1 ;ENTER MEMORY DUMP OF STACK CONTENTS
* "E" DUMP MEMORY FOR EXAMINE IN HEX AND ASCII
* AFTER CALLING 'IN2ADR' LOWER ADDRESS IN Y-REG.
* UPPER ADDRESS IN X-REG.
* IF HEX ADDRESSES ARE INVALID (V)=1.
; VERIFY $f996
MEMDUMP lbsr IN2ADR ;INPUT ADDRESS BOUNDRIES
bvs EDPRTN ;NEW COMMAND IF ILLEGAL HEX
;
; The start address is now in IY and the end in IX
;
MDUMP1 pshs y ;COMPARE LOWER TO UPPER BOUNDS
cmpx ,s++ ;LOWER BOUNDS > UPPER BOUNDS?
bcc AJDUMP ;IF NOT, DUMP HEX AND ASCII
EDPRTN rts
* ADJUST LOWER AND UPPER ADDRESS LIMITS
* TO EVEN 16 BYTE BOUNDRIES.
* IF LOWER ADDR = $4532
* LOWER BOUNDS WILL BE ADJUSTED TO = $4530.
* IF UPPER ADDR = $4567
* UPPER BOUNDS WILL BE ADJUSTED TO = $4570.
* ENTER WITH LOWER ADDRESS IN X-REG.
* -UPPER ADDRESS ON TOP OF STACK.
AJDUMP tfr x,d ;GET UPPER ADDR IN D-REG
addd #$10 ;ADD 16 TO UPPER ADDRESS
andb #$F0 ;MASK TO EVEN 16 BYTE BOUNDRY
pshs a,b ;SAVE ON STACK AS UPPER DUMP LIMIT
tfr y,d ;$F9A5 GET LOWER ADDRESS IN D-REG
andb #$F0 ;MASK TO EVEN 16 BYTE BOUNDRY
tfr d,x ;PUT IN X-REG AS LOWER DUMP LIMIT
NXTLIN cmpx ,s ;COMPARE LOWER TO UPPER LIMIT
beq SKPDMP ;IF EQUAL SKIP HEX-ASCII DUMP
lbsr INCHEK ;CHECK FOR INPUT FROM KEYBOARD
beq EDUMP ;IF NONE, CONTINUE WITH DUMP
SKPDMP leas 2,s ;READJUST STACK IF NOT DUMPING
rts
* PRINT 16 HEX BYTES FOLLOWED BY 16 ASCII CHARACTERS
* FOR EACH LINE THROUGHOUT ADDRESS LIMITS.
EDUMP pshs x ;PUSH LOWER ADDR LIMIT ON STACK
ldx #MSG5 ;POINT TO MSG " - "
lbsr PSTRNG ;PRINT MSG
ldx ,s ;LOAD LOWER ADDR FROM TOP OF STACK
lbsr OUT4H ;PRINT THE ADDRESS
lbsr OUT2S ;PRINT 2 SPACES
ldb #$10 ;LOAD COUNT OF 16 BYTES TO DUMP
ELOOP lda ,x+ ;GET FROM MEMORY HEX BYTE TO PRINT
lbsr OUT2H ;OUTPUT HEX BYTE AS ASCII
lbsr OUT1S ;OUTPUT SPACE
decb ;$F9D1 DECREMENT BYTE COUNT
bne ELOOP ;CONTINUE TIL 16 HEX BYTES PRINTED
* PRINT 16 ASCII CHARACTERS
* IF NOT PRINTABLE OR NOT VALID
* ASCII PRINT A PERIOD (.)
lbsr OUT2S ;2 SPACES
ldx ,s++ ;GET LOW LIMIT FRM STACK - ADJ STACK
ldb #$10 ;SET ASCII CHAR TO PRINT = 16
EDPASC lda ,x+ ;GET CHARACTER FROM MEMORY
cmpa #$20 ;IF LESS THAN $20, NON-PRINTABLE?
bcs PERIOD ;IF SO, PRINT PERIOD INSTEAD
cmpa #$7E ;IS IT VALID ASCII?
bls PRASC ;IF SO PRINT IT
PERIOD lda #'.' ;LOAD A PERIOD (.)
PRASC lbsr OUTCH ;PRINT ASCII CHARACTER
decb ;DECREMENT COUNT
bne EDPASC
bra NXTLIN
***** "Q" MEMORY TEST *****
; VERIFY $f9f2
MEMTST clr ,-s ;CLEAR BYTE ON STACK
clr ,-s ;CLEAR ANOTHER BYTE
lbsr IN2ADR ;GET BEGIN(Y) & END(X) ADDR. LIMITS
pshs x,y ;SAVE ADDRESSES ON STACK
bvs ADJSK6 ;EXIT IF NOT VALID HEX
cmpx 2,s ;COMPARE BEGIN TO END ADDR.
bcs ADJSK6 ;EXIT IF BEGIN > END ADDR.
lbsr OUT1S ;OUTPUT SPACE
MEMSET tfr y,d ;PUT BEGIN ADDR. IN 'D'-ACCUM.
addd 4,s ;ADD PASS COUNT TO BEGIN ADDR
pshs b ;ADD LS BYTE TO MS BYTE OF BEGIN ADDR
adda ,s+
sta ,y+ ;SAVE THIS DATA BYTE AT BEGIN ADDR
cmpy ,s ;COMPARE END TO BEGIN ADDR
bcs MEMSET ;IF BEGIN LOWER, CONTINUE TO SET MEMORY
ldy 2,s ;RELOAD BEGIN ADDRESS
TEST1 tfr y,d ;PUT BEGIN ADDR IN 'D'-ACC.
addd 4,s ;ADD PASS COUNT TO ADDRESS
pshs a ;ADD MS BYTE TO LS BYTE OF ADDRESS
addb ,s+
eorb ,y+ ;EX-OR THIS DATA WITH DATA IN MEMORY LOC.
beq GUDPAS ;IF (Z) SET, MEMORY BYTE OK
ldx #MSG5 ;POINT TO MSG " - "
lbsr PSTRNG ;PRINT MSG
leax -1,y ;GET ERROR ADDRESS IN X-REG
lbsr OUT4H ;OUTPUT IT
pshs x ;PUSH ERROR ADDR ON STACK
ldx #MSG8 ;POINT TO MSG " =>"
lbsr PDATA ;PRINT MSG
puls x ;POP ERROR ADDR FROM STACK
lbsr LRA ;GET PHYSICAL ADDR FROM LRA
lbsr XASCII ;OUTPUT EXTENDED 4 BITS OF PHYSICAL ADDR
lbsr OUT4H ;OUTPUT LS 16 BITS OF PHYSICAL ADDR
ldx #MSG6 ;POINT TO MSG ", PASS "
lbsr PDATA ;PRINT MSG
ldx 4,s ;LOAD PASS COUNT
lbsr OUT4H ;OUTPUT IT
ldx #MSG7 ;POINT TO MSG ", BITS IN ERROR
lbsr PDATA ;PRINT MSG
tfr b,a ;GET ERROR BYTE INTO A-ACC
ldx #MSG9 ;POINT TO MSG "76543210"
lbsr BIASCI ;OUTPUT IN BINARY/ASCII FORMAT
lbsr INCHEK ;CHECK FOR INPUT FROM KEYBOARD $FA56
bne ADJSK6 ;IF SO, EXIT MEMORY TEST
GUDPAS cmpy ,s ;COMPARE END ADDR TO BEGIN ADDR
bcs TEST1
lda #'+' ;GET "PASS" SYMBOL IF MEMORY PASS OK
lbsr OUTCH ;OUTPUT SYMBOL TO TERMINAL
lbsr INCHEK ;INPUT FROM KEYBOARD?
bne ADJSK6 ;IF SO, EXIT MEMORY TEST
ldy 2,s ;LOAD BEGIN ADDRESS
inc 5,s ;INCREMENT LS BYTE OF PASS COUNT
bne MEMSET ;IF NOT ZERO, SET NEXT MEMORY BYTE
inc 4,s ;INCREMENT MS BYTE OF PASS COUNT
bne MEMSET ;DONE WITH 65,535 PASSES OF MEMORY?
ADJSK6 leas 6,s ;ADJ STACK POINTER BY 6
rts
***** "B" SET BREAKPOINT *****
BRKPNT lbsr IN1ADR ;GET BREAKPOINT ADDRESS
bvs EXITBP ;EXIT IF INVALID HEX ADDR.
cmpx #STACK ;ADDRESS ILLEGAL IF >=$DFC0
bcc BPERR ;IF ERROR PRINT (?), EXIT
pshs x ;$FA82 PUSH BP ADDRESS ON STACK
ldx #$FFFF ;LOAD DUMMY ADDR TO TEST BP TABLE
bsr BPTEST ;TEST BP TABLE FOR FREE SPACE
puls x ;POP BP ADDRESS FROM STACK
beq BPERR ;(Z) SET, OUT OF BP TABLE SPACE
lda ,x ;GET DATA AT BREAKPOINT ADDRESS
cmpa #$3F ;IS IT A SWI?
beq BPERR ;IF SWI ALREADY, INDICATE ERROR
sta ,y+ ;SAVE DATA BYTE IN BP TABLE
stx ,y ;SAVE BP ADDRESS IN BP TABLE
lda #$3F ;LOAD A SWI ($3F)
sta ,x ;SAVE SWI AT BREAKPOINT ADDRESS
EXITBP rts
* INDICATE ERROR SETTING BREAKPOINT
BPERR lbsr OUT1S ;OUTPUT SPACE
lda #'?' ;LOAD (?), INDICATE BREAKPOINT ERROR
lbra OUTCH ;PRINT "?"
*** "X" CLEAR OUTSTANDING BREAKPOINTS ***
XBKPNT ldy #BPTBL ;POINT TO BREAKPOINT TABLE
ldb #8 ;LOAD BREAKPOINT COUNTER
XBPLP bsr RPLSWI ;REMOVE USED ENTRY IN BP TABLE
decb ;$FAAC DECREMENT BP COUNTER
bne XBPLP ;END OF BREAKPOINT TABLE?
rts
***** SWI ENTRY POINT *****
; VERIFY $fab3
SWIE tfr s,u ;TRANSFER STACK TO USER POINTER
ldx 10,u ;LOAD PC FROM STACK INTO X-REG
leax -1,x ;ADJUST ADDR DOWN 1 BYTE.
bsr BPTEST ;FIND BREAKPOINT IN BP TABLE
beq REGPR ;IF FOUND, REPLACE DATA AT BP ADDR
stx 10,u ;SAVE BREAKPOINT ADDR IN STACK
bsr RPLSWI ;GO REPLACE SWI WITH ORIGINAL DATA
REGPR lbsr REGSTR ;GO PRINT REGISTERS
lbra NEXTCMD ;GET NEXT COMMAND
RPLSWI ldx 1,y ;LOAD BP ADDRESS FROM BP TABLE
cmpx #STACK ;COMPARE TO TOP AVAILABLE USER MEMORY
bcc FFSTBL ;GO RESET TABLE ENTRY TO $FF'S
lda ,x ;GET DATA FROM BP ADDRESS
cmpa #$3F ;IS IT SWI?
bne FFSTBL ;IF NOT, RESET TABLE ENTRY TO $FF'S
lda ,y ;GET ORIGINAL DATA FROM BP TABLE
sta ,x ;$FAD3 RESTORE DATA AT BP ADDRESS
FFSTBL lda #$FF ;LOAD $FF IN A-ACC
sta ,y+ ;RESET BREAKPOINT TABLE DATA TO $FF'S
sta ,y+ ;RESET BREAKPOINT TABLE ADDR TO $FF'S
sta ,y+
rts
** SEARCH BREAKPOINT TABLE FOR MATCH **
BPTEST ldy #BPTBL ;POINT TO BREAKPOINT TABLE
ldb #8 ;LOAD BREAKPOINT COUNTER
FNDBP lda ,y+ ;LOAD DATA BYTE
cmpx ,y++ ;COMPARE ADDRESS, IS IT SAME?
beq BPADJ ;IF SO, ADJUST POINTER FOR TABLE ENTRY
decb ;IF NOT, DECREMENT BREAKPOINT COUNTER
bne FNDBP ;AND LOOK FOR NEXT POSSIBLE MATCH
rts
BPADJ leay -3,y ;MOVE POINTER TO BEGIN OF BP ENTRY
rts
*** "D" DISK BOOT FOR DMAF2 ***
if DMAF2
DBOOT lda #$DE
sta DRVREG
lda #$FF
sta PRIREG ;$FAF8
sta CCREG
sta AAAREG
sta BBBREG
tst CCREG
lda #$D8
sta COMREG
lbsr DLY
DBOOT0 lda COMREG
bmi DBOOT0
lda #$09
sta COMREG
lbsr DLY
DISKWT lda COMREG ;FETCH DRIVE STATUS
bita #1 ;TEST BUSY BIT
bne DISKWT ;LOOP UNTIL NOT BUSY
bita #$10
bne DBOOT
ldx #$C000 ;LOGICAL ADDR. = $C000
bsr LRA ;GET 20 BIT PHYSICAL ADDR. OF LOG. ADDR.
ora #$10
sta CCCREG
tfr x,d
coma
comb
std ADDREG
ldx #$FEFF ;LOAD DMA BYTE COUNT = $100
stx CNTREG ;STORE IN COUNT REGISTER
lda #$FF ;LOAD THE CHANNEL REGISTER
sta CCREG
lda #$FE ;SET CHANNEL 0
sta PRIREG
lda #1 ;SET SECTOR TO "1"
sta SECREG ;ISSUE COMMAND
lda #$8C ;SET SINGLE SECTOR READ
sta COMREG ;ISSUE COMMAND
bsr DLY
* THE FOLLOWING CODE TESTS THE STATUS OF THE
* CHANNEL CONTROL REGISTER. IF "D7" IS NOT
* ZERO THEN IT WILL LOOP WAITING FOR "D7"
* TO GO TO ZERO. IF AFTER 65,536 TRIES IT
* IS STILL A ONE THE BOOT OPERATION WILL
* BE STARTED OVER FROM THE BEGINING.
clrb
DBOOT1 pshs b ;$FB55
clrb
DBOOT2 tst CCREG
bpl DBOOT3
decb
bne DBOOT2
puls b
decb
bne DBOOT1
bra DBOOT
DBOOT3 puls b
lda COMREG
bita #$1C
beq DBOOT4
rts
DBOOT4 ldb #$DE
stb DRVREG
ldx #$C000
stx 10,u
tfr u,s ;$FB7B
rti
endif
if SD_SUPPORT
;
;=====================================================
; This boots the OS from the SD card. No registers
; are set on entry, and this never returns. If the
; boot fails, jump back into SBUG.
;
SdBoot2 ldx #dbmsg ;print prompt
jsr PDATA
SdBoot jsr xParInit ;do initialization
ldx #BootFCB
jsr DiskReadSector
bcs bootErr
jmp BOOT_ADDR
;
bootErr ldx #berrmsg
jsr PSTRNG
jmp MONITOR
;
berrmsg db CR,LF
db "BOOT ERROR!"
db CR,LF,0,EOT
dbmsg db BS,"isk boot"
db CR,LF,EOT
;
; FCB used to load the boot sector into memory
;
BootFCB db 0 ;drive 0
db 0 ;track 0
db 0 ;sector 0
db 0 ;sectors per track
dw BOOT_ADDR ;buffer address
endif
***** LRA LOAD REAL ADDRESS *****
* THE FOLLOWING CODE LOADS THE 20-BIT
* PHYSICAL ADDRESS OF A MEMORY BYTE
* INTO THE "A" AND "X" REGISTERS. THIS
* ROUTINE IS ENTERED WITH THE LOGICAL
* ADDRESS OF A MEMORY BYTE IN THE "IX"
* REGISTER. EXIT IS MADE WITH THE HIGH-
* ORDER FOUR BITS OF THE 20-BIT PHYSICAL
* ADDRESS IN THE "A" REGISTER, AND THE
* LOW-ORDER 16-BITS OF THE 20-BIT
* PHYSICAL ADDRESS IN THE "IX" REGISTER.
* ALL OTHER REGISTERS ARE PRESERVED.
* THIS ROUTINE IS REQUIRED SINCE THE
* DMAF1 AND DMAF2 DISK CONTROLLERS MUST
* PRESENT PHYSICAL ADDRESSES ON THE
* SYSTEM BUS.
FORCE $fb81
LRA pshs a,b,x,y ;PUSH REGISTERS ON STACK
lda 2,s ;GET MSB LOGICAL ADDR FRM X REG ON STACK
lsra
lsra ;ADJ FOR INDEXED INTO
lsra ;CORRESPONDING LOCATION
lsra ;IN LRA TABLE
ldy #LRARAM ;LOAD LRA TABLE BASE ADDRESS
ldb a,y ;GET PHYSICAL ADDR. DATA FROM LRA TABLE
lsrb ;. REAL ADDR. TO REFLECT EXTENDED
lsrb ; ADDRESS.
lsrb ; MS 4-BITS ARE RETURNED
lsrb ; THE "A" ACCUMULATOR
stb ,s ;MS 4 BITS IN A ACCUM. STORED ON STACK
ldb a,y ;LOAD REAL ADDRESS DATA FROM LRA TABLE
comb ;COMP TO ADJ FOR PHYSICAL ADDR. IN X REG
aslb ;ADJ DATA FOR RELOCATION IN X REG
aslb
aslb ;$FB97
aslb
lda 2,s ;GET MS BYTE OF LOGICAL ADDR.
anda #$0F ;MASK MS NIBBLE OF LOGICAL ADDRESS
sta 2,s ;SAVE IT IN X REG ON STACK
orb 2,s ;SET MS BYTE IN X REG TO ADJ PHY ADDR.
* PLUS LS NIBBLE OF LOGICAL ADDRESS
stb 2,s ;SAVE AS LS 16 BITS OF PHY ADDR IN X REG
* ON STACK
puls a,b,x,y ;POP REGS. FROM STACK
rts
* DELAY LOOP
DLY pshs b ;SAVE CONTENTS OF "B"
ldb #$20 ;GET LOOP DELAY VALUE
SUB1 decb ;SUBTRACT ONE FROM VALUE
bne SUB1 ;LOOP UNTIL ZERO
puls b ;RESTORE CONTENTS OF "B"
rts
***** "U" MINIDISK BOOT *****
if DC_X
MINBOOT tst Comreg
clr Drvreg ;SELECT DRIVE 0
* DELAY BEFORE ISSUING RESTORE COMMAND
ldb #3
ldx #0
LOOP leax 1,x ;$FBBB
cmpx #0
bne LOOP
decb ;$FBC2
bne LOOP
lda #$0F ;*LOAD HEAD, VERIFY, 20msec/step
sta Comreg ;ISSUE RESTORE COMMAND
bsr DELAY
LOOP1 ldb Comreg ;$FBCC
bitb #1
bne LOOP1 ;LOOP UNTIL THRU
lda #1
sta Secreg ;SET SECTOR REGISTER TO ONE
bsr DELAY
lda #$8C ;LOAD HEAD, DELAY 10msec,
sta Comreg ;AND READ SINGLE RECORD
bsr DELAY
ldx #$C000
bra LOOP3
LOOP2 bitb #2 ;$FBE6 DRQ?
beq LOOP3
lda Datreg
sta ,x+
LOOP3 ldb Comreg ;FETCH STATUS
bitb #1 ;BUSY?
bne LOOP2
bitb #$2C ;CRC ERROR OR LOST DATA?
beq LOOP4
rts
LOOP4 ldx #$C000 ;$FBFB
stx 10,u
tfr u,s
rti
* DELAY
DELAY ldb #$20
LOOP5 decb
bne LOOP5
rts
endif ;DC_X
***** "L" LOAD MIKBUG TAPE *****
* Otherwise known as an S-record file
LOAD
if READER_CONTROL
lda #$11 ;LOAD 'DC1' CASS. READ ON CODE
lbsr OUTCH ;OUTPUT IT TO TERMINAL PORT
endif
clr ECHO ;TURN OFF ECHO FLAG
LOAD1 lbsr ECHON ;INPUT 8 BIT BYTE WITH NO ECHO
LOAD2 cmpa #'S' ;IS IT AN "S", START CHARACTER ?
bne LOAD1 ;IF NOT, DISCARD AND GET NEXT CHAR.
lbsr ECHON
cmpa #'9' ;IS IT A "9" , END OF FILE CHAR ?
beq LOAD21 ;IF SO, EXIT LOAD
if ALLOW_S5
cmpa #'5' ;5 can also end some files
beq LOAD22
endif ;ALLOW_S5
cmpa #'1' ;IS IT A "1" , FILE LOAD CHAR ?
bne LOAD2 ;IF NOT, LOOK FOR START CHAR.
lbsr BYTE ;INPUT BYTE COUNT
pshs a ;PUSH COUNT ON STACK