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