-
Notifications
You must be signed in to change notification settings - Fork 27
/
ccp.asm
1290 lines (1175 loc) · 26.1 KB
/
ccp.asm
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
; Reformatted and converted for cross-assembly by Macro Assembler AS
; Eric Smith <[email protected]> 2018-01-24
; from original source os2ccp.asm from
; http://www.cpm.z80.de/download/cpm2-plm.zip
; Changes:
; multiple instructions per line split to separate lines
; dollar sign in labels replaced by underscore
; dollar sign (as digit separator) in binary constants removed
; single quotes around strings replaced with double quotes
; true and false replaced with _true and _false
; replaced "not" operator with "~"
; removed empty comments
; added ifdef origin to allow origin to be specified from command line
; added commments about serial number
; added ifdefs on "noserial" to omit serialization check
.cpu 8080
title "console command processor (CCP), ver 2.0"
; assembly language version of the CP/M console command processor
; version 2.2 February, 1980
; Copyright (c) 1976, 1977, 1978, 1979, 1980
; Digital Research
; Box 579, Pacific Grove,
; California, 93950
_false equ 0000h
_true equ ~_false
testing equ _false ;true if debugging
ifdef origin
org origin
bdosl equ $+800h ;bdos location
else
if testing
org 3400h
bdosl equ $+800h ;bdos location
else
org 000h
bdosl equ $+800h ;bdos location
endif
endif
tran equ 100h
tranm equ $
ccploc equ $
; ********************************************************
; * Base of CCP contains the following code/data *
; * ccp: jmp ccpstart (start with command) *
; * jmp ccpclear (start, clear command) *
; * ccp+6 127 (max command length) *
; * ccp+7 comlen (command length = 00) *
; * ccp+8 ' ... ' (16 blanks) *
; ********************************************************
; * Normal entry is at ccp, where the command line given *
; * at ccp+8 is executed automatically (normally a null *
; * command with comlen = 00). An initializing program *
; * can be automatically loaded by storing the command *
; * at ccp+8, with the command length at ccp+7. In this *
; * case, the ccp executes the command before prompting *
; * the console for input. Note that the command is exe-*
; * cuted on both warm and cold starts. When the command*
; * line is initialized, a jump to "jmp ccpclear" dis- *
; * ables the automatic command execution. *
; ********************************************************
jmp ccpstart ;start ccp with possible initial command
jmp ccpclear ;clear the command buffer
maxlen: db 127 ;max buffer length
comlen: db 0 ;command length (filled in by dos)
; (command executed initially if comlen non zero)
combuf:
db " " ;8 character fill
db " " ;8 character fill
db "COPYRIGHT (C) 1979, DIGITAL RESEARCH "; 38
ds 128-($-combuf)
; total buffer length is 128 characters
comaddr:dw combuf ;address of next to char to scan
staddr: ds 2 ;starting address of current fillfcb request
diska equ 0004h ;disk address for current disk
bdos equ 0005h ;primary bdos entry point
buff equ 0080h ;default buffer
fcb equ 005ch ;default file control block
rcharf equ 1 ;read character function
pcharf equ 2 ;print character function
pbuff equ 9 ;print buffer function
rbuff equ 10 ;read buffer function
breakf equ 11 ;break key function
liftf equ 12 ;lift head function (no operation)
initf equ 13 ;initialize bdos function
self equ 14 ;select disk function
openf equ 15 ;open file function
closef equ 16 ;close file function
searf equ 17 ;search for file function
searnf equ 18 ;search for next file function
delf equ 19 ;delete file function
dreadf equ 20 ;disk read function
dwritf equ 21 ;disk write function
makef equ 22 ;file make function
renf equ 23 ;rename file function
logf equ 24 ;return login vector
cself equ 25 ;return currently selected drive number
dmaf equ 26 ;set dma address
userf equ 32 ;set user number
; special fcb flags
rofile equ 9 ;read only file
sysfile equ 10 ;system file flag
; special characters
cr equ 13 ;carriage return
lf equ 10 ;line feed
la equ 5fh ;left arrow
eofile equ 1ah ;end of file
; utility procedures
printchar:
mov e,a
mvi c,pcharf
jmp bdos
printbc:
;print character, but save b,c registers
push b
call printchar
pop b
ret
crlf:
mvi a,cr
call printbc
mvi a,lf
jmp printbc
blank:
mvi a,' '
jmp printbc
print: ;print string starting at b,c until next 00 entry
push b ;now print the string
call crlf
pop h
prin0: mov a,m ;stop on 00
ora a
rz
inx h ;ready for next
push h
call printchar ;character printed
pop h
jmp prin0 ;for another character
initialize:
mvi c,initf
jmp bdos
select:
mov e,a
mvi c,self
jmp bdos
bdos_inr:
call bdos
sta dcnt
inr a
ret
open: ;open the file given by d,e
mvi c,openf
jmp bdos_inr
openc: ;open comfcb
xra a ;clear next record to read
sta comrec
lxi d,comfcb
jmp open
close: ;close the file given by d,e
mvi c,closef
jmp bdos_inr
search: ;search for the file given by d,e
mvi c,searf
jmp bdos_inr
searchn:
;search for the next occurrence of the file given by d,e
mvi c,searnf
jmp bdos_inr
searchcom:
;search for comfcb file
lxi d,comfcb
jmp search
delete: ;delete the file given by d,e
mvi c,delf
jmp bdos
bdos_cond:
call bdos
ora a
ret
diskread:
;read the next record from the file given by d,e
mvi c,dreadf
jmp bdos_cond
diskreadc:
;read the comfcb file
lxi d,comfcb
jmp diskread
diskwrite:
;write the next record to the file given by d,e
mvi c,dwritf
jmp bdos_cond
make: ;create the file given by d,e
mvi c,makef
jmp bdos_inr
renam: ;rename the file given by d,e
mvi c,renf
jmp bdos
getuser:
;return current user code in a
mvi e,0ffh ;drop through to setuser
setuser:
mvi c,userf ;sets user number
jmp bdos
saveuser:
;save user#/disk# before possible ^c or transient
call getuser ;code to a
add a ;rot left
add a
add a
add a
lxi h,cdisk ;4b=user, 4b=disk
ora m
sta diska ;stored away in memory for later
ret
setdiska:
lda cdisk ;user/disk
sta diska
ret
translate:
;translate character in register A to upper case
cpi 61h ;return if below lower case a
rc
cpi 7bh ;return if above lower case z
rnc
ani 5fh ;translated to upper case
ret
readcom:
;read the next command into the command buffer
;check for submit file
lda submit
ora a
jz nosub
;scanning a submit file
;change drives to open and read the file
lda cdisk
ora a
mvi a,0
cnz select
;have to open again in case xsub present
lxi d,subfcb ;skip if no sub
call open
jz nosub
lda subrc ;read last record(s) first
dcr a
sta subcr ;current record to read
lxi d,subfcb ;end of file if last record
call diskread
jnz nosub
;disk read is ok, transfer to combuf
lxi d,comlen
lxi h,buff
mvi b,128
call move0
;line is transferred, close the file with a
;deleted record
lxi h,submod ;clear fwflag
mvi m,0
inx h ;one less record
dcr m
lxi d,subfcb
call close
jz nosub
;close went ok, return to original drive
lda cdisk
ora a
cnz select
;print to the 00
lxi h,combuf
call prin0
call break_key
jz noread
call del_sub ;break key depressed
jmp ccp
nosub: ;no submit file
call del_sub
;translate to upper case, store zero at end
call saveuser ;user # save in case control c
mvi c,rbuff
lxi d,maxlen
call bdos
call setdiska ;no control c, so restore diska
noread: ;enter here from submit file
;set the last character to zero for later scans
lxi h,comlen ;length is in b
mov b,m
readcom0:
inx h ;end of scan?
mov a,b
ora a
jz readcom1 ;get character and translate
mov a,m
call translate
mov m,a
dcr b
jmp readcom0
readcom1: ;end of scan, h,l address end of command
mov m,a ;store a zero
lxi h,combuf ;ready to scan to zero
shld comaddr
ret
break_key:
;check for a character ready at the console
mvi c,breakf
call bdos
ora a
rz
mvi c,rcharf ;character cleared
call bdos
ora a
ret
cselect:
;get the currently selected drive number to reg-A
mvi c,cself
jmp bdos
setdmabuff:
;set default buffer dma address
lxi d,buff ;(drop through)
setdma:
;set dma address to d,e
mvi c,dmaf
jmp bdos
del_sub:
;delete the submit file, and set submit flag to false
lxi h,submit ;return if no sub file
mov a,m
ora a
rz
mvi m,0 ;submit flag is set to false
xra a ;on drive a to erase file
call select
lxi d,subfcb
call delete
lda cdisk ;back to original drive
jmp select
ifndef noserial
serialize:
;check serialization
lxi d,serial ;check six bytes
lxi h,bdosl
mvi b,6
ser0: ldax d
cmp m
jnz badserial
inx d
inx h
dcr b
jnz ser0
ret ;serial number is ok
endif
comerr:
;error in command string starting at position
;'staddr' and ending with first delimiter
call crlf ;space to next line
lhld staddr ;h,l address first to print
comerr0: ;print characters until blank or zero
mov a,m ; not blank
cpi ' '
jz comerr1
ora a ; not zero, so print it
jz comerr1
push h
call printchar
pop h
inx h
jmp comerr0; for another character
comerr1: ;print question mark,and delete sub file
mvi a,'?'
call printchar
call crlf
call del_sub
jmp ccp ;restart with next command
; fcb scan and fill subroutine (entry is at fillfcb below)
;fill the comfcb, indexed by A (0 or 16)
;subroutines
delim: ;look for a delimiter
ldax d ;not the last element
ora a
rz
cpi ' ' ;non graphic
jc comerr
rz ;treat blank as delimiter
cpi '='
rz
cpi la ;left arrow
rz
cpi '.'
rz
cpi ':'
rz
cpi ';'
rz
cpi '<'
rz
cpi '>'
rz
ret ;delimiter not found
deblank: ;deblank the input line
ldax d ;treat end of line as blank
ora a
rz
cpi ' '
rnz
inx d
jmp deblank
addh: ;add a to h,l
add l
mov l,a
rnc
inr h
ret
fillfcb0:
;equivalent to fillfcb(0)
mvi a,0
fillfcb:
lxi h,comfcb ;fcb rescanned at end
call addh
push h
push h
xra a ;clear selected disk (in case A:...)
sta sdisk
lhld comaddr ;command address in d,e
xchg
call deblank ;to first non-blank character
xchg ;in case of errors
shld staddr
xchg ;d,e has command, h,l has fcb address
pop h
;look for preceding file name A: B: ...
ldax d ;use current disk if empty command
ora a
jz setcur0
sbi 'A'-1 ;disk name held in b if : follows
mov b,a
inx d ;set disk name if :
ldax d
cpi ':'
jz setdsk
setcur: ;set current disk
dcx d ;back to first character of command
setcur0:
lda cdisk
mov m,a
jmp setname
setdsk: ;set disk to name in register b
mov a,b ;mark as disk selected
sta sdisk
mov m,b ;past the :
inx d
setname: ;set the file name field
mvi b,8 ;file name length (max)
setnam0:
call delim ;not a delimiter
jz padname
inx h ;must be ?'s
cpi '*'
jnz setnam1
mvi m,'?' ;to dec count
jmp setnam2
setnam1:
mov m,a ;store character to fcb
inx d
setnam2:
dcr b ;count down length
jnz setnam0
;end of name, truncate remainder
trname: call delim ;set type field if delimiter
jz setty
inx d
jmp trname
padname:
inx h
mvi m,' '
dcr b
jnz padname
setty: ;set the type field
mvi b,3 ;skip the type field if no .
cpi '.'
jnz padty
inx d ;past the ., to the file type field
setty0: ;set the field from the command buffer
call delim
jz padty
inx h
cpi '*'
jnz setty1
mvi m,'?' ;since * specified
jmp setty2
setty1: ;not a *, so copy to type field
mov m,a
inx d
setty2: ;decrement count and go again
dcr b
jnz setty0
;end of type field, truncate
trtyp: ;truncate type field
call delim
jz efill
inx d
jmp trtyp
padty: ;pad the type field with blanks
inx h
mvi m,' '
dcr b
jnz padty
efill: ;end of the filename/filetype fill, save command address
;fill the remaining fields for the fcb
mvi b,3
efill0: inx h
mvi m,0
dcr b
jnz efill0
xchg ;set new starting point
shld comaddr
;recover the start address of the fcb and count ?'s
pop h ;b=0, c=8+3
lxi b,11
scnq: inx h
mov a,m
cpi '?'
jnz scnq0
;? found, count it in b
inr b
scnq0: dcr c
jnz scnq
;number of ?'s in c, move to a and return with flags set
mov a,b
ora a
ret
intvec:
;intrinsic function names (all are four characters)
db "DIR "
db "ERA "
db "TYPE"
db "SAVE"
db "REN "
db "USER"
intlen equ ($-intvec)/4 ;intrinsic function length
; serial number (details not documented in original DRI source file)
serial: db 0 ; OEM number, low byte
db 0 ; CP/M version, 16h = 2.2
db 0 ; OEM number, high byte
db 0,0,0 ; serial number, big-endian
intrinsic:
;look for intrinsic functions (comfcb has been filled)
lxi h,intvec ;c counts intrinsics as scanned
mvi c,0
intrin0:
mov a,c ;done with scan?
cpi intlen
rnc
;no, more to scan
lxi d,comfcb+1 ;beginning of name
mvi b,4 ;length of match is in b
intrin1:
ldax d ;match?
cmp m
jnz intrin2 ;skip if no match
inx d
inx h
dcr b
jnz intrin1 ;loop while matching
;complete match on name, check for blank in fcb
ldax d ;otherwise matched
cpi ' '
jnz intrin3
mov a,c ;with intrinsic number in a
ret
intrin2: ;mismatch, move to end of intrinsic
inx h
dcr b
jnz intrin2
intrin3: ;try next intrinsic
inr c ;to next intrinsic number
jmp intrin0 ;for another round
ccpclear:
;clear the command buffer
xra a
sta comlen
;drop through to start ccp
ccpstart:
;enter here from boot loader
lxi sp,stack ;save initial disk number
push b
;(high order 4bits=user code, low 4bits=disk#)
mov a,c ;user code
rar
rar
rar
rar
ani 0fh
mov e,a ;user code selected
call setuser
;initialize for this user, get $ flag
call initialize ;0ffh in accum if $ file present
sta submit ;submit flag set if $ file present
pop b ;recall user code and disk number
mov a,c ;disk number in accumulator
ani 0fh
sta cdisk ;clears user code nibble
call select ;proper disk is selected, now check sub files
;check for initial command
lda comlen ;assume typed already
ora a
jnz ccp0
ccp:
;enter here on each command or error condition
lxi sp,stack
call crlf ;print d> prompt, where d is disk name
call cselect ;get current disk number
adi 'A'
call printchar
mvi a,'>'
call printchar
call readcom ;command buffer filled
ccp0: ;(enter here from initialization with command full)
lxi d,buff ;default dma address at buff
call setdma
call cselect ;current disk number saved
sta cdisk
call fillfcb0 ;command fcb filled
cnz comerr ;the name cannot be an ambiguous reference
lda sdisk
ora a
jnz userfunc
;check for an intrinsic function
call intrinsic
lxi h,jmptab ;index is in the accumulator
mov e,a ;index in d,e
mvi d,0
dad d
dad d
mov a,m
inx h
mov h,m
mov l,a
pchl
;pc changes to the proper intrinsic or user function
jmptab:
dw direct ;directory search
dw erase ;file erase
dw type ;type file
dw save ;save memory image
dw rename ;file rename
dw user ;user number
dw userfunc;user-defined function
ifndef noserial
badserial:
LXI H,76F3H ;'DI HLT' instructions.
;typo "lxi h,di or (hlt shl 8)" here originally,
;corrected by comparing to disassembly of Clark Calkins.
shld ccploc
lxi h,ccploc
pchl
endif
;utility subroutines for intrinsic handlers
readerr:
;print the read error message
lxi b,rdmsg
jmp print
rdmsg: db "READ ERROR",0
nofile:
;print no file message
lxi b,nofmsg
jmp print
nofmsg: db "NO FILE",0
getnumber: ;read a number from the command line
call fillfcb0 ;should be number
lda sdisk ;cannot be prefixed
ora a
jnz comerr
;convert the byte value in comfcb to binary
lxi h,comfcb+1 ;(b=0, c=11)
lxi b,11
;value accumulated in b, c counts name length to zero
conv0: mov a,m
cpi ' '
jz conv1
;more to scan, convert char to binary and add
inx h ;valid?
sui '0'
cpi 10
jnc comerr
mov d,a ;save value
mov a,b ;mult by 10
ani 11100000b
jnz comerr
mov a,b ;recover value
rlc ;*8
rlc
rlc
add b
jc comerr
add b ;*8+*2 = *10
jc comerr
add d ;+digit
jc comerr
mov b,a ;for another digit
dcr c
jnz conv0
ret
conv1: ;end of digits, check for all blanks
mov a,m ;blanks?
cpi ' '
jnz comerr
inx h
dcr c
jnz conv1
mov a,b ;recover value
ret
movename:
;move 3 characters from h,l to d,e addresses
mvi b,3
move0: mov a,m
stax d
inx h
inx d
dcr b
jnz move0
ret
addhcf: ;buff + a + c to h,l followed by fetch
lxi h,buff
add c
call addh
mov a,m
ret
setdisk:
;change disks for this command, if requested
xra a ;clear disk name from fcb
sta comfcb
lda sdisk ;no action if not specified
ora a
rz
dcr a ;already selected
lxi h,cdisk
cmp m
rz
jmp select
resetdisk:
;return to original disk after command
lda sdisk ;no action if not selected
ora a
rz
dcr a ;same disk
lxi h,cdisk
cmp m
rz
lda cdisk
jmp select
;individual intrinsics follow
direct:
;directory search
call fillfcb0 ;comfcb gets file name
call setdisk ;change disk drives if requested
lxi h,comfcb+1 ;may be empty request
mov a,m
cpi ' ' ;skip fill of ??? if not blank
jnz dir1
;set comfcb to all ??? for current disk
mvi b,11 ;length of fill ????????.???
dir0: mvi m,'?'
inx h
dcr b
jnz dir0
;not a blank request, must be in comfcb
dir1: mvi e,0 ;E counts directory entries
push d
call searchcom ;first one has been found
cz nofile ;not found message
dir2: jz endir
;found, but may be system file
lda dcnt ;get the location of the element
rrc
rrc
rrc
ani 1100000b
mov c,a
;c contains base index into buff for dir entry
mvi a,sysfile ;value to A
call addhcf
ral ;skip if system file
jc dir6
;c holds index into buffer
;another fcb found, new line?
pop d
mov a,e
inr e
push d
;e=0,1,2,3,...new line if mod 4 = 0
ani 11b ;and save the test
push psw
jnz dirhdr0 ;header on current line
call crlf
push b
call cselect
pop b
;current disk in A
adi 'A'
call printbc
mvi a,':'
call printbc
jmp dirhdr1 ;skip current line hdr
dirhdr0:
call blank ;after last one
mvi a,':'
call printbc
dirhdr1:
call blank
;compute position of name in buffer
mvi b,1 ;start with first character of name
dir3: mov a,b ;buff+a+c fetched
call addhcf
ani 7fh ;mask flags
;may delete trailing blanks
cpi ' ' ;check for blank type
jnz dir4
pop psw ;may be 3rd item
push psw
cpi 3 ;place blank at end if not
jnz dirb
mvi a,9 ;first char of type
call addhcf
ani 7fh
cpi ' '
jz dir5
;not a blank in the file type field
dirb: mvi a,' ' ;restore trailing filename chr
dir4:
call printbc ;char printed
inr b
mov a,b
cpi 12
jnc dir5
;check for break between names
cpi 9 ;for another char
jnz dir3
;print a blank between names
call blank
jmp dir3
dir5: ;end of current entry
pop psw ;discard the directory counter (mod 4)
dir6: call break_key ;check for interrupt at keyboard
jnz endir ;abort directory search
call searchn ;for another entry
jmp dir2
endir: ;end of directory scan
pop d ;discard directory counter
jmp retcom
erase:
call fillfcb0 ;cannot be all ???'s
cpi 11
jnz erasefile
;erasing all of the disk
lxi b,ermsg
call print
call readcom
lxi h,comlen ;bad input
dcr m
jnz ccp
inx h
mov a,m
cpi 'Y'
jnz ccp
;ok, erase the entire diskette
inx h ;otherwise error at retcom
shld comaddr
erasefile:
call setdisk
lxi d,comfcb
call delete
inr a ;255 returned if not found
cz nofile ;no file message if so
jmp retcom
ermsg: db "ALL (Y/N)?",0
type:
call fillfcb0 ;don't allow ?'s in file name
jnz comerr
call setdisk ;open the file
call openc
jz typerr ;zero flag indicates not found
;file opened, read 'til eof
call crlf ;read first buffer
lxi h,bptr
mvi m,255
type0: ;loop on bptr
lxi h,bptr ;end buffer
mov a,m
cpi 128
jc type1 ;carry if 0,1,...,127
push h
;read another buffer full
call diskreadc
pop h ;recover address of bptr
jnz typeof ;hard end of file
xra a ;bptr = 0
mov m,a
type1: ;read character at bptr and print
inr m ;bptr = bptr + 1
lxi h,buff ;h,l addresses char
call addh
mov a,m
cpi eofile
jz retcom
call printchar
call break_key ;abort if break
jnz retcom
jmp type0 ;for another character