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
|
; CPSCPM.ASM
; KERMIT - (Celtic for "FREE")
;
; This is the CP/M-80 implementation of the Columbia University
; KERMIT file transfer protocol.
;
; Version 4.0
;
; Copyright June 1981,1982,1983,1984
; Columbia University
;
; Originally written by Bill Catchings of the Columbia University Center for
; Computing Activities, 612 W. 115th St., New York, NY 10025.
;
; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
; others.
;
; This file duplicates the CP/M DIR and ERA functions so we don't have
; to exit.
;
; revision history:
;
;edit 14, 1-Apr-1991 by MF. Correct a bug which crept in with edit 13 which
; caused any control-key other than ^Y or ^Z to act like ^X after a key
; had been depressed to halt output of the TYPE/PRINT commands.
;edit 13, 25-Mar-1991 by MF. Make the TYPE command always abort to Kermit
; command-level if ^C is entered on the console even if multiple files
; are being typed via wild-cards. Make ^X typed on the console abort
; typeout of the current file and begin typeout of the next file,
; if any, otherwise go back to Kermit command-level.
; The foregoing also applies to the PRINT command.
;edit 12, 14-Feb-1991 by MF. Call "clrtop" in TYPE command at "type1"
; rather than sending a <ff> directly to the terminal as some
; terminals don't respond to <ff> characters. Thus the screen will be
; cleared (if the terminal allows) before each file is typed.
; Also use "getfil" rather than the bdos "openf" call to open
; files for typing (label "type2"). This tightens up the code.
; Zero "fcbcnt" before starting to type files (label "type0b").
; This apparently fixes a phantom bug which caused incorrect lookup (and
; hence garbage typeout) of files occassionally after a new disk
; was inserted and a SET DEFAULT-DISK was performed to reset the disk
; system. (It looked like parts of other files were being typed, as
; if the directory had been misread or had not been reset.)
;edit 11, 8-Feb-1991 by MF. Cause the bdos call for direct console input
; in "ckchr" **not** to go thru the bdos trap but to call bdos at 0005h
; directly. This corrects a bug wherein if commands such as INPUT
; (which check to see if a keyboard key has been pressed) were executed
; from a TAKE-file, the character following the terminator of such
; commands was being interpreted as that keyboard input, thus causing
; the next command in the TAKE-file to be unrecognized since its
; first character had been eaten as a result of the keyboard check.
; This bug **may** be the cause of a report received by Dr. Martin
; J. Carter of Nottingham University in the U.K. in which Kermit
; was reported to have read a character beyond a command terminator
; in a TAKE-file, making the subsequent command unrecognizable since
; its first character was missing.
;edit 10, 29-Jan-1991 by MF. Use the big buffer for TYPE/PRINT commands.
; Thus, edit 9 has been superseded.
;edit 9, 29-Jan-1991 by MF. Corrected EOF check in TYPE command routine
; following label "type20". a READF call, if successful, gives A=0
; (not A=0FFH) and A not zero if failure. Thus the "INR A" instruction
; checking for EOF was **always** nonzero. The reason the TYPE command
; worked is that CP/M text files indicate the text end-of-file with a
; Control-Z, in which case the TYPE routine branched correctly. In
; other words, this edit is more for aesthetic purposes to satisfy
; purists than something brought about by dire necessity!
;edit 8, 28-Jan-1991 by MF. Added code courtesy of Dr. Martin J. Carter
; of Nottingham University, UK, to use the big buffer for the COPY
; command.
;edit 7, 18-Sep-1990 by MF. Added RENAME routine to implement the
; RENAME (FRENAME) command to rename a CP/M file.
; Modified COPY routine to explicitly reject wild-carded filenames
; by using COMND function CMOFI rather than functions CMIFI and
; CMIFIN to get input and output filenames.
; Modified ERA and COPY routines to not act upon the respective
; commands until a "confirm" is typed. This prevents these
; routines from taking off upon recognition of action characters
; like "?", which can be quite annoying if one is an inexperienced user.
; edit 6, March 11, 1987 by OBSchou. Added in the TYPE and PRINT commands
; Both type to the screen, print also echoes to printer.
;
; edit 5 20 June, 1986. Added support for multiple file FCB buffering.
;
; edit 4: June 16, 1986 OBSchou at Loughborough University, UK
; added in a test to prevent a DIR command issued from a TAKE command
; being interruped by the next character in the take command buffer.
; Also added code for USER nn. (Well, its OS related,is it not?)
;
; edit 3: July 8, 1984 (CJC)
; Merge modifications from Toad Hall: support LASM (linked by CPSTT,
; links to CPSWLD), use prcrlf where appropriate.
;
; edit 2: June 5, 1984 (CJC)
; documentation and formatting; delete unused code (dir13); add module
; version string.
;
; edit 1: May, 1984 (CJC)
; extracted from CPMBASE.M80 version 3.9; modifications are described in
; the accompanying .UPD file.
;
cpmver: db 'CPSCPM.ASM (14) 1-Apr-1991$' ; name, edit number, date
npl EQU 04H ;Number of names per line for dir command.
; This is the DIR command. Display the name and size of all files
; matching the filespec.
; here from: kermit
;
; Note: This is abstracted from Keith Peterson's DIRF.ASM
; directory print function. Thanks again Keith.
;
;
dir: lxi d,fcb ;Where to put the data, if any.
mvi a,cmifin
call comnd ;Parse a full or piece of file-spec
jmp dir2 ;Didn't get a FULL file-spec
jmp dir4 ;lets do it
;
;
;Make FCB all '?' to match any file
dir2: lda fcb
cpi ' ' ;CMIFIN leaves that as ' '
jnz dir2a ;he typed at least x:
xra a
sta fcb ;default drive
dir2a: lxi h,fcb+1
mvi b,11 ;FN+FT count.
dir3: mvi m,'?' ;Store '?'s in FCB.
inx h
dcr b
jnz dir3
;Print signon message and drive name
dir4: call getun ; get current user number
lda fcb
ora a ;if not zero, get default
jnz dir4a
lda curdsk ;get default
dir4a: adi 'A'-1 ;Asciize it
sta dnam14+2 ;[4] add in user no, and Save it in message.
lda temp1+1 ;[4] most sig. user number
cpi '0' ;[4] if zero set space
jnz dir4b
mvi a,' ' ;[4] space
dir4b: sta dnam14 ;[4]
lda temp1
sta dnam14+1 ;[4] ls user number digit
call prcrlf
lxi d,inms14 ;Point to message
call prtstr
;
;Initialize number of names per line counter
mvi a,npl ;Nr. names per line.
sta nnams ;Init counter.
lda hidefs ; are we doing file size?
ana a
jnz dir4c ; we are not showing file size,
lda nnams
inr a
sta nnams ; so we can show another name per line
dir4c: xra a ; clear the flags ready for multi-sector buffering
sta fcbcnt ; clear fcb counter
sta mfflg1
sta mfflg2
sta mfflg3
lxi h,fcb0 ; reset pointer for fcb save space
shld xfcbptr
;
call dir26 ;Get disk parameters
xra a ;[5] say first time round, so no spare fcbs
sta fcbcnt ;[5]
dir5: call mfname ;get some names
jnc dir6 ;got one
jmp dir17 ;got none - do summary
dir6: ;Check for console break
lda takflg ;[4] ... but not if issued from TAKE....
ana a ;[4]
jnz dir6a ;[4] we do the lot regardless.
mvi c,consta ;Ck status of kbd.
call bdos
ora a ;Any key pressed?
jz dir6a ;nope, keep going
mvi c,conin
call bdos ;gobble key
jmp dir17 ;and print summary only
;Print an entry
dir6a:
lxi h,fcb+1 ;point to Filename
mvi b,8 ;File name length.
call dir11 ;Type filename.
mvi a,'.' ;Period after FN.
call dir10
mvi b,3 ;Get the filetype.
call dir11
call dir25 ;print size
lxi h,nnams ;Point to names counter.
dcr m ;One less on this line.
push psw
cnz dir7 ;No cr-lf needed, do fence.
pop psw
cz dir12 ;Cr-lf needed.
jmp dir5
;Print space, fence character, then space
dir7: call dir9
mvi a,':' ;Fence character.
call dir10
jmp dir9
; dir8 - Print two spaces
; dir9 - Print one space
; dir10 - Type char in A register
dir8: call dir9
dir9: mvi a,' '
dir10: push b
push d
push h
mov e,a ;Char to E for CP/M.
mvi c,conout ;Write char to console function.
call bdos
pop h
pop d
pop b
ret
;Type (B) characters from memory (HL)
dir11: mov a,m
ani 7FH ;Remove CP/M 2.x attributes.
call dir10
inx h
dcr b
jnz dir11
ret
;CR-LF routine. HL=NNAMS upon entry
dir12: push b
push d
push h
call prcrlf ;Print CR/LF [Toad Hall]
pop h ;(did use call to dir10, but slooow)
pop d
pop b
mvi m,npl ;Number of names per line.
lda hidefs ; are we showing file size?
ana a
rnz ; no, so all ok
inr m ; else show another file per line
ret
;Exit - All done, return via jmp (as for all main commands)
dir16: call prcrlf
lda curdsk
dcr a ;relative to 0
mov e,a
mvi c,logdsk
call bdos ;back to "logged in" disk
jmp kermit ;...and return to kermit.
;
;Determines free space remaining
;
dir17: xra a
sta mfflg1 ;clean up MFNAME
sta mfflg2
lda fcb ; get drive number from FCB
ora a
jz dir18 ; default?
dcr a ; no, make requested drive current drive.
mov e,a
mvi c,logdsk
call bdos
dir18: call sysspc ; get space available for current drive
push h
lxi d,inms15 ;"Drive "
call prtstr
lda fcb ;If no drive, get
ora a ;logged in drive
jnz dir24
mvi c,rddrv
call bdos
inr a
dir24: adi 'A'-1
sta inms16
lxi d,inms16 ;"x has "
call prtstr
pop h ;Get number of bytes available
call nout
lxi d,inms17 ;"K bytes free"
call prtstr
jmp dir16 ;all done
;Compute the size of the file
dir25: lda hidefs ; do we show file size?
ana a ; if non zero, we dont.
rz ; so just return
mvi c,cflsz ;get file-size
lxi d,fcb
call bdos
lda fcbrno ;shift least sign. part
lxi b,0 ;init bc
mov l,a
ani 7
jz dir250 ;even K
lxi b,1 ;save for later
dir250: push b ;save 0 or 1 to add to size
mvi b,3 ;shift 3 bits
dir25a: xra a ;clear sign
lda fcbrno+1 ;get most sig byte
rar ;shift right
sta fcbrno+1 ;put back
lda fcbrno ;get least sig part
rar
sta fcbrno
dcr b ;loop 3 times
jnz dir25a
mov l,a ;size in HL
lda fcbrno+1
mov h,a
pop b ;get 0 or 1
dad b ;round up to KB used
lda bmask ;get (sectors/block)-1
rrc
rrc ;get (K/block)-1
rrc
ani 1FH
mov c,a
dad b ;add (K/block)-1 to size to round up
cma ;make a mask
ana l ;truncate after rounding up
mov l,a
push h
lxi b,-10 ;subtract 10
dad b
jc dir25d ;>= 10
call dir8 ; print a leading space
jmp dir25e
dir25d: pop h ;get size again
push h
lxi b,-100 ;subtract 100
dad b
jc dir25e ;>= 100
call dir9 ; print another leading space
dir25e: call dir9 ;a space
pop h ;get size back
call nout ;..go print it
mvi a,'k' ;..and follow with K size
call dir10
ret
dir26: mvi c,gtdpar ;current DISK PARAMETER BLOCK
call bdos
inx h
inx h
mov a,m ;Get Block Shift Factor
sta bshiftf
inx h ;Bump to Block Mask
mov a,m ;get it
sta bmask
inx h
inx h
mov e,m ;Get Max Block number
inx h
mov d,m
xchg
shld bmax ;Put it away
ret
;
; ERA command - erase a CP/M file
; here from: kermit
era: mvi a,cmifi ;Parse a file-spec
lxi d,fcb ;into FCB
call comnd
jmp kermit ;bad parse
mvi a,cmcfm ;[MF]Get a confirm from the user
call comnd ;[MF]...
jmp kermit ;[MF]NO? try another command
lxi d,fcb
mvi c,sfirst ;check if valid
call bdos
inr a ;0 if FILE not found
jnz era1 ;found at least one
lxi d,erms15 ;"unable to find file"
call prtstr
jmp kermit
era1: lxi d,fcb
mvi c,delf
call bdos
lxi d,inms18 ;" File(s) erased"
call prtstr
jmp kermit
; USER - select a new user. This is an unusual routine in that the user
; enters a number. The others take on/off or filename (except
; set escape
;
user: mvi a,cmnum ; go parse a number
call comnd
jmp kermit ; if we can not do it, quit to command loop
mvi a,cmcfm ; get a confirm from the user
call comnd
jmp kermit ; if no, then try another command
lhld number ; else get the number...
xchg ; until a non valid digit is typed (eg cr)
lxi h,-32 ; if a carry, then ok
dad d ; ... else its above 32
jc user1
xchg ; restor number in hl again
mov a,l ; Lets save it
sta curusr ; as current user number
mov e,l ; get user no to e...
mvi c,usrcod
call bdos
call getun ; get user number to temp1 and temp2
lda temp2
cpi '0'
jnz user0 ; dont do ms digit if a zero
mvi a,' '
user0: sta kerm1 ; save into string etc
sta dnam14 ; also for dir command
lda temp1
sta kerm1+1
sta dnam14+1 ; also for dir command
jmp kermit
user1: lxi d,erms23 ; tell user sorry
call prtstr
jmp kermit
;
; TYPE - type a file or files to the console.
;
; This utility also used by print, where the characters printed to
; the console are also copied to the printer if the prnfl flag
; is non-zero. Uses mfname to type (print) multiple names.
; Each file is preceeded with a formfeed character (usually clears
; the screen on a VDU)
;
type: mvi a,cmifi ; parse a file name
lxi d,fcb ; let the parser know where the FCB is
call comnd
jmp type02 ; if error say so
type0b:
xra a ; clear some flags for mfname
sta mfflg1
sta mfflg2
sta mfflg3
sta fcbcnt ;[12]...
lxi h,fcb0 ; reset the fcb pointers etc
shld fcbptr
call mfname
jc type02 ; match not found
;[MF][10]The following code to type a file using a 1-sector buffer has
;[MF][10]been replaced by code to use the "big buffer" -- 30-Jan-1991
;type1: lxi d,buff ; point to the default DMA address
; mvi c,setdma
; call bdos ; tell bdos where to put the dma address
; mvi a,ff ; do a form feed
; call typit
; xra a ; clear the character count
; sta chrcnt
;
;type2: mvi c,openf ; open the file for reading
; lxi d,fcb
; xra a ; but first clear bits of fcb...
; sta fcb+12
; sta fcb+14
; sta fcb+15
; sta fcb+32
; call bdos ; NOW open the file
;
;type20: mvi c,readf ; open up the file and read first sector
; lxi d,fcb
; call bdos
;;[MF][9]Correct EOF test below (next two instructions)
;; inr a ; if 0ffh returned, error. Assume EOF
;; jz typex ; so exit from here
; ora a ;[MF][9]If error, assume EOF
; jnz typex ;[MF][9]so exit
; lxi h,0 ; else clear the pointer into the file
; shld typptr
;
;
;type2a: lxi d,buff ;ok, so lets get the byte to print
; lhld typptr
; dad d ; add offset to the DMA base
; mov a,m ; and get character to type (print)
; ani 7fh ; make sure it is printable
; cpi 20h ; is it a control character?
; jp type3
; cpi 09h ; if its a tab, then expand it
; jnz type2b
;
;type2c: mvi a,' ' ; send a space
; call typit ; type it
; lda chrcnt ; get the number of chrs so far
; ani 7h ; see of an 8th pos?
; jnz type2c ; loop until all spaces done, then exit
; jmp type4
;
;type2b: cpi cr ; is it a cr or lf?
; jnz type2d
; call typit ; do a cr
; xra a
; sta chrcnt ; cr of lf => clear character count
; jmp type4 ; and exit
;
;type2d: cpi lf
; jnz type2e
; call typit ; print the character
; xra a
; sta chrcnt ; cr or lf clears the character count
; jmp type4
;
;type2e: cpi cntlz ; is it end of file?
; jnz type2f
; jmp typex ; yes, so close and try for another file
;
;type2f: push psw ; control char - save the character
; mvi a,'^' ; send control chars as ^A, for ex.
; call typit
; pop psw
;
;type3: call typit
;
;
;type4: lhld typptr ; get the pointer
; inx h
; shld typptr ; up it by one character, and save it.
; mov a,l ; lets see if the sector has been typed
; ana a
; jm type20 ; if 80h => read new sector
; jmp type2a ; else just continue along
;[MF][10]The following code uses the "big buffer" to read the file
;[MF][10]which is to be typed
;[12]Clear the screen explicitly as some terminals don't respond
;[12]to the <ff> character.
;type1: mvi a,ff ; do a form feed
; call typit
type1: call clrtop ;[12] Clear the screen
xra a ; clear the character count
sta temp1 ;[MF]alias column counter
type2:
;[12]Eliminate call to openf in favor of call to "getfil"
; mvi c,openf ; open the file for reading
lxi d,fcb
; xra a ; but first clear bits of fcb...
; sta fcb+12
; sta fcb+14
; sta fcb+15
; sta fcb+32
; call bdos ; NOW open the file
call getfil ;[12] NOW open the file
type20: call inbuf ;[MF]Fill input buffers
jmp typex ;[MF]Tru end-of-file reached
jmp type21 ;[MF]Begin typing/printing characters
type2a: lda chrcnt ;[MF]Get buffer character counter
dcr a ;[MF]and decrement it
jm type20 ;[MF]Get more characters if needed
type21: sta chrcnt ;[MF]else remember new buffer character counter
lhld bufpnt ;[MF]Now get character pointer
mov a,m ; and get character to type (print)
inx h ;[MF]Increment the pointer
shld bufpnt ;[MF]and remember it
ani 7fh ; make sure character is printable
cpi 20h ; is it a control character?
jp type3
cpi 09h ; if its a tab, then expand it
jnz type2b
type2c: mvi a,' ' ; send a space
call typit ; type it
lda temp1 ;[MF]Get the number of characters so far
ani 7h ; see if an 8th pos?
jnz type2c ; loop until all spaces done, then exit
jmp type2a ;[MF]and continue
type2b: cpi cr ; is it a cr or lf?
jnz type2d
call typit ; do a cr
xra a
sta temp1 ; cr or lf => clear character count
jmp type2a ;[MF]and continue
type2d: cpi lf
jnz type2e
call typit ; print the character
xra a
sta temp1 ; cr or lf clears the character count
jmp type2a ;[MF]and continue
type2e: cpi cntlz ; is it end of file?
jnz type2f
jmp typex ; yes, so close and try for another file
type2f: push psw ; control char - save the character
mvi a,'^' ; send control chars as ^A, for ex.
call typit
pop psw
type3: call typit
jmp type2a ; and continue along
typex: mvi c,closf
lxi d,fcb
call bdos ; close the file
mvi a,cr ; send cr lf to screen/printer to clear buffers
call typit
mvi a,lf
call typit
call mfname ; and see if there are other files to type
jnc type1 ; yup, so go do it
xra a ; make sure the flag is reset
sta prnfl
jmp kermit ; then exit.
typex0: mvi c,closf ;[MF]Close the file
lxi d,fcb ;[MF]...
call bdos ;[MF]...
mvi a,cr ;[MF]Clear buffers
call typit ;[MF]...
mvi a,lf ;[MF]...
call typit ;[MF]...
xra a ;[MF]Clear flag
sta prnfl ;[MF]...
lda takflg ;[MF]See if we're TAKEing commands
ani 1 ;[MF]from a file
cnz closet ;[MF]If we are, abort TAKE-file processing
jmp kermit ;[MF]Back to Kermit command-level
; error for file not found for type
type02: lxi d,nofile ; say no file name (its invalid)
call prtstr
xra a
sta prnfl ; clear the flag
jmp kermit ; so abort
typit: mov e,a
call ckqtyp ; see if a cntl-c or other character from user
jmp typit2 ;[MF] Control-C entered, abort
jc typit1 ; CNTL-X entered, so abort file [MF]
push d ; save for a bit
call outcon ; send it to the console
lda temp1 ; update the number of characters sent[MF]
inr a
sta temp1 ;[MF]
pop d
lda prnfl ; see if we have to print it too
ana a
rz
call outprn ; send character to printer (buffer)
ret
typit1: pop d ; adjust stack again
jmp typex ; and say we are done (for this file)
typit2: pop d ;[MF] Adjust the stack
jmp typex0 ;[MF] and abort file typeout completely
; CKQTYP - CHeck for requested Quiet TYPe (ie hang on a second)
; Routine sees if the user has typed ANY key. If a key HAS been pressed
; see if its a Control-c. If so, flag for an abort, else wait for
; a second entry from the user. If its a Control C, flag an abort
; else continue with the print.
; note: only the DE registers maintained. All others destroyed.
; **NOTE** CKQTYP now gives a nonskip return if Control-C is typed,
; a skip-return with carry set if a Control-X is typed and a skip-return
; with carry clear if any other character is typed as the second
; character.
ckqtyp: push d ; save the character to be printed
call ckchr ; see if user entered a character
ani 7fh ; strip parity etc
jz ckqty3 ; nothing entered, so go on as usual (See below)
cpi ctrlc ; control c?
jz ckqt1a ;[MF] Yup, give nonskip return
cpi 'X'-100o ;[MF] If Control-X,
jz ckqty1 ; yup, set carry and exit
ckqty2: call ckchr ; another character to wait for (ie pause)
ani 7fh
jz ckqty2 ; wait until some input
cpi ctrlc ; if control c, abort
jz ckqt1a ;[MF] ...
cpi 'X'-100o ;[MF] Control-X?
jz ckqty1 ; yuss, so flag abort file [MF]
ckqty3: pop d ; else restore the character to be typed [MF]
; ret ; no, so continue with type/print
stc ;[MF]Set carry
cmc ;[MF]Then clear it
jmp rskp ;[MF] Continue with type/print (skip ret)
ckqty1: pop d ; restore stack again
stc ; set carry and return
; ret
jmp rskp ;[MF] ...
ckqt1a: pop d ;[MF] Adjust stack
ret ;[MF] and return
;[MF][14]No longer need these lines
;ckqty3: pop d ; restore stack again
;; ret
; stc ;[MF] Clear carry
; cmc ;[MF] ...
; jmp rskp ;[MF] and give skip return
ckchr: call selcon ; make sure we are talking to the console
mvi e,0ffh ; see if user has any input for us
mvi c,dconio
; call bdos ;[11]Don't go thru bdos trap
call 0005h ;[11]Call bdos directly
ret ; This routine does not care what comes back
;
; COPY - routine to copy from a source file to a destination file
; from the Kermit command state.
;
; Note. This could be tricky, as there are several forms of copy
; copy d:source.ext d:dest.ext (Easy one)
; copy d:source.ext d: (File to another drive)
; copy d:source.??? d: (several files)
; copy d:*.* d: (Several files)
;
; Initially, lets make it top one, and see how we go, ok?
;
;
;Things to do for copy:
; 1) get source name
; 2) get target name
; 3) if both source and destination = abort
; 4) if source does not exist abort
; 5) attempt to delete destination file if it exists
; 6) open source and destination files
; 7) copy file across
; 8) close all files
; 9) return to command mode
;
copy: ; Here goes...
; 1) get source file name
mvi a,cmofi ; go parse a file name
;[MF]Nonwild
lxi d,cfcbs ; use the source for copy FCB (Allows copy
call comnd ; from a TAKE file etc)
jmp kermit ; if error, abort
; 2) get target name
mvi a,cmofi ; go parse a target file name
;[MF]Again, nonwild
lxi d,cfcbd ; use destination fcb
call comnd ; get it
jmp kermit ;[MF]Couldn't.
mvi a,cmcfm ;[MF]Get a confirm from the user
call comnd ;[MF]...
jmp kermit ;[MF]No? try another command
; 3) see if both target and source are equal
copy0: mvi b,12 ; we are gonna test drive, file and extention
lxi d,cfcbs ; from source file name...
lxi h,cfcbd ; to destination file name
xra a ; clear flag for difference found
sta equflg
copy1: ldax d ; get source file name character
cmp m ; test with targer file name
jz copy2 ; if equal, do nothing
lda equflg ; else update flage (ie files are different)
inr a
sta equflg
copy2: inx h
inx d
dcr b
jnz copy1 ; up pointers and test for next char
lda equflg ; if still null, then its a daft thing to do
ana a
jnz copy3 ; its not a daft thing to do
lxi d,samems ; load up "File source and destination the same"
call prtstr ; tell user
jmp kermit ; and try again
; 4) If source does not exist, abort. Assume we have a full file name.
copy3:
lxi d,cfcbs ; load up source fcb
mvi c,openf ; open file
call bdos
inr a ; error on open?
jnz copy4
lxi d,nofile ; assume file not found
call prtstr
jmp kermit ; and die
copy4: lxi d,cfcbd ; load up destination fcb
mvi c,delf ; destroy target name if it exists
call bdos ; ignore error messages
lxi d,cfcbd ; load up destination fcb
mvi c,makef ; make a file
call bdos
inr a ; make error?
jnz copy4a
lxi d,erms12 ; no directory space
call prtstr
jmp copy7 ; close source file
copy4a: lxi d,cfcbd ; load up destination fcb...
mvi c,openf ; for open
call bdos
inr a ; error on open?
jnz copy5 ; could do with better error detection...
lxi d,erms15 ;... but assume its a disk full
call prtstr
jmp copy7 ; close source file and jmp kermit
;copy5: lxi d,buff ; set default dma address to 80h
; mvi c,setdma
; call bdos
;
;copy6: lxi d,cfcbs ; copy routine proper.. get a sector
; mvi c,readf
; call bdos
; ana a ; error reading the file?
; jnz copy8 ; yes, then cope with it (could be EOF)
; [MaJoC 910128] The above code, which reads single logical sectors,
; is grossly inefficient with systems (most of them) with larger physical
; disk blocks and a single shared read/write buffer. Use of INBUF below
; is functionally equivalent at this level, but does actual disk reads
; by the Big Buffer-ful.
copy5:
xra a ; Initialise INBUF, to force reading of
sta seccnt ; the first Big Buffer-ful. Redundant
sta endsts ; if file opened by GETFIL (or variant).
sta eoflag ;[MF]...
lxi h,cfcbs ;[MF]Copy source fcb to default fcb
lxi d,fcb ;[MF]since INBUF uses the default fcb
lxi b,33 ;[MF]...
call mover ;[MF]...
copy6:
; INBUF returns a pointer to the next logical bufferful via bufpnt, filling
; the Big Buffer as necessary, with skip return for success and nonskip on
; error or EOF.
call inbuf ; Start of copy proper: get bufferful.
jmp copy8 ; Nonskip return: treat as EOF.
lhld bufpnt ; Skip return => OK: pick up buffer pointer.
xchg
mvi c, setdma ; Tell system where to write from.
call bdos
; [majoc 910128: end]
lxi d,cfcbd ; send sector to destination
mvi c,writef
call bdos
ana a ; error on write (disk full?)
jz copy6 ; no error, so do another sector.
lxi d,erms17 ; say disk is full
call prtstr
lxi d,cfcbd ; close the output file...
mvi c,closf
call bdos
lxi d,cfcbd ; ... and then delete it
mvi c,delf
call bdos ; ... and then drop through to...
copy7: lxi d,cfcbs ; here to close the source FCB
mvi c,closf
call bdos
jmp kermit
copy8: lxi d,cfcbd ; orderly close of destination file
mvi c,closf
call bdos
jmp copy7 ; now close the source file as well.
;
;[MF]RENAME - Rename a file
;
rename: mvi a,cmofi ;[MF]Get nonwild filename
lxi d,cfcbs ;[MF]Use "COPY" fcb's
call comnd ;[MF]...
jmp kermit ;[MF]Couldn't get it.
mvi a,cmofi ;[MF]Get filespec to rename it to
lxi d,cfcbd ;[MF]...
call comnd ;[MF]...
jmp kermit ;[MF]Couldn't.
renam0: lxi d,cfcbs ;[MF]See if file to be renamed exists
mvi c,openf ;[MF]by trying to open it
call bdos ;[MF]...
inr a ;[MF]Does the file exist?
jnz renam1 ;[MF]Yes
lxi d,nofile ;[MF]No, inform the user
call prtstr ;[MF]...
jmp kermit ;[MF]and bomb
renam1: lxi d,cfcbd ;[MF]Point to rename filespec
mvi c,openf ;[MF]Set function code to
call bdos ;[MF]See if rename file exists
inr a ;[MF]Does it?
jz renam2 ;[MF]No
lxi d,erms31 ;[MF]Yes, complain
call prtstr ;[MF]...
jmp kermit ;[MF]and depart with tail between legs
renam2: lxi h,cfcbd ;[MF]Now get rename filespec again
lxi d,cfcbs+16 ;[MF]and where to copy it to
lxi b,16 ;[MF]We copy drive, filename, filetype, extent
call mover ;[MF]...
lxi d,cfcbs ;[MF]Point to fcb for rename
mvi c,renam ;[MF]Get rename function
call bdos ;[MF]Try to rename the file
inr a ;[MF]Did we succeed?
jnz kermit ;[MF]Yes, done
lxi d,erms16 ;[MF]No, complain
call prtstr ;[MF]...
jmp kermit ;[MF]and start over
IF lasm
LINK CPSWLD
ENDIF;lasm [Toad Hall]
|