home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / cpm86 / c86utl.a86 < prev    next >
Text File  |  2020-01-01  |  21KB  |  965 lines

  1. ;* * * * * * * * * * * * * * * version 2.9 * * * * * * * * * * * * * * *
  2. ; [34c]    Make DMA initialization and buffer allocation global
  3. ; [34b]    Add LOCAL TYPE command
  4. ; [34a]    Fix bugs in directory listing file sizes
  5. ;* * * * * * * * * * * * * * * version 2.8 * * * * * * * * * * * * * * *
  6. ; [32d]    Add routines to get disk parameters for space calculation
  7. ; [32a]    Add routines to get and set default disk and user numbers
  8. ;* * * * * * * * * * * * * * * version 2.7 * * * * * * * * * * * * * * *
  9. ; [29c]  Clear FCB prior to opening or creating a file.
  10. ; [29b]  Add TAKE command file processing.
  11. ;    RonB, 04/08/84
  12. ;* * * * * * * * * * * * * * * version 2.6 * * * * * * * * * * * * * * *
  13. ;  [24a] Add terminal session logging
  14. ;    RonB, 03/15/84
  15. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  16. ;  [20e] Add regular console status check, in addition to direct I/O check.
  17. ;    RonB,03/02/84
  18. ;  [19c] Give "bdos" mnemonic for vector 224.
  19. ; * * * * * * * * * * * * * * *  version 2.1  * * * * * * * * * * * * * * *
  20. ;  [7]    Do tab expansion and suppress nulls while in telnet mode.
  21. ;    RonB,12/24/83
  22. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  23.  
  24. ; BDOS command codes
  25.  
  26. bdos    equ    224
  27. reset    EQU    00H
  28. conin    EQU    01H
  29. conout    EQU    02H
  30. rdrin    EQU    03H
  31. punout    EQU    04H
  32. lstout    EQU    05H
  33. dconio    EQU    06H
  34. gtiob    EQU    07H
  35. prstr    EQU    09H
  36. consta    EQU    0BH
  37. resetd    EQU    0DH                        ;[32a]
  38. stdrv    EQU    0EH                        ;[32a]
  39. opnfil    EQU    0FH
  40. clsfil    EQU    10H
  41. sfirst    EQU    11H
  42. snext    EQU    12H
  43. delf    EQU    13H
  44. readf    EQU    14H
  45. writef    EQU    15H
  46. makef    EQU    16H
  47. gtdrv    EQU    19H                        ;[32a]
  48. gtalv    EQU    1BH                        ;[32d]
  49. gtrov    EQU    1DH                        ;[32d]
  50. statr    EQU    1EH
  51. gtdpb    EQU    1FH                        ;[32d]
  52. stusr    EQU    20H                        ;[32a]
  53. readr    EQU    21H
  54. writer    EQU    22H
  55. cflsz    EQU    23H
  56. dmaset    EQU    1AH
  57. dmabas    EQU    33H
  58. allocm    EQU    37H                        ;[32d]
  59. freem    EQU    39H                        ;[32d]
  60.  
  61.     DSEG $                        ;[29b] begin
  62.  
  63. ; TAKE command file processing data area.
  64.  
  65. tkfcb    db    0,'KERMIT  INI',0,0,0,0        ;FCB with default name
  66.     rb    19
  67. tkbuf    rb    80h                ;Input buffer
  68. tkptr    dw    0                ;Buffer pointer
  69. tkflg    db    1                ;Initially enable file input
  70.  
  71. ; Messages and storage for directory operations
  72.  
  73. dirm01    db    'Drive $'                    ;[32d] begin
  74. dirm02    db    ', User $'
  75. dirm03    db    '    K$'
  76. dirm04    db    ' : $'        ;directory column separator
  77. dirm05    db    ' files, $'
  78. dirm06    db    'K listed$'
  79. dirm07    db    '  $'        ;displayed at start of each row
  80. eram01    db    tab,'Delete? $'
  81. eram02    db    tab,'...not deleted$'
  82. eram03    db    tab,'...deleted$'
  83. eram04    db    ' $'        ;displayed at start of each row
  84. erahlp    db    cr,lf,'Respond with ''Y'' to delete this file,'
  85.     db    cr,lf,'             ''N'' to bypass this file,'
  86.     db    cr,lf,'         or ''ESC'' to return to the Kermit-86> prompt.$'
  87. spcm01    db    'K (out of $'
  88. spcm02    db    'K) remaining on drive $'
  89. morm01    db    '--more--$'
  90. morm02    db    'Return: next line, Space: next page, ^X: next file, ^Z: quit$'
  91. membuf    rb    5        ;memory control block
  92. dirbuf    rb    16
  93. dindex    dw    0        ;index to first entry in row
  94. dlngth    dw    0        ;length of directory list
  95. dircnt    dw    0        ;files in directory list
  96. dirsiz    dw    0        ;kbytes in directory list
  97. remK    dw    0        ;Kbytes remaining on disk
  98. maxK    dw    0        ;Kbytes available if disk was empty
  99. DSM    dw    0        ;drive maximum allocation blocks
  100. KPB    dw    0        ;drive Kbytes Per Block        ;[32d] end
  101.  
  102.     CSEG $            ;Resume coding segment.
  103.  
  104. tkst:    cmp    tkptr, 0    ;Is file open yet?
  105.     jne    tkst1
  106.     call    tkopn
  107.      jmp    r        ;If open failure
  108. tkst1:    mov    bx, tkptr    ;Do we need a new record?
  109.     cmp    bx, offset tkbuf+80h
  110.     jb    tkst2
  111.     call    tkread
  112.     mov    bx, tkptr
  113. tkst2:    cmp    byte ptr [bx], 1Ah    ;Are we at end of file?
  114.     je    tkst3
  115.     jmp    rskp        ;If not, say we have a character.
  116. tkst3:    call    tkcls        ;  otherwise end the file
  117.     jmp    r
  118.  
  119. tkin:    call    tkst        ;If no file input,
  120.      jmp    bin        ;  get it from the console.
  121.     mov    bx, tkptr
  122.     mov    al, [bx]    ;Get character from command file record.
  123.     inc    tkptr
  124.     cmp    al, lf        ;Ignore <lf> in file
  125.     je    tkin
  126.     push    ax
  127.     mov    dl, al        ;Echo it to the display.
  128.     call    bout
  129.     pop    ax
  130.     ret
  131.  
  132. tkopn:    mov    dx, offset tkfcb ;Open the command file
  133.     call    fcbzer        ;zero fcb trailer
  134.     mov    cl, opnfil
  135.     int    bdos
  136.     inc    al
  137.     jz    tkopn1
  138.     mov    tkptr, offset tkbuf+80h ;If success, show we need a read
  139.     jmp    rskp
  140. tkopn1:    mov    tkflg, 0    ;On failure, turn off file input flag.
  141.     ret
  142.  
  143. tkread:    mov    dx, offset tkbuf ;Set dma to our location.
  144.     call    setdma
  145.     mov    dx, offset tkfcb
  146.     call    sinr        ;Read a record.
  147.     cmp    al, 0
  148.     je    tkrd1
  149.     mov    tkbuf, 1Ah    ;If failure, load buffer with EOF.
  150. tkrd1:    mov    tkptr, offset tkbuf    ;Reinitialize buffer pointer.
  151.     call    inidma        ;Reset dma to normal.
  152.     ret
  153.  
  154. tkcls:    mov    dx, offset tkfcb ;Close command file.
  155.     call    closf
  156.     mov    tkflg, 0    ;Turn off file input flag.
  157.     ret                            ;[29b] end
  158.  
  159.  
  160. ; Local directory operation
  161.  
  162. dirutl:    call    getwld        ;fill buffer with matching names
  163.      jmp    r        ;on failure a message has already been printed
  164.     cmp    dircnt,0
  165.     jne    locd3
  166.      ret
  167. locd3:    mov    dirsiz,0
  168.     mov    ax,dircnt
  169.     dec    ax        ;calculate number of entries in each column
  170.     shr    ax,1        ; = ((count-1)/4)+1
  171.     shr    ax,1
  172.     inc    ax
  173.     mov    dlngth,ax
  174.     call    tcrlf
  175.     mov    dx, offset dirm01 ;print header: Drive X, User nn:
  176.     call    tcrmsg
  177.     mov    dl,fcb        ;display the drive letter
  178.     add    dl,'A'-1
  179.     call    bout
  180.     mov    dx, offset dirm02
  181.     call    tmsg
  182.     mov    al,defusr    ;display the user number
  183.     cbw
  184.     call    nout
  185.     mov    dl,':'
  186.     call    bout
  187.     mov    dindex,0    ;table entry in first column
  188.     mov    cx,dlngth
  189. locd4a:    push    cx
  190.     mov    dx, offset dirm07 ;Start new row
  191.     call    tcrmsg
  192.     mov    si,dindex
  193.     mov    cx,4
  194. locd4b:    push    si
  195.     push    cx
  196.     push    ds
  197.     mov    ds,word ptr membuf
  198.     mov    cl,4        ;change entry number to table offset
  199.     shl    si,cl
  200.     inc    si        ;skip user number
  201.     mov    cx,8        ;Eight characters in filename
  202. locd5b:    lodsb            ;get a filename character
  203.     mov    dl,al
  204.     push    cx
  205.     call    bout        ;print it
  206.     pop    cx
  207.     loop    locd5b
  208.     mov    dl,'.'        ;separate filename and type with a period
  209.     call    bout
  210.     mov    cx,3        ;Three characters in file type
  211. locd5c:    lodsb            ;get a file type character
  212.     mov    dl,al
  213.     push    cx
  214.     call    bout        ;print it
  215.     pop    cx
  216.     loop    locd5c
  217.     lodsw            ;get file size
  218.     pop    ds
  219.     add    dirsiz,ax    ;add filesize to listing size
  220.     mov    di, offset dirm03 ;message for file size (____K)
  221.     mov    cx,3
  222. locd5d:    mov    byte ptr [di],' ' ;first blank out the last size
  223.     inc    di
  224.     loop    locd5d
  225.     mov    bx,10
  226. locd5e:    mov    dx,0        ;fill in current size
  227.     div    bx
  228.     add    dl,'0'
  229.     mov    [di],dl
  230.     dec    di
  231.     cmp    ax,0
  232.     jne    locd5e
  233.     mov    dx, offset dirm03 ;print size message
  234.     call    tmsg
  235.     pop    cx
  236.     cmp    cx,1        ;follow all but last column with separator
  237.     je    locd5f
  238.     mov    dx, offset dirm04 ;print column separator
  239.     push    cx
  240.     call    tmsg
  241.     pop    cx
  242. locd5f:    pop    si
  243.     add    si,dlngth
  244.     cmp    si,dircnt
  245.     jae    locd6
  246.     loop    locd4b
  247. locd6:    inc    dindex
  248.     pop    cx
  249.     dec    cx
  250.     jz    locd8
  251.     jmp    locd4a
  252. locd8:    call    tcrlf        ;end the last row
  253.     call    tcrlf        ;add a blank row
  254.     mov    ax,dircnt    ;display file count
  255.     call    nout
  256.     mov    dx, offset dirm05
  257.     call    tmsg
  258.     mov    ax,dirsiz    ;display total file size
  259.     call    nout
  260.     mov    dx, offset dirm06
  261.     call    tmsg
  262.     jmp    rskp
  263.  
  264.  
  265. ; Erase utility function
  266.  
  267. erautl:    call    getwld
  268.      jmp    r        ;On error a message has already been printed
  269.     mov    dindex,0
  270. loce3:    mov    si,dindex
  271.     cmp    si,dircnt
  272.     jb    loce4
  273.     jmp    loce9
  274. loce4:    mov    cl,4
  275.     shl    si,cl
  276.     inc    si
  277.     mov    di, offset fcb+1    ;FCB already has drive code
  278.     push    ds
  279.     pop    es
  280.     mov    ds, word ptr membuf
  281.     mov    cx,15
  282.     rep    movsb
  283.     push    es
  284.     pop    ds
  285.     mov    dx, offset eram04    ;Start new row
  286.     call    tcrmsg
  287.     mov    dx, offset fcb
  288.     call    tfile
  289.     mov    dx, offset eram01    ;'<tab>Delete? '
  290.     call    tmsg
  291. loce5a:    call    dbinst            ;clear out all typeahead
  292.      jmp    loce5b
  293.     call    dbin
  294.     jmps    loce5a
  295. loce5b:    call    dbin            ;get response
  296.     cmp    al,0            ;NUL is ignored
  297.     je    loce5b
  298.     cmp    al,cr            ;CR bypasses file
  299.     je    loce5d
  300.     cmp    al,' '            ;any nonprintable char aborts
  301.     jb    loce8
  302.     cmp    al,7Fh
  303.     jae    loce8
  304.     push    ax
  305.     mov    dl,al            ;echo the printable response
  306.     call    bout
  307.     pop    ax
  308.     cmp    al,'?'            ;request for help?
  309.     jne    loce5c
  310.     mov    dx, offset erahlp    ;help message
  311.     call    tcmsgc
  312.     jmp    loce3
  313. loce5c:    or    al,'a'-'A'        ;convert to lower case
  314.     cmp    al,'y'
  315.     je    loce6
  316. loce5d:    mov    dx, offset eram02    ;'    ...not deleted'
  317.     call    tmsg
  318.     jmp    loce7
  319. loce6:    cmp    byte ptr fcb+14,0    ;make file read-write if necessary
  320.     je    loce6a
  321.     mov    dx, offset fcb
  322.     call    setatr
  323. loce6a:    mov    dx, offset fcb        ;delete file
  324.     call    delete
  325.     mov    dx, offset eram03     ;'    ...deleted'
  326.     call    tmsg
  327. loce7:    inc    dindex
  328.     jmp    loce3
  329. loce8:    mov    dx, offset eram02    ;'    ...not deleted' when aborting
  330.     call    tmsg
  331. loce9:    call    tcrlf
  332.     jmp    rskp
  333.  
  334.  
  335. ; Type utility function
  336.  
  337. typutl:    call    getwld
  338.      jmp    r        ;On error a message has already been printed
  339.     mov    dindex,0
  340. loct3:    mov    si,dindex        ;Get next filename in table
  341.     cmp    si,dircnt
  342.     jb    loct4
  343.     jmp    loct9
  344. loct4:    mov    dlngth,1
  345.     mov    cl,4
  346.     shl    si,cl
  347.     inc    si
  348.     mov    di, offset fcb+1
  349.     push    ds
  350.     pop    es
  351.     mov    ds, word ptr membuf
  352.     mov    cx,15
  353.     rep    movsb
  354.     push    es
  355.     pop    ds
  356.     call    tcrlf            ;Display the filename
  357.     mov    dx, offset fcb
  358.     call    tfile
  359.     call    tcrlf
  360.     mov    dx, offset fcb
  361.     call    openf            ;Open the file
  362.     inc    al
  363.     jnz    loct5
  364.     jmp    loct6b
  365. loct5:    mov    dx, offset fcb        ;Read a record
  366.     call    sinr
  367.     cmp    al,0
  368.     jne    loct6
  369.     mov    bx,offset dma
  370. loct5a:    mov    dl,[bx]            ;Get a character
  371.     cmp    dl,1Ah
  372.     je    loct6
  373.     and    dl,7Fh
  374.     push    bx
  375.     push    dx
  376.     call    bout            ;Print the character
  377.     pop    dx
  378.     cmp    dl,lf
  379.     jne    loct5b
  380.     inc    dlngth            ;Count lf characters
  381.     cmp    dlngth,22        ;If more than 22, then pause for input
  382.     jb    loct5b
  383.     call    more
  384.      jmp    loct5c
  385. loct5b:    pop    bx
  386.     inc    bx
  387.     cmp    bx,offset dma+128
  388.     jb    loct5a
  389.     jmps    loct5
  390. loct5c:    pop    bx
  391.     jmps    loct6a
  392. loct6:    mov    ax,dindex        ;EOF in file
  393.     inc    ax
  394.     cmp    ax,dircnt
  395.     jae    loct6a
  396.     call    tcrlf
  397.     call    more
  398.      jmp    loct6a
  399. loct6a:    mov    dx, offset fcb        ;Close file
  400.     call    closf
  401.     call    tcrlf
  402. loct6b:    inc    dindex            ;Move on to next file
  403.     jmp    loct3
  404. loct9:    jmp    rskp
  405.  
  406.  
  407. more:    call    revon
  408.     mov    dx,offset morm01    ;Show --more-- message
  409.     call    tmsg
  410.     call    revoff
  411. more1:    call    dbin            ;Get response
  412.     cmp    al,0            ; ignore nulls
  413.     je    more1
  414.     push    ax
  415.     call    clrlin
  416.     mov    dl,tab            ;This is to fool CP/M so it
  417.     call    bout            ;  gets tab stops right
  418.     mov    dl,cr
  419.     call    bout
  420.     pop    ax
  421.     and    al,7Fh
  422.     cmp    al,'?'            ;? gives help
  423.     jne    more2
  424.     call    revon
  425.     mov    dx,offset morm02    ;Show help message
  426.     call    tmsg
  427.     call    revoff
  428.     jmps    more1
  429. more2:    cmp    al,cr            ;cr, lf go to next line
  430.     je    more4
  431.     cmp    al,lf
  432.     je    more4
  433.     mov    dlngth,0        ;Everything else resets line count
  434.     cmp    al,0Fh            ;^O, ^X go to next file
  435.     je    more6
  436.     cmp    al,18h
  437.     je    more6
  438.     cmp    al,03h            ;^C, ^Z, q quit
  439.     je    more5
  440.     cmp    al,1Ah
  441.     je    more5
  442.     or    al,'a'-'A'
  443.     cmp    al,'q'
  444.     je    more5
  445. more4:    jmp    rskp            ;Next line, page
  446. more5:    mov    ax,dircnt        ;Quit
  447.     mov    dindex,ax
  448. more6:    ret                ;Next file
  449.  
  450.  
  451. ; Space remaining utility
  452.  
  453. spcutl:    call    getprm        ;Get the disk parameters for calculation
  454.     call    tcrlf
  455.     mov    ax,remK        ;Display the number of Kbytes remaining
  456.     call    nout
  457.     mov    dx, offset spcm01
  458.     call    tmsg
  459.     mov    ax,maxK        ;And the total number on the drive.
  460.     call    nout
  461.     mov    dx, offset spcm02
  462.     call    tmsg
  463.     mov    dl,fcb        ;Finally say which drive it is.
  464.     add    dl,'A'-1
  465.     call    bout
  466.     mov    dl,':'
  467.     call    bout
  468.     call    tcrlf
  469.     jmp    rskp
  470.  
  471.  
  472. ; get and save disk parameters which relate to block allocation and size
  473.  
  474. getprm:    mov    newdrv,0    ;initialize flag
  475.     mov    dl,fcb        ;specified drive must be the default
  476.     dec    dl        ; which is true if drive was not specified
  477.     jl    gprm2
  478.     cmp    dl,defdrv    ; or if specified drive matches the default
  479.     je    gprm2
  480.     mov    newdrv,0FFh    ;otherwise show that we changed default
  481.     push    dx
  482.     call    getrov        ;make sure the desired drive is write enabled
  483.     pop    dx        ; or else the data may be inaccurate
  484.     mov    cl,dl
  485.     mov    ax,1
  486.     shl    ax,cl
  487.     and    ax,bx
  488.     jz    gprm1
  489.     push    dx
  490.     call    rstdsk        ;if read-only, reset all drives
  491.     pop    dx
  492. gprm1:    call    setdrv        ;select the new drive as default
  493. gprm2:    push    es
  494.     call    getdpb        ;get address of DPB in ES:BX
  495.     mov    cl,es:2[bx]    ;get Block Shift Factor
  496.     sub    cl,3
  497.     mov    ax,1
  498.     shl    ax,cl
  499.     mov    KPB,ax        ;save Kbytes Per Block
  500.     mov    cx,es:5[bx]    ;get DSM maximum block number
  501.     mov    DSM,cx        ;save for file size and allocation calculation
  502.     inc    cx        ;number of blocks includes block 0
  503.     mul    cx
  504.     mov    maxK,ax        ;Maximum number of Kbytes
  505.     mov    remK,ax        ;Kbytes remaining
  506.     mov    ax,es:7[bx]    ;subtract directory allocation from maxK
  507.     mov    cl,5
  508.     shr    ax,cl
  509.     inc    ax
  510.     sub    maxK,ax
  511.     call    getalv        ;get address of allocation vector in ES:BX
  512.     mov    ax,DSM        ;compute length of vector = (DSM/8)+1
  513.     mov    cl,3
  514.     shr    ax,cl
  515.     inc    ax
  516.     mov    cx,ax
  517.     mov    ax,0        ;Count allocated blocks:
  518. gprm3:    mov    dl,es:[bx]    ;for each byte in vector,
  519.     inc    bx
  520.     push    cx
  521.     mov    cx,8        ;  for each bit in byte,
  522. gprm4:    test    dl,1
  523.     jz    gprm5
  524.     inc    ax        ;    if bit is set, then block is allocated
  525. gprm5:    shr    dl,1
  526.     loop    gprm4
  527.     pop    cx
  528.     loop    gprm3
  529.     mul    KPB        ;convert allocated blocks to Kbytes
  530.     sub    remK,ax        ;subtract allocated Kbytes from remK
  531.     pop    es
  532.     cmp    newdrv,0    ;reset default drive if we changed it
  533.     je    gprm6
  534.     mov    dl,defdrv
  535.     call    setdrv
  536. gprm6:    ret
  537.  
  538.  
  539. ; This subroutine fills the previously allocated memory buffer with a sorted
  540. ; list of filenames matching the wild name in fcb.  On failure, if there were
  541. ; no files, it prints an appropriate error message and simply returns.  On
  542. ; success, it returns to the skip location with the number of entries
  543. ; in the list in dircnt.  Each buffer entry is 16 bytes long and contains
  544. ; the user number at offset 0, the filename (with all attribute bits stripped)
  545. ; at offset 1-11, the allocated size in Kbytes at offset 12-13, and the
  546. ; read-only and system flags at offsets 14 and 15.
  547.  
  548. getwld:    mov    byte ptr fcb+12,'?' ;Match any extent
  549.     mov    byte ptr fcb+13,'?'
  550.     mov    byte ptr fcb+14,'?'
  551.     call    getprm        ;get disk parameters for size calculation
  552.     mov    dircnt,0    ;zero file count and total space occupied
  553.     mov    dx, offset fcb
  554.     call    gtjfn        ;get first filename
  555.     cmp    al,0FFh
  556.     jne    gwld2
  557.     mov    dx, offset erms15 ;unable to find file
  558.     call    tcrmsg
  559.     mov    dx, offset fcb
  560.     call    tfile
  561.      ret
  562. gwld2:    mov    cl,5        ;find file directory entry
  563.     shl    al,cl
  564.     mov    ah,0
  565.     mov    si, offset dma
  566.     add    si,ax        ;pointer to filename (incl. user number)
  567.     mov    di, offset dirbuf
  568.     push    ds
  569.     pop    es
  570.     mov    ax,9[si]    ;get read-only and system flags
  571.     and    ax,8080h    ;keep only attribute bits
  572.     mov    14[di],ax    ;save flags at end of buffer
  573.     mov    cx,12
  574. gwld2a:    lodsb
  575.     and    al,7Fh        ;get rid of all attribute bits
  576.     stosb
  577.     loop    gwld2a
  578.     add    si,4        ;look at allocation area
  579.     mov    ax,0        ;initialize block count
  580.     cmp    DSM,256        ;if <256 blocks, then each takes a byte
  581.     jb    gwld2c
  582.     mov    cx,8        ;8 blocks, one word each
  583. gwld2b:    cmp    word ptr [si],0
  584.     je    gwld2e
  585.     inc    si
  586.     inc    si
  587.     inc    ax
  588.     loop    gwld2b
  589.     jmps    gwld2e
  590. gwld2c:    mov    cx,16        ;16 blocks, one byte each
  591. gwld2d:    cmp    byte ptr [si],0
  592.     je    gwld2e
  593.     inc    si
  594.     inc    ax
  595.     loop    gwld2d
  596. gwld2e:    mul    KPB        ;convert blocks to kbytes
  597.     stosw            ;save this FCB's allocation
  598.     mov    ax,dircnt
  599.     cmp    ax,word ptr membuf+2 ;don't exceed buffer length
  600.     jb    gwld2f
  601.     mov    dx,offset erms27 ; if memory exceeded, print warning
  602.     call    tcmsgc        ;     and use what info we have
  603.     jmp    gwld4
  604. gwld2f:    mov    si, offset dirbuf ;go back to start of filename
  605.     mov    es,word ptr membuf ;find correct location in sorted file list
  606.     mov    di,0
  607.     mov    cx,dircnt    ;number of entries already in list
  608.     jcxz    gwld3e
  609. gwld3a:    push    cx
  610.     push    si
  611.     push    di
  612.     mov    cx,12
  613.     repe    cmpsb
  614.     jb    gwld3d        ;table entry greater than this file, insert
  615.     ja    gwld3c        ;table entry less than this file, keep looking
  616.     lodsw            ;else table entry same as file
  617.     add    es:[di],ax    ; ...add this FCB's allocation to size
  618. gwld3b:    pop    di
  619.     pop    si
  620.     pop    cx
  621.     jmp    gwld3f        ;go get next filename
  622. gwld3c:    pop    di        ;haven't found insert location yet
  623.     pop    si
  624.     pop    cx
  625.     add    di,16
  626.     loop    gwld3a
  627.     jmp    gwld3e        ;if greater than all entries, insert at end
  628. gwld3d:    pop    di        ;insertion point
  629.     pop    si        ;filename pointer
  630.     pop    ax        ;number of entries following insertion point
  631.     push    si
  632.     push    di
  633.     mov    cl,4        ;each entry occupies 16 bytes
  634.     shl    ax,cl
  635.     add    di,ax
  636.     dec    di
  637.     mov    si,di        ;point to last byte of table
  638.     add    di,16        ;move last part down 16 bytes
  639.     mov    cx,ax
  640.     push    ds        ;save filename segment
  641.     push    es        ;make all action in table segment
  642.     pop    ds
  643.     std            ;decrement pointers after each move
  644.     rep    movsb
  645.     cld
  646.     pop    ds        ;restore filename segment
  647.     pop    di        ;insertion point
  648.     pop    si        ;filename pointer
  649. gwld3e:    mov    cx,16        ;insert filename in table
  650.     rep    movsb
  651.     inc    dircnt        ;count new entry
  652. gwld3f:    mov    dx, offset fcb    ;look for another matching filename
  653.     call    gnjfn
  654.     cmp    al,0FFh
  655.     je    gwld4
  656.     jmp    gwld2        ;go process next filename
  657. gwld4:    push    ds
  658.     pop    es
  659.     jmp    rskp
  660.  
  661. ; General output utility routines
  662.  
  663. tmsgcr:    call    tmsg        ;Print the string
  664.     call    tcrlf        ;Print a CRLF.
  665.     ret
  666.  
  667. tcrmsg:    push    dx        ;Don't trash our string.
  668.     call    tcrlf        ;Print a CRLF.
  669.     pop    dx        ;Restore our string.
  670.     call    tmsg        ;Print the string
  671.     ret
  672.  
  673. tcmsgc:    push    dx        ;Don't trash our string.
  674.     call    tcrlf        ;Print a CRLF.
  675.     pop    dx        ;Restore our string.
  676.     call    tmsg        ;Print the string
  677.     call    tcrlf        ;Print a CRLF.
  678.     ret
  679.  
  680. tcrlf:    mov    dl,cr        ;print a crlf
  681.     call    bout
  682.     mov    dl,lf
  683.     call    bout
  684.     ret
  685.  
  686. tmsg:    push    bx        ;Don't clobber my ACs.
  687.     mov    cl, prstr    ;Ask BDOS for string printing.
  688.     int    bdos        ;What a way to call the BDOS.
  689.     pop    bx
  690.     ret
  691.  
  692. tfile:    mov    bx, dx        ;Print filename in [dx]'s FCB    ;[24a] begin
  693.     mov    dl, [bx]    ;If explicit drive number, display it.
  694.     cmp    dl, 0
  695.     je    tfil1
  696.     add    dl, 'A'-1
  697.     push    bx
  698.     call    bout
  699.     mov    dl, ':'
  700.     call    bout
  701.     pop    bx
  702. tfil1:    mov    cx, 11        ;Now display 11 chars of filename
  703. tfil2:    push    cx
  704.     cmp    cx, 3        ;With period before file type
  705.     jne    tfil3
  706.     push    bx
  707.     mov    dl, '.'
  708.     call    bout
  709.     pop    bx
  710. tfil3:    inc    bx
  711.     mov    dl, [bx]
  712.     cmp    dl, ' '        ;Don't include spaces
  713.     je    tfil4
  714.     push    bx
  715.     call    bout
  716.     pop    bx
  717. tfil4:    pop    cx
  718.     loop    tfil2
  719.     ret                            ;[24a] end
  720.  
  721.  
  722. bout:    mov    cl, conout    ;Ask BDOS for character printing.
  723.     int    bdos
  724.     ret
  725.  
  726. bin:    cmp    tkflg, 0    ;Check for command file input.    ;[29b] begin
  727.     je    bin1
  728.     jmp    tkin                        ;[29b] end
  729. bin1:    mov    cl, conin    ;Get a char from the console.
  730.     int    bdos
  731.     ret
  732.  
  733. binst:    cmp    tkflg, 0    ;Check for command file input.    ;[29b] begin
  734.     je    binst1
  735.     jmp    tkst                        ;[29b] end
  736. binst1:    mov    cl, consta    ;Console input status check    ;[20e] begin
  737.     int    bdos
  738.     or    al, al        ;Result 0 if no character ready
  739.     jz    bins2
  740.     jmp    rskp        ;Return SKIP if character ready
  741. bins2:    ret                            ;[20e] end
  742.  
  743. dbout:    cmp    dl, 0        ;Skip null fillers.
  744.     je    dbout3
  745.     call    logchr        ;Log the character if necessary ;[24a]
  746.     call    dotab        ;Do any necessary tab expansion.
  747.     jmp    r        ; No more chars to output.
  748. dbout2:    mov    cl, dconio    ;Put a char to the console.
  749.     int    bdos
  750. dbout3:    ret
  751.  
  752. dbin:    push    dx
  753.     mov    cl, dconio    ;Get a char from the console without
  754.     mov    dl, 0FFH    ; interference.
  755.     int    bdos
  756.     pop    dx
  757.     ret
  758.  
  759. dbinst:    push    dx
  760.     mov    cl, dconio    ;Check the console's input status.
  761.     mov    dl, 0FEH
  762.     int    bdos
  763.     pop    dx
  764.     or    al, al        ;Result 0 if no character ready ;[20e] begin
  765.     jz    dbins2
  766.     jmp    rskp        ;Return SKIP if character ready
  767. dbins2:    ret                            ;[20e] end
  768.  
  769. ;Log the terminal output character
  770.  
  771. logchr:    cmp    logfil, 0    ;Only log if file is open    ;[24a] begin
  772.     je    logch9
  773.     mov    bx, bufpnt    ;Store the character in the buffer.
  774.     mov    [bx], dl
  775.     inc    bx
  776.     cmp    bx, offset dma+80h    ;Have we filled a buffer?
  777.     jb    logch1
  778.     push    dx        ;If so, write it to file.
  779.     mov    dx, offset lfcb
  780.     call    soutr
  781.     pop    dx
  782.     mov    bx, offset dma
  783. logch1:    mov    bufpnt, bx
  784. logch9:    ret            ;Return to output routine    ;[24a] end
  785.  
  786. ;Halt this program.
  787.  
  788. haltf:    mov    cl, reset    ;End this program.
  789.     int    bdos
  790.     ret            ;One never knows!
  791.  
  792. ;Reset the disk system to log in drives                ;[32a] begin
  793.  
  794. rstdsk:    mov    cl,resetd
  795.     int    bdos
  796.     call    inidma        ;Concurrent CP/M also resets DMA address
  797.     ret
  798.  
  799. ;Get and set the default disk drive
  800.  
  801. getdrv:    mov    cl,gtdrv
  802.     int    bdos
  803.     ret            ;returns drive in al (A=0 through P=15)
  804.  
  805. setdrv:    mov    cl,stdrv    ;new drive number (A=0 through P=15) in dl
  806.     int    bdos
  807.     ret
  808.  
  809. ;Get and set the default user number
  810.  
  811. getusr:    mov    cl,stusr
  812.     mov    dl,0FFh
  813.     int    bdos
  814.     ret            ;returns user in al (0-15)
  815.  
  816. setusr:    mov    cl,stusr    ;new user number (0-15) in dl
  817.     int    bdos
  818.     ret                            ;[32a] end
  819.  
  820.  
  821. ; Get the address of the disk allocation vector            ;[32d] begin
  822.  
  823. getalv:    mov    cl,gtalv
  824.     int    bdos
  825.     ret
  826.  
  827. ; Get the disk read-only vector
  828.  
  829. getrov:    mov    cl,gtrov
  830.     int    bdos
  831.     ret
  832.  
  833. ; Set file attributes according to FCB in dx
  834.  
  835. setatr:    mov    cl,statr
  836.     int    bdos
  837.     ret
  838.  
  839. ; Get the address of the DPB
  840.  
  841. getdpb:    mov    cl,gtdpb
  842.     int    bdos
  843.     ret
  844.  
  845. ; Allocate a block of memory.  MCB address is in dx.
  846.  
  847. allmem:    mov    cl,allocm
  848.     int    bdos
  849.     ret
  850.  
  851. ; Free a previously allocated block of memory.  MCB address is in dx.
  852.  
  853. fremem:    mov    cl,freem
  854.     int    bdos
  855.     ret                            ;[32d] end
  856.  
  857.  
  858. ; Get the first file in a wild card search.
  859.  
  860. gtjfn:    mov    cl, sfirst
  861.     int    bdos
  862.     ret
  863.  
  864. ; Get the next file in a wild card search.
  865.  
  866. gnjfn:    mov    cl, snext
  867.     int    bdos
  868.     ret
  869.  
  870. ; Close the file pointed to by the FCB in DX.
  871.  
  872. closf:    mov    cl, clsfil
  873.     int    bdos
  874.     ret
  875.  
  876. ; Open the file pointed to by the FCB in DX.
  877.  
  878. openf:    call    fcbzer        ;clear the fcb trailer        ;[29c]
  879.     mov    cl, opnfil
  880.     int    bdos
  881.     ret
  882.  
  883. ; Create the file pointed to by the FCB in DX.
  884.  
  885. create:    call    fcbzer        ;clear the fcb trailer        ;[29c]
  886.     mov    cl, makef
  887.     int    bdos
  888.     ret
  889.  
  890. fcbzer:    push    bx        ;Clear the end of the FCB    ;[29c] begin
  891.     push    cx        ;  prior to opening or creating a file.
  892.     mov    bx, dx
  893.     add    bx, 12
  894.     mov    ch, 0
  895.     mov    cl, 23
  896. fcbz1:    mov    [bx], ch
  897.     inc    bx
  898.     loop    fcbz1
  899.     pop    cx
  900.     pop    bx
  901.     ret                            ;[29c] end
  902.  
  903. ; Write a record to the file pointed to by the FCB in DX.
  904.  
  905. soutr:    mov    cl, writef
  906.     int    bdos
  907.     ret
  908.  
  909. ; Read a record from the file pointed to by the FCB in DX.
  910.  
  911. sinr:    mov    cl, readf
  912.     int    bdos
  913.     ret
  914.  
  915. ; Delete the file pointed to by the FCB in DX.
  916.  
  917. delete:    mov    cl, delf
  918.     int    bdos
  919.     ret
  920.  
  921. ; Sets dma to the default buffer.  Functions that change this must call this
  922. ; function to reset it before continuing
  923.  
  924. inidma:    push    dx
  925.     mov    dx, offset dma
  926.     call    setdma
  927.     pop    dx
  928.     ret
  929.  
  930. ; Sets the DMA to the offset pointed to in DX and the base in DS.
  931.  
  932. setdma:    mov    cl, dmaset
  933.     int    bdos
  934.     mov    dx, ds
  935.     mov    cl, dmabas
  936.     int    bdos
  937.     ret
  938.  
  939. ; Do random access read, write, or file size checks, FCB is in dx
  940.  
  941. rinr:    mov    cl, readr
  942.     int    bdos
  943.     ret
  944.  
  945. routr:    mov    cl, writer
  946.     int    bdos
  947.     ret
  948.  
  949. sizef:    mov    cl, cflsz
  950.     int    bdos
  951.     ret
  952.  
  953. ; Jumping to this location is like retskp.  It assumes the instruction
  954. ;   after the call is a jmp addr.
  955.  
  956. rskp:    pop    bp
  957.     add    bp, 3
  958.     push    bp
  959.     ret
  960.  
  961.  
  962. ; Jumping here is the same as a ret.
  963.  
  964. r:    ret
  965.