]> cloudbase.mooo.com Git - kermit-80.git/blob - cpscpm.asm
Convert line endings to CP/M format (cr/lf).
[kermit-80.git] / cpscpm.asm
1 ; CPSCPM.ASM
2 ; KERMIT - (Celtic for "FREE")
3 ;
4 ; This is the CP/M-80 implementation of the Columbia University
5 ; KERMIT file transfer protocol.
6 ;
7 ; Version 4.0
8 ;
9 ; Copyright June 1981,1982,1983,1984
10 ; Columbia University
11 ;
12 ; Originally written by Bill Catchings of the Columbia University Center for
13 ; Computing Activities, 612 W. 115th St., New York, NY 10025.
14 ;
15 ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
16 ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
17 ; others.
18 ;
19 ; This file duplicates the CP/M DIR and ERA functions so we don't have
20 ; to exit.
21 ;
22 ; revision history:
23 ;
24 ;edit 14, 1-Apr-1991 by MF. Correct a bug which crept in with edit 13 which
25 ; caused any control-key other than ^Y or ^Z to act like ^X after a key
26 ; had been depressed to halt output of the TYPE/PRINT commands.
27 ;edit 13, 25-Mar-1991 by MF. Make the TYPE command always abort to Kermit
28 ; command-level if ^C is entered on the console even if multiple files
29 ; are being typed via wild-cards. Make ^X typed on the console abort
30 ; typeout of the current file and begin typeout of the next file,
31 ; if any, otherwise go back to Kermit command-level.
32 ; The foregoing also applies to the PRINT command.
33 ;edit 12, 14-Feb-1991 by MF. Call "clrtop" in TYPE command at "type1"
34 ; rather than sending a <ff> directly to the terminal as some
35 ; terminals don't respond to <ff> characters. Thus the screen will be
36 ; cleared (if the terminal allows) before each file is typed.
37 ; Also use "getfil" rather than the bdos "openf" call to open
38 ; files for typing (label "type2"). This tightens up the code.
39 ; Zero "fcbcnt" before starting to type files (label "type0b").
40 ; This apparently fixes a phantom bug which caused incorrect lookup (and
41 ; hence garbage typeout) of files occassionally after a new disk
42 ; was inserted and a SET DEFAULT-DISK was performed to reset the disk
43 ; system. (It looked like parts of other files were being typed, as
44 ; if the directory had been misread or had not been reset.)
45 ;edit 11, 8-Feb-1991 by MF. Cause the bdos call for direct console input
46 ; in "ckchr" **not** to go thru the bdos trap but to call bdos at 0005h
47 ; directly. This corrects a bug wherein if commands such as INPUT
48 ; (which check to see if a keyboard key has been pressed) were executed
49 ; from a TAKE-file, the character following the terminator of such
50 ; commands was being interpreted as that keyboard input, thus causing
51 ; the next command in the TAKE-file to be unrecognized since its
52 ; first character had been eaten as a result of the keyboard check.
53 ; This bug **may** be the cause of a report received by Dr. Martin
54 ; J. Carter of Nottingham University in the U.K. in which Kermit
55 ; was reported to have read a character beyond a command terminator
56 ; in a TAKE-file, making the subsequent command unrecognizable since
57 ; its first character was missing.
58 ;edit 10, 29-Jan-1991 by MF. Use the big buffer for TYPE/PRINT commands.
59 ; Thus, edit 9 has been superseded.
60 ;edit 9, 29-Jan-1991 by MF. Corrected EOF check in TYPE command routine
61 ; following label "type20". a READF call, if successful, gives A=0
62 ; (not A=0FFH) and A not zero if failure. Thus the "INR A" instruction
63 ; checking for EOF was **always** nonzero. The reason the TYPE command
64 ; worked is that CP/M text files indicate the text end-of-file with a
65 ; Control-Z, in which case the TYPE routine branched correctly. In
66 ; other words, this edit is more for aesthetic purposes to satisfy
67 ; purists than something brought about by dire necessity!
68 ;edit 8, 28-Jan-1991 by MF. Added code courtesy of Dr. Martin J. Carter
69 ; of Nottingham University, UK, to use the big buffer for the COPY
70 ; command.
71 ;edit 7, 18-Sep-1990 by MF. Added RENAME routine to implement the
72 ; RENAME (FRENAME) command to rename a CP/M file.
73 ; Modified COPY routine to explicitly reject wild-carded filenames
74 ; by using COMND function CMOFI rather than functions CMIFI and
75 ; CMIFIN to get input and output filenames.
76 ; Modified ERA and COPY routines to not act upon the respective
77 ; commands until a "confirm" is typed. This prevents these
78 ; routines from taking off upon recognition of action characters
79 ; like "?", which can be quite annoying if one is an inexperienced user.
80 ; edit 6, March 11, 1987 by OBSchou. Added in the TYPE and PRINT commands
81 ; Both type to the screen, print also echoes to printer.
82 ;
83 ; edit 5 20 June, 1986. Added support for multiple file FCB buffering.
84 ;
85 ; edit 4: June 16, 1986 OBSchou at Loughborough University, UK
86 ; added in a test to prevent a DIR command issued from a TAKE command
87 ; being interruped by the next character in the take command buffer.
88 ; Also added code for USER nn. (Well, its OS related,is it not?)
89 ;
90 ; edit 3: July 8, 1984 (CJC)
91 ; Merge modifications from Toad Hall: support LASM (linked by CPSTT,
92 ; links to CPSWLD), use prcrlf where appropriate.
93 ;
94 ; edit 2: June 5, 1984 (CJC)
95 ; documentation and formatting; delete unused code (dir13); add module
96 ; version string.
97 ;
98 ; edit 1: May, 1984 (CJC)
99 ; extracted from CPMBASE.M80 version 3.9; modifications are described in
100 ; the accompanying .UPD file.
101 ;
102 cpmver: db 'CPSCPM.ASM (14) 1-Apr-1991$' ; name, edit number, date
103
104 npl EQU 04H ;Number of names per line for dir command.
105
106 ; This is the DIR command. Display the name and size of all files
107 ; matching the filespec.
108 ; here from: kermit
109 ;
110 ; Note: This is abstracted from Keith Peterson's DIRF.ASM
111 ; directory print function. Thanks again Keith.
112 ;
113 ;
114 dir: lxi d,fcb ;Where to put the data, if any.
115 mvi a,cmifin
116 call comnd ;Parse a full or piece of file-spec
117 jmp dir2 ;Didn't get a FULL file-spec
118 jmp dir4 ;lets do it
119 ;
120 ;
121 ;Make FCB all '?' to match any file
122 dir2: lda fcb
123 cpi ' ' ;CMIFIN leaves that as ' '
124 jnz dir2a ;he typed at least x:
125 xra a
126 sta fcb ;default drive
127 dir2a: lxi h,fcb+1
128 mvi b,11 ;FN+FT count.
129
130 dir3: mvi m,'?' ;Store '?'s in FCB.
131 inx h
132 dcr b
133 jnz dir3
134 ;Print signon message and drive name
135 dir4: call getun ; get current user number
136 lda fcb
137 ora a ;if not zero, get default
138 jnz dir4a
139 lda curdsk ;get default
140 dir4a: adi 'A'-1 ;Asciize it
141 sta dnam14+2 ;[4] add in user no, and Save it in message.
142 lda temp1+1 ;[4] most sig. user number
143 cpi '0' ;[4] if zero set space
144 jnz dir4b
145 mvi a,' ' ;[4] space
146 dir4b: sta dnam14 ;[4]
147 lda temp1
148 sta dnam14+1 ;[4] ls user number digit
149 call prcrlf
150 lxi d,inms14 ;Point to message
151 call prtstr
152 ;
153 ;Initialize number of names per line counter
154 mvi a,npl ;Nr. names per line.
155 sta nnams ;Init counter.
156 lda hidefs ; are we doing file size?
157 ana a
158 jnz dir4c ; we are not showing file size,
159 lda nnams
160 inr a
161 sta nnams ; so we can show another name per line
162
163 dir4c: xra a ; clear the flags ready for multi-sector buffering
164 sta fcbcnt ; clear fcb counter
165 sta mfflg1
166 sta mfflg2
167 sta mfflg3
168 lxi h,fcb0 ; reset pointer for fcb save space
169 shld xfcbptr
170 ;
171 call dir26 ;Get disk parameters
172 xra a ;[5] say first time round, so no spare fcbs
173 sta fcbcnt ;[5]
174 dir5: call mfname ;get some names
175 jnc dir6 ;got one
176 jmp dir17 ;got none - do summary
177
178 dir6: ;Check for console break
179 lda takflg ;[4] ... but not if issued from TAKE....
180 ana a ;[4]
181 jnz dir6a ;[4] we do the lot regardless.
182
183 mvi c,consta ;Ck status of kbd.
184 call bdos
185 ora a ;Any key pressed?
186 jz dir6a ;nope, keep going
187 mvi c,conin
188 call bdos ;gobble key
189 jmp dir17 ;and print summary only
190
191 ;Print an entry
192 dir6a:
193 lxi h,fcb+1 ;point to Filename
194 mvi b,8 ;File name length.
195 call dir11 ;Type filename.
196 mvi a,'.' ;Period after FN.
197 call dir10
198 mvi b,3 ;Get the filetype.
199 call dir11
200 call dir25 ;print size
201 lxi h,nnams ;Point to names counter.
202 dcr m ;One less on this line.
203 push psw
204 cnz dir7 ;No cr-lf needed, do fence.
205 pop psw
206 cz dir12 ;Cr-lf needed.
207 jmp dir5
208
209 ;Print space, fence character, then space
210 dir7: call dir9
211 mvi a,':' ;Fence character.
212 call dir10
213 jmp dir9
214
215 ; dir8 - Print two spaces
216 ; dir9 - Print one space
217 ; dir10 - Type char in A register
218 dir8: call dir9
219 dir9: mvi a,' '
220 dir10: push b
221 push d
222 push h
223 mov e,a ;Char to E for CP/M.
224 mvi c,conout ;Write char to console function.
225 call bdos
226 pop h
227 pop d
228 pop b
229 ret
230
231 ;Type (B) characters from memory (HL)
232 dir11: mov a,m
233 ani 7FH ;Remove CP/M 2.x attributes.
234 call dir10
235 inx h
236 dcr b
237 jnz dir11
238 ret
239
240 ;CR-LF routine. HL=NNAMS upon entry
241 dir12: push b
242 push d
243 push h
244 call prcrlf ;Print CR/LF [Toad Hall]
245 pop h ;(did use call to dir10, but slooow)
246 pop d
247 pop b
248 mvi m,npl ;Number of names per line.
249 lda hidefs ; are we showing file size?
250 ana a
251 rnz ; no, so all ok
252 inr m ; else show another file per line
253 ret
254
255 ;Exit - All done, return via jmp (as for all main commands)
256 dir16: call prcrlf
257 lda curdsk
258 dcr a ;relative to 0
259 mov e,a
260 mvi c,logdsk
261 call bdos ;back to "logged in" disk
262 jmp kermit ;...and return to kermit.
263
264 ;
265 ;Determines free space remaining
266 ;
267 dir17: xra a
268 sta mfflg1 ;clean up MFNAME
269 sta mfflg2
270 lda fcb ; get drive number from FCB
271 ora a
272 jz dir18 ; default?
273 dcr a ; no, make requested drive current drive.
274 mov e,a
275 mvi c,logdsk
276 call bdos
277 dir18: call sysspc ; get space available for current drive
278 push h
279 lxi d,inms15 ;"Drive "
280 call prtstr
281 lda fcb ;If no drive, get
282 ora a ;logged in drive
283 jnz dir24
284 mvi c,rddrv
285 call bdos
286 inr a
287 dir24: adi 'A'-1
288 sta inms16
289 lxi d,inms16 ;"x has "
290 call prtstr
291 pop h ;Get number of bytes available
292 call nout
293 lxi d,inms17 ;"K bytes free"
294 call prtstr
295 jmp dir16 ;all done
296
297 ;Compute the size of the file
298
299 dir25: lda hidefs ; do we show file size?
300 ana a ; if non zero, we dont.
301 rz ; so just return
302 mvi c,cflsz ;get file-size
303 lxi d,fcb
304 call bdos
305 lda fcbrno ;shift least sign. part
306 lxi b,0 ;init bc
307 mov l,a
308 ani 7
309 jz dir250 ;even K
310 lxi b,1 ;save for later
311 dir250: push b ;save 0 or 1 to add to size
312 mvi b,3 ;shift 3 bits
313 dir25a: xra a ;clear sign
314 lda fcbrno+1 ;get most sig byte
315 rar ;shift right
316 sta fcbrno+1 ;put back
317 lda fcbrno ;get least sig part
318 rar
319 sta fcbrno
320 dcr b ;loop 3 times
321 jnz dir25a
322 mov l,a ;size in HL
323 lda fcbrno+1
324 mov h,a
325 pop b ;get 0 or 1
326 dad b ;round up to KB used
327 lda bmask ;get (sectors/block)-1
328 rrc
329 rrc ;get (K/block)-1
330 rrc
331 ani 1FH
332 mov c,a
333 dad b ;add (K/block)-1 to size to round up
334 cma ;make a mask
335 ana l ;truncate after rounding up
336 mov l,a
337 push h
338 lxi b,-10 ;subtract 10
339 dad b
340 jc dir25d ;>= 10
341 call dir8 ; print a leading space
342 jmp dir25e
343
344 dir25d: pop h ;get size again
345 push h
346 lxi b,-100 ;subtract 100
347 dad b
348 jc dir25e ;>= 100
349 call dir9 ; print another leading space
350 dir25e: call dir9 ;a space
351 pop h ;get size back
352 call nout ;..go print it
353 mvi a,'k' ;..and follow with K size
354 call dir10
355 ret
356
357 dir26: mvi c,gtdpar ;current DISK PARAMETER BLOCK
358 call bdos
359 inx h
360 inx h
361 mov a,m ;Get Block Shift Factor
362 sta bshiftf
363 inx h ;Bump to Block Mask
364 mov a,m ;get it
365 sta bmask
366 inx h
367 inx h
368 mov e,m ;Get Max Block number
369 inx h
370 mov d,m
371 xchg
372 shld bmax ;Put it away
373 ret
374 ;\f
375 ; ERA command - erase a CP/M file
376 ; here from: kermit
377
378 era: mvi a,cmifi ;Parse a file-spec
379 lxi d,fcb ;into FCB
380 call comnd
381 jmp kermit ;bad parse
382 mvi a,cmcfm ;[MF]Get a confirm from the user
383 call comnd ;[MF]...
384 jmp kermit ;[MF]NO? try another command
385 lxi d,fcb
386 mvi c,sfirst ;check if valid
387 call bdos
388 inr a ;0 if FILE not found
389 jnz era1 ;found at least one
390 lxi d,erms15 ;"unable to find file"
391 call prtstr
392 jmp kermit
393
394 era1: lxi d,fcb
395 mvi c,delf
396 call bdos
397 lxi d,inms18 ;" File(s) erased"
398 call prtstr
399 jmp kermit
400
401 ; USER - select a new user. This is an unusual routine in that the user
402 ; enters a number. The others take on/off or filename (except
403 ; set escape
404 ;
405 user: mvi a,cmnum ; go parse a number
406 call comnd
407 jmp kermit ; if we can not do it, quit to command loop
408 mvi a,cmcfm ; get a confirm from the user
409 call comnd
410 jmp kermit ; if no, then try another command
411 lhld number ; else get the number...
412 xchg ; until a non valid digit is typed (eg cr)
413 lxi h,-32 ; if a carry, then ok
414 dad d ; ... else its above 32
415 jc user1
416 xchg ; restor number in hl again
417 mov a,l ; Lets save it
418 sta curusr ; as current user number
419 mov e,l ; get user no to e...
420 mvi c,usrcod
421 call bdos
422 call getun ; get user number to temp1 and temp2
423 lda temp2
424 cpi '0'
425 jnz user0 ; dont do ms digit if a zero
426 mvi a,' '
427 user0: sta kerm1 ; save into string etc
428 sta dnam14 ; also for dir command
429 lda temp1
430 sta kerm1+1
431 sta dnam14+1 ; also for dir command
432 jmp kermit
433
434 user1: lxi d,erms23 ; tell user sorry
435 call prtstr
436 jmp kermit
437
438
439 ;
440 ; TYPE - type a file or files to the console.
441 ;
442 ; This utility also used by print, where the characters printed to
443 ; the console are also copied to the printer if the prnfl flag
444 ; is non-zero. Uses mfname to type (print) multiple names.
445 ; Each file is preceeded with a formfeed character (usually clears
446 ; the screen on a VDU)
447 ;
448
449 type: mvi a,cmifi ; parse a file name
450 lxi d,fcb ; let the parser know where the FCB is
451 call comnd
452 jmp type02 ; if error say so
453
454 type0b:
455 xra a ; clear some flags for mfname
456 sta mfflg1
457 sta mfflg2
458 sta mfflg3
459 sta fcbcnt ;[12]...
460 lxi h,fcb0 ; reset the fcb pointers etc
461 shld fcbptr
462 call mfname
463 jc type02 ; match not found
464
465 ;[MF][10]The following code to type a file using a 1-sector buffer has
466 ;[MF][10]been replaced by code to use the "big buffer" -- 30-Jan-1991
467 ;type1: lxi d,buff ; point to the default DMA address
468 ; mvi c,setdma
469 ; call bdos ; tell bdos where to put the dma address
470 ; mvi a,ff ; do a form feed
471 ; call typit
472 ; xra a ; clear the character count
473 ; sta chrcnt
474 ;
475 ;type2: mvi c,openf ; open the file for reading
476 ; lxi d,fcb
477 ; xra a ; but first clear bits of fcb...
478 ; sta fcb+12
479 ; sta fcb+14
480 ; sta fcb+15
481 ; sta fcb+32
482 ; call bdos ; NOW open the file
483 ;
484 ;type20: mvi c,readf ; open up the file and read first sector
485 ; lxi d,fcb
486 ; call bdos
487 ;;[MF][9]Correct EOF test below (next two instructions)
488 ;; inr a ; if 0ffh returned, error. Assume EOF
489 ;; jz typex ; so exit from here
490 ; ora a ;[MF][9]If error, assume EOF
491 ; jnz typex ;[MF][9]so exit
492 ; lxi h,0 ; else clear the pointer into the file
493 ; shld typptr
494 ;
495 ;
496 ;type2a: lxi d,buff ;ok, so lets get the byte to print
497 ; lhld typptr
498 ; dad d ; add offset to the DMA base
499 ; mov a,m ; and get character to type (print)
500 ; ani 7fh ; make sure it is printable
501 ; cpi 20h ; is it a control character?
502 ; jp type3
503 ; cpi 09h ; if its a tab, then expand it
504 ; jnz type2b
505 ;
506 ;type2c: mvi a,' ' ; send a space
507 ; call typit ; type it
508 ; lda chrcnt ; get the number of chrs so far
509 ; ani 7h ; see of an 8th pos?
510 ; jnz type2c ; loop until all spaces done, then exit
511 ; jmp type4
512 ;
513 ;type2b: cpi cr ; is it a cr or lf?
514 ; jnz type2d
515 ; call typit ; do a cr
516 ; xra a
517 ; sta chrcnt ; cr of lf => clear character count
518 ; jmp type4 ; and exit
519 ;
520 ;type2d: cpi lf
521 ; jnz type2e
522 ; call typit ; print the character
523 ; xra a
524 ; sta chrcnt ; cr or lf clears the character count
525 ; jmp type4
526 ;
527 ;type2e: cpi cntlz ; is it end of file?
528 ; jnz type2f
529 ; jmp typex ; yes, so close and try for another file
530 ;
531 ;type2f: push psw ; control char - save the character
532 ; mvi a,'^' ; send control chars as ^A, for ex.
533 ; call typit
534 ; pop psw
535 ;
536 ;type3: call typit
537 ;
538 ;
539 ;type4: lhld typptr ; get the pointer
540 ; inx h
541 ; shld typptr ; up it by one character, and save it.
542 ; mov a,l ; lets see if the sector has been typed
543 ; ana a
544 ; jm type20 ; if 80h => read new sector
545 ; jmp type2a ; else just continue along
546
547 ;[MF][10]The following code uses the "big buffer" to read the file
548 ;[MF][10]which is to be typed
549 ;[12]Clear the screen explicitly as some terminals don't respond
550 ;[12]to the <ff> character.
551 ;type1: mvi a,ff ; do a form feed
552 ; call typit
553 type1: call clrtop ;[12] Clear the screen
554 xra a ; clear the character count
555 sta temp1 ;[MF]alias column counter
556
557 type2:
558 ;[12]Eliminate call to openf in favor of call to "getfil"
559 ; mvi c,openf ; open the file for reading
560 lxi d,fcb
561 ; xra a ; but first clear bits of fcb...
562 ; sta fcb+12
563 ; sta fcb+14
564 ; sta fcb+15
565 ; sta fcb+32
566 ; call bdos ; NOW open the file
567 call getfil ;[12] NOW open the file
568
569 type20: call inbuf ;[MF]Fill input buffers
570 jmp typex ;[MF]Tru end-of-file reached
571 jmp type21 ;[MF]Begin typing/printing characters
572
573 type2a: lda chrcnt ;[MF]Get buffer character counter
574 dcr a ;[MF]and decrement it
575 jm type20 ;[MF]Get more characters if needed
576 type21: sta chrcnt ;[MF]else remember new buffer character counter
577 lhld bufpnt ;[MF]Now get character pointer
578 mov a,m ; and get character to type (print)
579 inx h ;[MF]Increment the pointer
580 shld bufpnt ;[MF]and remember it
581 ani 7fh ; make sure character is printable
582 cpi 20h ; is it a control character?
583 jp type3
584 cpi 09h ; if its a tab, then expand it
585 jnz type2b
586
587 type2c: mvi a,' ' ; send a space
588 call typit ; type it
589 lda temp1 ;[MF]Get the number of characters so far
590 ani 7h ; see if an 8th pos?
591 jnz type2c ; loop until all spaces done, then exit
592 jmp type2a ;[MF]and continue
593
594 type2b: cpi cr ; is it a cr or lf?
595 jnz type2d
596 call typit ; do a cr
597 xra a
598 sta temp1 ; cr or lf => clear character count
599 jmp type2a ;[MF]and continue
600
601 type2d: cpi lf
602 jnz type2e
603 call typit ; print the character
604 xra a
605 sta temp1 ; cr or lf clears the character count
606 jmp type2a ;[MF]and continue
607
608 type2e: cpi cntlz ; is it end of file?
609 jnz type2f
610 jmp typex ; yes, so close and try for another file
611
612 type2f: push psw ; control char - save the character
613 mvi a,'^' ; send control chars as ^A, for ex.
614 call typit
615 pop psw
616
617 type3: call typit
618 jmp type2a ; and continue along
619
620 typex: mvi c,closf
621 lxi d,fcb
622 call bdos ; close the file
623 mvi a,cr ; send cr lf to screen/printer to clear buffers
624 call typit
625 mvi a,lf
626 call typit
627 call mfname ; and see if there are other files to type
628 jnc type1 ; yup, so go do it
629 xra a ; make sure the flag is reset
630 sta prnfl
631 jmp kermit ; then exit.
632
633 typex0: mvi c,closf ;[MF]Close the file
634 lxi d,fcb ;[MF]...
635 call bdos ;[MF]...
636 mvi a,cr ;[MF]Clear buffers
637 call typit ;[MF]...
638 mvi a,lf ;[MF]...
639 call typit ;[MF]...
640 xra a ;[MF]Clear flag
641 sta prnfl ;[MF]...
642 lda takflg ;[MF]See if we're TAKEing commands
643 ani 1 ;[MF]from a file
644 cnz closet ;[MF]If we are, abort TAKE-file processing
645 jmp kermit ;[MF]Back to Kermit command-level
646
647 ; error for file not found for type
648 type02: lxi d,nofile ; say no file name (its invalid)
649 call prtstr
650 xra a
651 sta prnfl ; clear the flag
652 jmp kermit ; so abort
653
654
655 typit: mov e,a
656 call ckqtyp ; see if a cntl-c or other character from user
657 jmp typit2 ;[MF] Control-C entered, abort
658 jc typit1 ; CNTL-X entered, so abort file [MF]
659 push d ; save for a bit
660 call outcon ; send it to the console
661 lda temp1 ; update the number of characters sent[MF]
662 inr a
663 sta temp1 ;[MF]
664 pop d
665 lda prnfl ; see if we have to print it too
666 ana a
667 rz
668 call outprn ; send character to printer (buffer)
669 ret
670
671 typit1: pop d ; adjust stack again
672 jmp typex ; and say we are done (for this file)
673
674 typit2: pop d ;[MF] Adjust the stack
675 jmp typex0 ;[MF] and abort file typeout completely
676
677
678 ; CKQTYP - CHeck for requested Quiet TYPe (ie hang on a second)
679 ; Routine sees if the user has typed ANY key. If a key HAS been pressed
680 ; see if its a Control-c. If so, flag for an abort, else wait for
681 ; a second entry from the user. If its a Control C, flag an abort
682 ; else continue with the print.
683 ; note: only the DE registers maintained. All others destroyed.
684 ; **NOTE** CKQTYP now gives a nonskip return if Control-C is typed,
685 ; a skip-return with carry set if a Control-X is typed and a skip-return
686 ; with carry clear if any other character is typed as the second
687 ; character.
688
689 ckqtyp: push d ; save the character to be printed
690 call ckchr ; see if user entered a character
691 ani 7fh ; strip parity etc
692 jz ckqty3 ; nothing entered, so go on as usual (See below)
693 cpi ctrlc ; control c?
694 jz ckqt1a ;[MF] Yup, give nonskip return
695 cpi 'X'-100o ;[MF] If Control-X,
696 jz ckqty1 ; yup, set carry and exit
697 ckqty2: call ckchr ; another character to wait for (ie pause)
698 ani 7fh
699 jz ckqty2 ; wait until some input
700 cpi ctrlc ; if control c, abort
701 jz ckqt1a ;[MF] ...
702 cpi 'X'-100o ;[MF] Control-X?
703 jz ckqty1 ; yuss, so flag abort file [MF]
704 ckqty3: pop d ; else restore the character to be typed [MF]
705 ; ret ; no, so continue with type/print
706 stc ;[MF]Set carry
707 cmc ;[MF]Then clear it
708 jmp rskp ;[MF] Continue with type/print (skip ret)
709
710 ckqty1: pop d ; restore stack again
711 stc ; set carry and return
712 ; ret
713 jmp rskp ;[MF] ...
714
715 ckqt1a: pop d ;[MF] Adjust stack
716 ret ;[MF] and return
717
718 ;[MF][14]No longer need these lines
719 ;ckqty3: pop d ; restore stack again
720 ;; ret
721 ; stc ;[MF] Clear carry
722 ; cmc ;[MF] ...
723 ; jmp rskp ;[MF] and give skip return
724
725 ckchr: call selcon ; make sure we are talking to the console
726 mvi e,0ffh ; see if user has any input for us
727 mvi c,dconio
728 ; call bdos ;[11]Don't go thru bdos trap
729 call 0005h ;[11]Call bdos directly
730 ret ; This routine does not care what comes back
731
732
733 ;
734 ; COPY - routine to copy from a source file to a destination file
735 ; from the Kermit command state.
736 ;
737 ; Note. This could be tricky, as there are several forms of copy
738 ; copy d:source.ext d:dest.ext (Easy one)
739 ; copy d:source.ext d: (File to another drive)
740 ; copy d:source.??? d: (several files)
741 ; copy d:*.* d: (Several files)
742 ;
743 ; Initially, lets make it top one, and see how we go, ok?
744 ;
745 ;
746 ;Things to do for copy:
747 ; 1) get source name
748 ; 2) get target name
749 ; 3) if both source and destination = abort
750 ; 4) if source does not exist abort
751 ; 5) attempt to delete destination file if it exists
752 ; 6) open source and destination files
753 ; 7) copy file across
754 ; 8) close all files
755 ; 9) return to command mode
756 ;
757 copy: ; Here goes...
758 ; 1) get source file name
759 mvi a,cmofi ; go parse a file name
760 ;[MF]Nonwild
761 lxi d,cfcbs ; use the source for copy FCB (Allows copy
762 call comnd ; from a TAKE file etc)
763 jmp kermit ; if error, abort
764
765 ; 2) get target name
766 mvi a,cmofi ; go parse a target file name
767 ;[MF]Again, nonwild
768 lxi d,cfcbd ; use destination fcb
769 call comnd ; get it
770 jmp kermit ;[MF]Couldn't.
771 mvi a,cmcfm ;[MF]Get a confirm from the user
772 call comnd ;[MF]...
773 jmp kermit ;[MF]No? try another command
774
775 ; 3) see if both target and source are equal
776 copy0: mvi b,12 ; we are gonna test drive, file and extention
777 lxi d,cfcbs ; from source file name...
778 lxi h,cfcbd ; to destination file name
779 xra a ; clear flag for difference found
780 sta equflg
781 copy1: ldax d ; get source file name character
782 cmp m ; test with targer file name
783 jz copy2 ; if equal, do nothing
784 lda equflg ; else update flage (ie files are different)
785 inr a
786 sta equflg
787 copy2: inx h
788 inx d
789 dcr b
790 jnz copy1 ; up pointers and test for next char
791
792 lda equflg ; if still null, then its a daft thing to do
793 ana a
794 jnz copy3 ; its not a daft thing to do
795 lxi d,samems ; load up "File source and destination the same"
796 call prtstr ; tell user
797 jmp kermit ; and try again
798
799 ; 4) If source does not exist, abort. Assume we have a full file name.
800 copy3:
801 lxi d,cfcbs ; load up source fcb
802 mvi c,openf ; open file
803 call bdos
804 inr a ; error on open?
805 jnz copy4
806 lxi d,nofile ; assume file not found
807 call prtstr
808 jmp kermit ; and die
809
810 copy4: lxi d,cfcbd ; load up destination fcb
811 mvi c,delf ; destroy target name if it exists
812 call bdos ; ignore error messages
813 lxi d,cfcbd ; load up destination fcb
814 mvi c,makef ; make a file
815 call bdos
816 inr a ; make error?
817 jnz copy4a
818 lxi d,erms12 ; no directory space
819 call prtstr
820 jmp copy7 ; close source file
821
822 copy4a: lxi d,cfcbd ; load up destination fcb...
823 mvi c,openf ; for open
824 call bdos
825 inr a ; error on open?
826 jnz copy5 ; could do with better error detection...
827 lxi d,erms15 ;... but assume its a disk full
828 call prtstr
829 jmp copy7 ; close source file and jmp kermit
830
831 ;copy5: lxi d,buff ; set default dma address to 80h
832 ; mvi c,setdma
833 ; call bdos
834 ;
835 ;copy6: lxi d,cfcbs ; copy routine proper.. get a sector
836 ; mvi c,readf
837 ; call bdos
838 ; ana a ; error reading the file?
839 ; jnz copy8 ; yes, then cope with it (could be EOF)
840 ; [MaJoC 910128] The above code, which reads single logical sectors,
841 ; is grossly inefficient with systems (most of them) with larger physical
842 ; disk blocks and a single shared read/write buffer. Use of INBUF below
843 ; is functionally equivalent at this level, but does actual disk reads
844 ; by the Big Buffer-ful.
845 copy5:
846 xra a ; Initialise INBUF, to force reading of
847 sta seccnt ; the first Big Buffer-ful. Redundant
848 sta endsts ; if file opened by GETFIL (or variant).
849 sta eoflag ;[MF]...
850 lxi h,cfcbs ;[MF]Copy source fcb to default fcb
851 lxi d,fcb ;[MF]since INBUF uses the default fcb
852 lxi b,33 ;[MF]...
853 call mover ;[MF]...
854 copy6:
855 ; INBUF returns a pointer to the next logical bufferful via bufpnt, filling
856 ; the Big Buffer as necessary, with skip return for success and nonskip on
857 ; error or EOF.
858 call inbuf ; Start of copy proper: get bufferful.
859 jmp copy8 ; Nonskip return: treat as EOF.
860 lhld bufpnt ; Skip return => OK: pick up buffer pointer.
861 xchg
862 mvi c, setdma ; Tell system where to write from.
863 call bdos
864 ; [majoc 910128: end]
865 lxi d,cfcbd ; send sector to destination
866 mvi c,writef
867 call bdos
868 ana a ; error on write (disk full?)
869 jz copy6 ; no error, so do another sector.
870 lxi d,erms17 ; say disk is full
871 call prtstr
872 lxi d,cfcbd ; close the output file...
873 mvi c,closf
874 call bdos
875 lxi d,cfcbd ; ... and then delete it
876 mvi c,delf
877 call bdos ; ... and then drop through to...
878
879 copy7: lxi d,cfcbs ; here to close the source FCB
880 mvi c,closf
881 call bdos
882 jmp kermit
883
884 copy8: lxi d,cfcbd ; orderly close of destination file
885 mvi c,closf
886 call bdos
887 jmp copy7 ; now close the source file as well.
888
889 ;
890 ;[MF]RENAME - Rename a file
891 ;
892 rename: mvi a,cmofi ;[MF]Get nonwild filename
893 lxi d,cfcbs ;[MF]Use "COPY" fcb's
894 call comnd ;[MF]...
895 jmp kermit ;[MF]Couldn't get it.
896 mvi a,cmofi ;[MF]Get filespec to rename it to
897 lxi d,cfcbd ;[MF]...
898 call comnd ;[MF]...
899 jmp kermit ;[MF]Couldn't.
900 renam0: lxi d,cfcbs ;[MF]See if file to be renamed exists
901 mvi c,openf ;[MF]by trying to open it
902 call bdos ;[MF]...
903 inr a ;[MF]Does the file exist?
904 jnz renam1 ;[MF]Yes
905 lxi d,nofile ;[MF]No, inform the user
906 call prtstr ;[MF]...
907 jmp kermit ;[MF]and bomb
908 renam1: lxi d,cfcbd ;[MF]Point to rename filespec
909 mvi c,openf ;[MF]Set function code to
910 call bdos ;[MF]See if rename file exists
911 inr a ;[MF]Does it?
912 jz renam2 ;[MF]No
913 lxi d,erms31 ;[MF]Yes, complain
914 call prtstr ;[MF]...
915 jmp kermit ;[MF]and depart with tail between legs
916 renam2: lxi h,cfcbd ;[MF]Now get rename filespec again
917 lxi d,cfcbs+16 ;[MF]and where to copy it to
918 lxi b,16 ;[MF]We copy drive, filename, filetype, extent
919 call mover ;[MF]...
920 lxi d,cfcbs ;[MF]Point to fcb for rename
921 mvi c,renam ;[MF]Get rename function
922 call bdos ;[MF]Try to rename the file
923 inr a ;[MF]Did we succeed?
924 jnz kermit ;[MF]Yes, done
925 lxi d,erms16 ;[MF]No, complain
926 call prtstr ;[MF]...
927 jmp kermit ;[MF]and start over
928
929
930 IF lasm
931 LINK CPSWLD
932 ENDIF;lasm [Toad Hall]