aboutsummaryrefslogtreecommitdiff
path: root/src/cpscpm.asm
blob: 49df54fd3769ba28084d2a9ba6a12dd96afa206b (plain)
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]