home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / ZSYS / SIMTEL20 / ZCPR3 / DIR.MAC < prev    next >
Text File  |  2000-06-30  |  33KB  |  1,465 lines

  1. ;
  2. ; Program: DIR
  3. ; Author:  Richard Conn
  4. ; Version:  1.0
  5. ; Date: 23 Mar 84
  6. ;
  7. VERS    EQU    11        ; Changed manner of calculating disk size
  8.                 ; Using all0 and all1 instead of drm
  9.                 ; Added modified dirqs and fsize  jww
  10.                 ; Trial to list files vertically  jww
  11. ;
  12. ;VERS    EQU    10        ; Release
  13. ;
  14. MONTH    EQU    1
  15. DAY    EQU    2
  16. YEAR    EQU    85
  17. ;
  18. Z3ENV    SET    0F400H        ; Set zcpr3 environment descriptor address
  19. ;
  20. ; Equates
  21. ;
  22. YES    EQU    0FFH
  23. NO    EQU    0
  24. ;
  25. VIDEO    EQU    YES        ; Enhanced video?
  26. VOPT    EQU    YES        ; Print signon and vers no
  27. VERT    EQU    YES        ; List files vertically (default)
  28. ;
  29. FCB    EQU    5CH
  30. FCB2    EQU    6CH
  31. CTRLC    EQU    03H
  32. CR    EQU    0DH
  33. LF    EQU    0AH
  34. ;
  35. ; VLIB, Z3LIB and SYSLIB References
  36. ;
  37.     EXT    Z3VINIT,TINIT,STNDOUT,STNDEND,BDOS
  38.     EXT    CODEND,RETUD,PFN1,DFREE,DUTDIR,DPARAMS
  39.     EXT    CRLF,COUT,PAFDC,PHLDC,PHLFDC,Z3LOG,FILLB,GETCRT,CIN
  40. ;
  41. ; Environment Definition
  42. ;
  43.      IF    Z3ENV NE 0
  44. ;
  45. ; External ZCPR3 Environment Descriptor
  46. ;
  47.     JMP    START
  48.     DB    'Z3ENV'        ; This is a zcpr3 utility
  49.     DB    1        ; External environment descriptor
  50. Z3EADR:
  51.     DW    Z3ENV
  52. START:
  53.     LHLD    Z3EADR        ; Pt to zcpr3 environment
  54. ;
  55.      ELSE
  56. ;
  57. ; Internal ZCPR3 Environment Descriptor
  58. ;
  59.     MACLIB    Z3BASE.LIB
  60.     MACLIB    SYSENV.LIB
  61. Z3EADR:
  62.     JMP    START
  63.     SYSENV
  64. START:
  65.     LXI    H,Z3EADR    ; Pt to zcpr3 environment
  66.      ENDIF
  67. ;
  68. ; Start of Program -- Initialize ZCPR3 Environment
  69. ;
  70.     CALL    Z3VINIT        ; Initialize the zcpr3 env
  71.     CALL    TINIT        ; Initialize the terminal
  72. ;
  73. ; Make FCB Wild if No Entry
  74. ;
  75.     LXI    H,FCB+1        ; Pt to first char
  76.     MOV    A,M        ; Get it
  77.     CPI    ' '        ; Check for space
  78.     MVI    B,11        ; Prepare to set 11 bytes
  79.     MVI    A,'?'        ; To "?"
  80.     CZ    FILLB        ; Do it if space
  81. ;
  82. ; Check for Help
  83. ;
  84.     LXI    D,FCB+1        ; Pt to first char of fcb
  85.     LDAX    D        ; Get first char of fcb
  86.     CPI    '/'
  87.     JNZ    DOIT
  88.     CALL    PRINT
  89.     DB    'DIR Vers '
  90.     DB    (VERS/10)+'0','.',(VERS    MOD 10)+'0',CR,LF
  91.     DB    ' Syntax:  DIR dir:afn o',CR,LF
  92.     DB    ' Options: A=All, S=Sys, H=Horiz, V=Vert, '
  93.     DB    'T=File Type/Name Sor','t'+80H
  94.     RET
  95. ;
  96. ; Perform Directory Function
  97. ;
  98. DOIT:
  99.     DCX    D        ; Pt to fcb
  100.     CALL    Z3LOG        ; Log into dir
  101.     XRA    A        ; Clear disk selection byte
  102.     STAX    D
  103. ;
  104. ; Process Options in FCB2
  105. ;
  106.     LXI    H,FCB2+1    ; Pt to options
  107.     MVI    B,8        ; Allow for up to 8 options
  108.     MVI    C,10000000B    ; Assume just normal files
  109. OPTLOOP:
  110.     MOV    A,M        ; Get next char
  111.     INX    H        ; Advance
  112.     DCR    B        ; Count down
  113.     JZ    SETDATA        ; Done - set data
  114.     CPI    ' '
  115.     JZ    OPTLOOP
  116.     CPI    'H'        ; Select horizontal listing
  117.     JZ    SETHORIZ
  118.     CPI    'V'        ; Select vertical listing
  119.     JZ    SETVERT
  120.     CPI    'T'        ; File type?
  121.     JZ    SETTYPE
  122.     CPI    'S'        ; System?
  123.     JZ    SETSYS
  124.     CPI    'A'        ; System and normal?
  125.     JNZ    OPTLOOP
  126. ;
  127. ; Select Both System and Normal Files
  128. ;
  129.     MVI    A,11000000B    ; Normal and system files
  130.     JMP    SETSYS1
  131. ;
  132. ; Select Horizontal listing
  133. ;
  134. SETHORIZ:
  135.     MVI    A,YES
  136.     STA    HORIZ
  137.     JMP    OPTLOOP
  138. ;
  139. ; Select Vertical listing
  140. ;
  141. SETVERT:
  142.     MVI    A,NO
  143.     STA    HORIZ
  144.     JMP    OPTLOOP
  145. ;
  146. HORIZ:    DB    NOT VERT    ; Horizontal listing flag
  147. ;
  148. ; Select File Type/Name Alphabetization
  149. ;
  150. SETTYPE:
  151.     MOV    A,C        ; Get flag
  152.     ORI    00100000B
  153.     MOV    C,A
  154.     JMP    OPTLOOP
  155. ;
  156. ; Select Just System Files
  157. ;
  158. SETSYS:
  159.     MVI    A,01000000B    ; System
  160. SETSYS1:
  161.     PUSH    PSW
  162.     MOV    A,C
  163.     ANI    00111111B    ; Mask out
  164.     MOV    C,A
  165.     POP    PSW
  166.     ORA    C
  167.     MOV    C,A
  168.     JMP    OPTLOOP
  169. ;
  170. ; Set Selection Byte in A
  171. ;
  172. SETDATA:
  173.     CALL    DPARAMS        ; Init parameters
  174.     CALL    CODEND        ; Pt to free area
  175.     MOV    A,C        ; Selection in a
  176. ;
  177. ; Load and Sort Directory
  178. ;
  179.     CALL    DIRQS        ; Quick load
  180.     SHLD    DIRBEG        ; Beginning of directory area
  181.     JNZ    DISPLAY
  182.     CALL    PRINT
  183.     DB    ' Ovf','l'+80H
  184.     RET
  185. ;
  186. ; Display Directory
  187. ;
  188. DISPLAY:
  189.     PUSH    H        ; Save ptr to first entry
  190. ;
  191. ; Init:
  192. ;    Total of All File Sizes
  193. ;    Number of Files Displayed
  194. ;    Line Counter
  195. ;    Entry Counter
  196. ;
  197.      IF    VOPT        ; Signon and version
  198.     PUSH    B
  199.      IF    VIDEO
  200.     CALL    STNDOUT
  201.      ENDIF
  202.     MVI    C,22        ; Print 22 spaces
  203. DIS0:    MVI    A,' '
  204.     CALL    COUT
  205.     DCR    C
  206.     JNZ    DIS0
  207.     CALL    PRINT
  208.     DB    'DIRectory Version '
  209.     DB    VERS/10+'0','.',VERS MOD 10+'0'
  210.     DB    '  ',MONTH/10+'0',MONTH    MOD 10+'0','/'
  211.     DB    DAY/10+'0',DAY MOD 10+'0','/'
  212.     DB    YEAR/10+'0',YEAR MOD 10+'0'
  213.     DB    CR,LF+80H
  214.      IF    VIDEO
  215.     CALL    STNDEND
  216.      ENDIF
  217.     POP    B
  218.      ENDIF            ; Vopt
  219. ;
  220.     LXI    H,0        ; Set total size count
  221.     SHLD    TOTCOUNT
  222.     LXI    H,FCOUNT    ; Save file count
  223.     MOV    M,C
  224.     INX    H
  225.     MOV    M,B        ; File count saved from bc
  226.     PUSH    B        ; Save file count
  227.     MOV    H,B
  228.     MOV    L,C        ; Move it to hl
  229.     LXI    D,4
  230.     CALL    DIVIDE        ; Divide by four columns
  231.     JZ    DIS1
  232.     INX    B        ; Round up if remainder from division
  233. DIS1:    MOV    H,B
  234.     MOV    L,C        ; Quotient to hl
  235.     CALL    X16
  236.     SHLD    LINES
  237.     POP    H        ; Get file count
  238.     PUSH    H        ; And put it back
  239.     DCX    H        ; File count -1 points to last file
  240.     CALL    X16        ; Multiply by 16 chars/line
  241.     XCHG            ; Directory size to de
  242.     LHLD    DIRBEG
  243.     DAD    D
  244.     SHLD    DIREND
  245.     POP    B        ; Get file count
  246.     POP    H        ; Pt to first entry
  247.     XRA    A
  248.     STA    LCOUNT        ; Init line count
  249.     STA    COUNT        ; Init entry count
  250.     MOV    A,B        ; Check for done
  251.     ORA    C
  252.     JZ    PRREMAIN    ; Print remaining space on disk and exit
  253.     CALL    PRINT
  254.     DB    ' '+80H        ; Print first leading space
  255. ;
  256. ; Loop to Display File Entries
  257. ;
  258. DISPLOOP:
  259. ;
  260. ; Print Separator if Within a Line
  261. ;
  262.     LDA    COUNT        ; See if new entry on line
  263.     ANI    3
  264.     JZ    DISPL1
  265. ;
  266. ; Print Separator if Entry is Within a List
  267. ;
  268.      IF    VIDEO
  269.     CALL    STNDOUT
  270.      ENDIF
  271.     CALL    PRINT        ; Print separator
  272.     DB    '|',' '+80H
  273.      IF    VIDEO
  274.     CALL    STNDEND
  275.      ENDIF
  276. ;
  277. ; Print Next Entry
  278. ;
  279. DISPL1:
  280.     PUSH    H        ; Save key regs
  281.     PUSH    B        ; Hl pts to next entry, bc = count
  282. ;
  283. ; Print File Name
  284. ;
  285.     INX    H        ; Pt to file name
  286.     XCHG
  287.     CALL    PFN1        ; Print file name
  288.     XCHG
  289.     DCX    H        ; Pt to first byte of file entry
  290. ;
  291. ; Print File Size and Increment Total of All File Sizes
  292. ;
  293.     PUSH    H        ; Save ptr to first byte of file entry
  294.     CALL    FSIZE        ; Compute file size (to de)
  295.     LHLD    TOTCOUNT    ; Increment total count
  296.     DAD    D
  297.     SHLD    TOTCOUNT
  298.     XCHG
  299.     CALL    PHLDC        ; Print file size
  300.     POP    H        ; Get ptr to first byte of file entry
  301. ;
  302. ; Check R/O Byte
  303. ;
  304.     MVI    B,' '        ; Assume r/w
  305.     LXI    D,9        ; Pt to r/o
  306.     DAD    D
  307.     MOV    A,M        ; Get r/o byte
  308.     ANI    80H        ; Look at it
  309.     JZ    ROOUT
  310.     MVI    B,'r'        ; Set r/o
  311. ROOUT:
  312.     MOV    A,B        ; Get char
  313.     CALL    COUT
  314. ;
  315. ; Increment Entry Count and Issue New Line if Limit Reached
  316. ;
  317.     LDA    COUNT        ; Increment entry count
  318.     INR    A
  319.     STA    COUNT
  320.     LDA    HORIZ        ; Check horiz/vert listing
  321.     ORA    A
  322.     JZ    DISPL2        ; Vertical listing
  323.     LDA    COUNT
  324.     ANI    3        ; New line?
  325.     CZ    NEWLIN
  326.     JMP    DISPL2
  327. ;
  328. ; New Line - Increment Line Count and Issue Page Break if Limit Reached
  329. ;
  330. NEWLIN:    CALL    PRNL
  331.     LDA    LCOUNT        ; Count down lines
  332.     INR    A
  333.     STA    LCOUNT
  334.     CALL    GETCRT        ; Get crt data
  335.     INX    H        ; Pt to text line count
  336.     INX    H
  337.     DCR    A        ; Back up again
  338.     CMP    M        ; Compare
  339.     RNZ
  340.     XRA    A        ; Reset line count
  341.     STA    LCOUNT
  342.      IF    VIDEO
  343.     CALL    STNDOUT
  344.      ENDIF
  345.     CALL    PRINT
  346.     DB    '  Pause -',' '+80H
  347.      IF    VIDEO
  348.     CALL    STNDEND
  349.      ENDIF
  350.     CALL    CIN
  351.     CALL    PRNL        ; Print new line with leading space
  352.     CPI    CTRLC        ; Abort?
  353.     RNZ
  354.     POP    PSW        ; Clear the rest of the stack
  355.     POP    PSW
  356.     POP    PSW
  357.     RET            ; To zcpr3
  358. ;
  359. ; Advance to Next Entry
  360. ;
  361. DISPL2:
  362.     POP    B        ; Restore count and ptr to current entry
  363.     POP    H
  364.     LDA    HORIZ        ; Check horiz/vert listing
  365.     ORA    A
  366.     JNZ    DISP2        ; Horizontal
  367.     XCHG            ; Pointer to de
  368.     LHLD    LINES
  369.     DAD    D        ; Point to next entry
  370.     XCHG            ; New pointer to de
  371.     LHLD    DIREND
  372.     CALL    SUBDE        ; Check if new ptr is within the directory
  373.     XCHG            ; New pointer to hl
  374.     JNC    DISP3        ; New pointer is ok
  375.     LHLD    DIRBEG        ; Otherwise start new line
  376.     LXI    D,16        ; Next line
  377.     DAD    D
  378.     SHLD    DIRBEG        ; Save it
  379.     XRA    A
  380.     STA    COUNT        ; Clear column count
  381.     PUSH    H
  382.     PUSH    B
  383.     CALL    NEWLIN
  384.     POP    B
  385.     POP    H
  386.     JMP    DISP3
  387. DISP2:    LXI    D,16        ; Skip to next entry
  388.     DAD    D
  389. DISP3:    DCX    B        ; Count down
  390.     MOV    A,B        ; Done?
  391.     ORA    C
  392.     JNZ    DISPLOOP
  393.     LDA    COUNT        ; See if new line required
  394.     ANI    3
  395.     CNZ    CRLF        ; New line if any entries on line
  396. ;
  397. ; Print Remaining Space on Disk and Exit
  398. ;
  399. PRREMAIN:
  400. ;
  401. ; Print DU
  402. ;
  403.      IF    VIDEO
  404.     CALL    STNDOUT
  405.      ENDIF
  406.     MVI    B,8        ; Space over 8 spaces
  407.     MVI    A,' '
  408. SPACER:
  409.     CALL    COUT
  410.     DCR    B
  411.     JNZ    SPACER
  412.     CALL    RETUD        ; Get du in bc
  413.     MOV    A,B        ; Print disk letter
  414.     ADI    'A'        ; Convert to ascii
  415.     CALL    COUT
  416.     MOV    A,C        ; Print user number
  417.     CALL    PAFDC        ; Print floating
  418.     CALL    PRINT        ; Print separator
  419.     DB    ':'+80H
  420.     CALL    DUTDIR        ; See if matching dir
  421.     JZ    PRREM1
  422. ;
  423. ; Print DIR if any
  424. ;
  425.     MVI    B,8        ; 8 chars max
  426. PRREM0:
  427.     MOV    A,M        ; Get char
  428.     INX    H        ; Pt to next
  429.     CPI    ' '        ; Space?
  430.     CNZ    COUT        ; Echo char
  431.     DCR    B        ; Count down
  432.     JNZ    PRREM0
  433. ;
  434. ; Print File Count
  435. ;
  436. PRREM1:
  437.     LHLD    FCOUNT        ; Print number of files
  438.     CALL    PRINT
  439.     DB    ' --',' '+80H
  440.     CALL    PHLFDC
  441. ;
  442. ; Print Total of All File Sizes
  443. ;
  444.     LHLD    TOTCOUNT    ; Print total count
  445.     CALL    PRINT
  446.     DB    ' files using',' '+80H
  447.     CALL    PHLFDC        ; Print as floating
  448. ;
  449. ; Print Amount of Free Space Remaining
  450. ;
  451.     CALL    DFREE        ; Compute amount of free space
  452.     XCHG            ; In hl
  453.     CALL    PRINT
  454.     DB    'k ','('+80H
  455.     CALL    PHLFDC
  456.     CALL    PRINT
  457.     DB    'k remain of',' '+80H
  458.     CALL    DSIZE
  459.     CALL    PHLFDC
  460.     CALL    PRINT
  461.     DB    'k total',')'+80H
  462.      IF    VIDEO
  463.     CALL    STNDEND
  464.      ENDIF
  465.     RET
  466. ;
  467. ; Print New Line with Leading Space
  468. ;
  469. PRNL:
  470.     CALL    PRINT
  471.     DB    CR,LF,' '+80H    ; New line with leading space
  472.     RET
  473. ;
  474. ; Print Routine (String at Return Address) which is terminated by MSB
  475. ;
  476. PRINT:
  477.     XTHL            ; Pt to string and save hl
  478.     PUSH    PSW
  479. PRINT1:
  480.     MOV    A,M        ; Get next char
  481.     ANI    7FH        ; Mask msb
  482.     CALL    COUT
  483.     MOV    A,M        ; Get next char
  484.     INX    H        ; Pt to next
  485.     ANI    80H        ; Check msb
  486.     JZ    PRINT1
  487.     POP    PSW        ; Get a
  488.     XTHL            ; Restore return address and hl
  489.     RET
  490. ;
  491. ; DSIZE returns the size of the current disk in HL (k)
  492. ;
  493. DSIZE:    PUSH    D
  494.     PUSH    B
  495. ;
  496.     MVI    C,31        ; Return dpb address in hl
  497.     CALL    BDOS
  498.     INX    H
  499.     INX    H        ; Point to bls
  500.     MOV    A,M        ; Bls in a
  501.     STA    BLS
  502.     INX    H
  503.     INX    H
  504.     INX    H        ; Point to dsm
  505.     MOV    E,M
  506.     INX    H
  507.     MOV    D,M        ; Dsm in de
  508.     INX    D        ; Rel 1
  509.     PUSH    D        ; Save dsm on stack
  510.     INX    H        ; Point to drm
  511.     INX    H
  512.     INX    H        ; Point to all0
  513.     MOV    D,M
  514.     INX    H        ; Point to all1
  515.     MOV    E,M
  516.     XCHG            ; Allocation vector in hl
  517.     LXI    D,-1        ; Clear a counter
  518. DS0:    INX    D
  519.     CALL    SHLHL
  520.     JC    DS0
  521.     CALL    SUBDE        ; Get complement of count
  522.     POP    D        ; Get dsm from stack
  523.     DAD    D        ; Hl = groups available
  524.     LDA    BLS        ; Block shift factor
  525.     SUI    3        ; From bls in a
  526.     JZ    DSX
  527. DSIZ0:    DAD    H
  528.     DCR    A
  529.     JNZ    DSIZ0
  530. DSX:
  531.     POP    B
  532.     POP    D
  533.     RET
  534. ;
  535. ; DIVIDE divides HL by DE returning quotient in BC and remainder in HL
  536. ;  Zero flag is set if no remainder
  537. ;
  538. DIVIDE:    LXI    B,0        ; Clear quotient
  539. DIV0:    CALL    SUBDE        ; Subtract de from hl
  540.     JC    DIV1        ; Overflow
  541.     INX    B        ; Increment quotient
  542.     JMP    DIV0        ; Again..
  543. DIV1:    DAD    D        ; Restore remainder in hl
  544.     MOV    A,H        ; Check for remainder
  545.     ORA    L        ; Equal zero
  546.     RET
  547. ;
  548. ; SUBDE subtracts DE from HL returning carry set if de > hl
  549. ;
  550. SUBDE:    MOV    A,L
  551.     SUB    E
  552.     MOV    L,A
  553.     MOV    A,H
  554.     SBB    D
  555.     MOV    H,A
  556.     RET
  557. ;
  558. ; X16 simply shifts HL left four times
  559. ;
  560. X16:    DAD    H
  561.     DAD    H
  562.     DAD    H
  563.     DAD    H
  564.     RET
  565. ;
  566. ; SHLHL shifts HL left into carry
  567. ;
  568. SHLHL:    ORA    A        ; Reset carry
  569.     MOV    A,L
  570.     RAL
  571.     MOV    L,A
  572.     MOV    A,H
  573.     RAL
  574.     MOV    H,A
  575.     RET
  576. ;
  577. ; SYSLIB Module Name:  SDIRQS
  578. ; Author:  Richard Conn
  579. ; Part of SYSLIB3 SDIR Series
  580. ; SYSLIB Version Number:  3.0
  581. ; Module Version Number:  1.4
  582. ; Module Entry Points:
  583. ;    DIRQS
  584. ; Module External References:
  585. ;    None
  586. ;
  587.  
  588. ;*
  589. ;* EQUATES
  590. ;*
  591. CPM    EQU    0
  592. BUFF    EQU    80H        ; Dma buffer
  593. ESIZE    EQU    16        ; 16 bytes/entry
  594.  
  595. ;*
  596. ;*  GENERAL-PURPOSE DIRECTORY SELECT ROUTINE WITHOUT SIZING INFORMATION
  597. ;*    THIS ROUTINE SCANS FOR THE FCB PTED TO BY DE AND LOADS ALL ENTRIES
  598. ;* WHICH MATCH IT INTO THE MEMORY BUFFER PTED TO BY HL.  ON EXIT,
  599. ;* BC=NUMBER OF FILES IN BUFFER, AND HL PTS TO FIRST FILE IN BUFFER.
  600. ;*    THE DIRECTORY BUFFER GENERATED BY DIRQ CONTAINS ENTRIES WHICH MAY NOT
  601. ;* BE USED TO COMPUTE THE SIZE OF THE FILES USING THE FSIZE ROUTINE.  THE
  602. ;* DIRQS ROUTINE IS DESIGNED FOR THIS PURPOSE.    THE BASIC TRADEOFF BETWEEN
  603. ;* THE TWO ROUTINES IS THE DIRQ RUNS FASTER THAN DIRQS, AND THIS IS NOTICABLE
  604. ;* IF THERE IS A SIGNIFICANT NUMBER OF FILES TO BE PROCESSED.
  605. ;*
  606. ;*    THE DIRQ/DIRQS ROUTINES ARE INTENDED TO BE USED IN APPLICATIONS WHERE
  607. ;* THE ONLY THING DESIRED IS A DIRECTORY LOAD OF THE CURRENT DIRECTORY
  608. ;* (DISK AND USER).  DIRF/DIRFS PROVIDE MORE FLEXIBILITY AT A GREATER COST
  609. ;* IN TERMS OF SIZE.
  610. ;*
  611. ;*    INPUT PARAMETERS:
  612. ;*    HL PTS TO BUFFER, DE PTS TO FCB, A IS SELECT FLAG:
  613. ;*            Bit 7 - Select Non-Sys, Bit 6 - Select Sys
  614. ;*            Bit 5 - Sort by File Name and Type (0) or other (1)
  615. ;*            Bits 4-0 - Unused
  616. ;*    OUTPUT PARAMETERS:
  617. ;*    HL PTS TO FIRST FILE IN BUFFER
  618. ;*    BC = NUMBER OF FILES
  619. ;*    A=0 and Z Flag Set if TPA Overflow
  620. ;*    DE UNCHANGED
  621. ;*
  622. DIRQS:
  623.     PUSH    D        ; Save ptr to fcb
  624.  
  625.     STA    SELFLG        ; Save select flag for selection and alphabetization
  626.     SHLD    HOLD        ; Set ptr to hold buffer
  627.     LXI    B,36        ; Allow 36 bytes
  628.     DAD    B        ; Hl now points to temp fcb
  629.     SHLD    TFCB        ; Set ptr to temp fcb
  630.     DAD    D        ; Hl now pts to scratch area
  631.  
  632.     PUSH    D        ; Save ptr to fcb
  633.     CALL    DBUFFER        ; Get ptrs
  634.     POP    D        ; Get ptr to fcb
  635.     PUSH    H        ; Save ptr to buffer
  636.     CALL    DIRLOAD        ; Load directory (fast load)
  637.     POP    H        ; Get ptr to buffer
  638.  
  639.     POP    D        ; Get ptr to fcb
  640.  
  641.     RZ            ; Abort if tpa overflow
  642.  
  643.     PUSH    PSW        ; Save flag to indicate no tpa overflow
  644.     CALL    DIRALPHA    ; Alphabetize
  645.     POP    PSW        ; Get psw (tpa overflow flag)
  646.     RET
  647.  
  648. ;*
  649. ;*  THIS ROUTINE ACCEPTS A BASE ADDRESS FOR THE DYNAMIC BUFFERS
  650. ;*    REQUIRED, DETERMINES HOW MUCH SPACE IS REQUIRED FOR THE BUFFERS,
  651. ;*    AND SETS THE ORDER PTR TO PT TO THE FIRST AND DIRBUF TO PT TO
  652. ;*    THE SECOND (ORDER SPACE = DIRMAX*2 AND DIRBUF = DIRMAX * ESIZE)
  653. ;*  ON INPUT, HL PTS TO AVAILABLE BASE
  654. ;*  ON OUTPUT, HL PTS TO DIRBUF
  655. ;*    A=0 AND ZERO FLAG SET IF CCP OVERRUN
  656. ;*
  657. DBUFFER:
  658.     SHLD    ORDER        ; Pt to order table
  659.     CALL    DPARAMS0    ; Get parameters
  660.     LHLD    DIRMAX        ; Number of entries in dir
  661.     XCHG            ; In de
  662.     LHLD    ORDER        ; Add to order base
  663.     DAD    D        ; *1
  664.     CALL    MEMCHK        ; Check for within range
  665.     DAD    D        ; Hl pts to dirbuf
  666.     CALL    MEMCHK        ; Check for within range
  667.     SHLD    DIRBUF        ; Set ptr and hl pts to directory buffer
  668.     XRA    A        ; Ok
  669.     DCR    A        ; Set flags (nz)
  670.     RET
  671.  
  672. MEMCHK:
  673.     PUSH    H        ; Save regs
  674.     PUSH    D
  675.     XCHG            ; Next address in de
  676.     LHLD    BDOS+1        ; Get address of bdos
  677.     MOV    A,D        ; Check for page overrun
  678.     CMP    H
  679.     JNC    MEMORUN        ; Overrun if d>=h
  680.     POP    D
  681.     POP    H
  682.     RET
  683. MEMORUN:
  684.     POP    D        ; Restore
  685.     POP    H
  686.     POP    PSW        ; Clear stack
  687.     XRA    A        ; Return 0
  688.     RET
  689.  
  690. ;*
  691. ;*  THIS ROUTINE EXTRACTS DISK PARAMETER INFORMATON FROM THE DPB AND
  692. ;*    STORES THIS INFORMATION IN:
  693. ;*    BLKSHF    <-- BLOCK SHIFT FACTOR (1 BYTE)
  694. ;*    BLKMSK    <-- BLOCK MASK (1 BYTE)
  695. ;*    EXTENT    <-- EXTENT MASK (1 BYTE) [NOT ANY MORE]
  696. ;*    BLKMAX    <-- MAX NUMBER OF BLOCKS ON DISK (2 BYTES)
  697. ;*    DIRMAX    <-- MAX NUMBER OF DIRECTORY ENTRIES (2 BYTES)
  698. ;*
  699. DPARAMS0:
  700. ;*
  701. ;*  VERSION 2.x OR MP/M
  702. ;*
  703.     MVI    C,31        ; 2.x or mp/m...request dpb
  704.     CALL    BDOS
  705.     INX    H
  706.     INX    H
  707.     MOV    A,M        ; Get block shift
  708.     STA    BLKSHF        ; Block shift factor
  709.     INX    H        ; Get block mask
  710.     MOV    A,M
  711.     STA    BLKMSK        ; Block mask
  712.     INX    H
  713.     INX    H
  714.     MOV    E,M        ; Get max block number
  715.     INX    H
  716.     MOV    D,M
  717.     XCHG
  718.     INX    H        ; Add 1 for max number of blocks
  719.     SHLD    BLKMAX        ; Maximum number of blocks
  720.     XCHG
  721.     INX    H
  722.     MOV    E,M        ; Get directory size
  723.     INX    H
  724.     MOV    D,M
  725.     XCHG
  726.     INX    H        ; Add 1 for number of entries
  727.     SHLD    DIRMAX        ; Maximum number of directory entries
  728.     RET
  729.  
  730. ;*
  731. ;*  BUILD DIRECTORY TABLE AT DIRBUF
  732. ;*    THIS IS THE OPTIMAL DIRECTORY LOAD ROUTINE; IT ONLY LOADS UNIQUE
  733. ;*        FILE NAMES FROM DISK, BUT THE INFORMATION IS NOT SUFFICIENT
  734. ;*        TO COMPUTE THE FILE SIZES
  735. ;*    ON INPUT, HL PTS TO DIRECTORY BUFFER (16 x N MAX)
  736. ;*        DE PTS TO FCB (ONLY 12 BYTES NEEDED)
  737. ;*    ON OUTPUT, BC IS NUM OF FILES
  738. ;*        A=0 AND ZERO FLAG SET IF TPA OVERFLOW
  739. ;*
  740. DIRLOAD:
  741.     SHLD    DSTART        ; Set start of buffer area
  742.     INX    D        ; Pt to file name
  743.     LHLD    TFCB        ; Pt to tfcb
  744.     MVI    M,0        ; Select current disk
  745.     INX    H        ; Pt to file name in tfcb
  746.     MVI    B,11        ; 11 chars
  747. DLLOOP:
  748.     LDAX    D        ; Copy
  749.     MOV    M,A
  750.     INX    H        ; Pt to next
  751.     INX    D
  752.     DCR    B        ; Count down
  753.     JNZ    DLLOOP
  754.     MVI    M,'?'        ; Select all extents
  755.     INX    H        ; Pt to next char
  756.     MVI    M,0
  757.     INX    H
  758.     MVI    M,'?'        ; And all modules
  759.     INX    H
  760.     MVI    B,21        ; 23 chars
  761.     XRA    A        ; Zero rest of tfcb
  762. DLLOOP1:
  763.     MOV    M,A        ; Store zero
  764.     INX    H        ; Pt to next
  765.     DCR    B        ; Count down
  766.     JNZ    DLLOOP1
  767.  
  768. ;*
  769. ;*  THIS SECTION OF CODE INITIALIZES THE COUNTERS USED
  770. ;*
  771.     LXI    H,0        ; Hl=0
  772.     SHLD    FCOUNT0        ; Total files on disk = 0
  773. ;*
  774. ;*  NOW WE BEGIN SCANNING FOR FILES TO PLACE INTO THE MEMORY BUFFER
  775. ;*
  776.     MVI    C,17        ; Search for file
  777.     JMP    DIRLP1
  778. DIRLP:
  779.     CALL    PENTRY        ; Place entry in dir
  780.     JZ    DIROVFL        ; Memory overflow error
  781.     MVI    C,18        ; Search for next match
  782. DIRLP1:
  783.     LHLD    TFCB        ; Pt to fcb
  784.     XCHG
  785.     CALL    BDOS
  786.     CPI    255        ; Done?
  787.     JNZ    DIRLP
  788. ;*
  789. ;*  NOW WE ARE DONE WITH THE LOAD -- SET UP RETURN VALUES
  790. ;*
  791. DIRDN:
  792.     XRA    A        ; Load ok
  793.     DCR    A        ; Set flags (nz)
  794. DIRDNX:
  795.     LHLD    FCOUNT0        ; Get total number of files
  796.     MOV    B,H        ; In bc
  797.     MOV    C,L
  798.     RET
  799. ;*
  800. ;*  MEMORY OVERFLOW ERROR
  801. ;*
  802. DIROVFL:
  803.     XRA    A        ; Load error
  804.     JMP    DIRDNX
  805.  
  806. ;*
  807. ;*  PENTRY --
  808. ;*  PLACE ENTRY IN DIRECTORY BUFFER IF NOT AN ERASED ENTRY
  809. ;*
  810. ;*  ON INPUT,  A=0-3 FOR ADR INDEX IN BUFF OF ENTRY FCB
  811. ;*          FCOUNT0=NUMBER OF FILES IN DIR SO FAR
  812. ;*  ON OUTPUT, FCOUNT0=NUMBER OF FILES IN DIR SO FAR
  813. ;*          A=0 AND ZERO FLAG SET IF MEMORY OVERFLOW ERROR
  814. ;*
  815. PENTRY:
  816.     RRC            ; Multiply by 32 for offset computation
  817.     RRC
  818.     RRC
  819.     ANI    60H        ; A=byte offset
  820.     LXI    D,BUFF        ; Pt to buffer entry
  821.     MOV    L,A        ; Let hl=offset
  822.     MVI    H,0
  823.     DAD    D        ; Hl=ptr to fcb
  824. ;*
  825. ;*  HL=ADR OF FCB IN BUFF
  826. ;*
  827.     CALL    ATTEST        ; Test attributes
  828.     JZ    PEDONE        ; Skip if attribute not desired
  829.  
  830. ;*
  831. ;*  SCAN DIRECTORY ENTRIES AS LOADED SO FAR FOR ANOTHER ENTRY BY THE SAME
  832. ;*    NAME; IF FOUND, SET THAT ENTRY TO BE THE ENTRY WITH THE LARGER EX
  833. ;*    AND RETURN WITH THE ZERO FLAG SET, INDICATING NO NEW FILE; IF NOT
  834. ;*    FOUND, RETURN WITH ZERO FLAG RESET (NZ)
  835. ;*
  836.     CALL    DUPENTRY    ; Check for duplicate and select ex
  837.     JZ    PEDONE        ; Skip if duplicate
  838.  
  839. ;*
  840. ;*  COPY FCB PTED TO BY HL INTO DIRECTORY BUFFER
  841. ;*
  842.     XCHG            ; Save ptr in de
  843.     LHLD    DIRBUF        ; Pt to next entry location
  844.     XCHG            ; Hl pts to fcb, de pts to next entry location
  845.     MVI    B,ESIZE        ; Number of bytes/entry
  846.     CALL    SDMOVE        ; Copy fcb into memory buffer
  847.     XCHG            ; Hl pts to next entry
  848.     SHLD    DIRBUF        ; Set ptr
  849.     XCHG            ; Ptr to next entry in de
  850.     LHLD    BDOS+1        ; Base address of bdos in hl
  851.     MOV    A,H        ; Get base page of bdos
  852.     SUI    9        ; Compute 1 page in front of base page of ccp
  853.     CMP    D        ; Is ptr to next entry beyond this?
  854.     RZ
  855.  
  856. ;*  INCREMENT TOTAL NUMBER OF FILES
  857.     LHLD    FCOUNT0        ; Total files = total files + 1
  858.     INX    H
  859.     SHLD    FCOUNT0
  860.  
  861. ;*  DONE WITH PENTRY AND NO ERROR
  862. PEDONE:
  863.     XRA    A        ; No error
  864.     DCR    A        ; Set flags (nz)
  865.     RET
  866.  
  867. ;*
  868. ;*  CHECK ATTRIBUTES OF FILE ENTRY PTED TO BY HL AGAINST SELFLG
  869. ;*    IF SYSTEM FILE AND SYSTEM ATTRIBUTE SET, RETURN NZ
  870. ;*    IF NORMAL FILE AND NORMAL ATTRIBUTE SET, RETURN NZ
  871. ;*
  872. ATTEST:
  873.     PUSH    H        ; Save ptr
  874.     LXI    B,10        ; Pt to system attribute
  875.     DAD    B
  876.     MOV    A,M        ; Get system attribute
  877.     POP    H        ; Restore ptr
  878.     ANI    80H        ; Check for sys
  879.     LDA    SELFLG        ; Get selection flag
  880.     JZ    ATDIR
  881.     ANI    01000000B    ; Check system attribute
  882.     RET
  883. ATDIR:
  884.     ANI    10000000B    ; Check normal attribute
  885.     RET
  886.  
  887. ;*
  888. ;*  SCAN DIRECTORY ENTRIES AS LOADED SO FAR FOR ANOTHER ENTRY BY THE SAME
  889. ;*    NAME; IF FOUND, SET THAT ENTRY TO BE THE ENTRY WITH THE LARGER EX
  890. ;*    AND RETURN WITH THE ZERO FLAG SET, INDICATING NO NEW FILE; IF NOT
  891. ;*    FOUND, RETURN WITH ZERO FLAG RESET (NZ)
  892. ;*  ON INPUT, HL PTS TO ENTRY TO SCAN FOR, FCOUNT0 = NUMBER OF ENTRIES SO FAR,
  893. ;*        AND (DSTART) = STARTING ADDRESS OF DIRECTORY LOADED
  894. ;*  ON OUTPUT, A=0 AND ZERO FLAG SET IF DUPLICATE ENTRY FOUND; A=0FFH AND NZ
  895. ;*        IF NO DUP ENTRY FOUND
  896. ;*        ONLY HL NOT AFFECTED
  897. ;*
  898. DUPENTRY:
  899.     PUSH    H        ; Save ptr to entry to scan for
  900.     XCHG            ; Ptr in de
  901.     LHLD    FCOUNT0        ; Check count
  902.     MOV    A,H        ; No entries?
  903.     ORA    L
  904.     JZ    NODUP        ; No duplicate entry return
  905.     MOV    B,H        ; Bc=number of entries
  906.     MOV    C,L
  907.     LHLD    DSTART        ; Hl pts to first entry
  908. DUPELOOP:
  909.     PUSH    B        ; Save count
  910.     PUSH    H        ; Save ptrs
  911.     PUSH    D
  912.     INX    H        ; Pt to fn
  913.     INX    D
  914.     MVI    B,11        ; Compare fn and ft
  915.     CALL    COMP
  916.     JNZ    NODUPL        ; Continue looking for another entry
  917. ;  DUPLICATE ENTRIES HAVE BEEN IDENTIFIED AT THIS POINT
  918.     MOV    C,M        ; Extent in low order
  919.     INX    H
  920.     INX    H
  921.     MOV    B,M        ; Module in high order
  922.     PUSH    B        ; Save entry size a moment
  923.     XCHG            ; Point hl to target
  924.     MOV    E,M        ; Extent in low order
  925.     INX    H
  926.     INX    H
  927.     MOV    D,M        ; Module in high order
  928.     POP    H        ; Dir in hl, target in de
  929.     XCHG
  930.     CALL    SUBDE        ; Subtract dir size from target size
  931.     POP    D        ; Get ptrs
  932.     POP    H
  933.     JC    DUPSMALL    ; Target is smaller
  934. ;  NEW TARGET IS LARGER THAN STORED ENTRY
  935.     XCHG            ; Hl pts to target, de pts to dir entry
  936.     MVI    B,ESIZE        ; Number of bytes to move
  937.     CALL    SDMOVE        ; Move it
  938. ;  NEW TARGET IS SMALLER THAN STORED ENTRY
  939. DUPSMALL:
  940.     POP    B        ; Clear count from stack
  941.     XRA    A        ; Indicate dup found
  942.     POP    H        ; Restore ptr to entry to scan for
  943.     RET
  944. ;  NO DUPLICATE FOUND; ADVANCE TO NEXT ENTRY
  945. NODUPL:
  946.     POP    D        ; Restore ptrs
  947.     POP    H
  948.     LXI    B,ESIZE        ; Hl pts to current entry in buffer, so add esize to it
  949.     DAD    B
  950.     POP    B        ; Get count
  951.     DCX    B        ; Count down
  952.     MOV    A,B        ; Check for done
  953.     ORA    C
  954.     JNZ    DUPELOOP
  955. ;  NO DUPLICATE FOUND
  956. NODUP:
  957.     XRA    A        ; Indicate dup not found
  958.     DCR    A        ; Set flags (nz)
  959.     POP    H        ; Restore ptr to entry to scan for
  960.     RET
  961.  
  962. ;*
  963. ;*  DIRALPHA -- ALPHABETIZES DIRECTORY PTED TO BY HL; BC CONTAINS
  964. ;*    THE NUMBER OF FILES IN THE DIRECTORY AND A = SORT FLAG
  965. ;*    (0=SORT BY FILE NAME/TYPE, <>0 = SORT BY FILE TYPE/NAME)
  966. ;*
  967. DIRALPHA:
  968.     MOV    A,B        ; Any files?
  969.     ORA    C
  970.     RZ
  971.     PUSH    H        ; Save regs
  972.     PUSH    D
  973.     PUSH    B
  974.     SHLD    DIRBUF        ; Save ptr to directory
  975.     PUSH    H        ; Save hl
  976.     MOV    H,B        ; Hl=bc=file count
  977.     MOV    L,C
  978.     SHLD    N        ; Set "N"
  979.     POP    H
  980. ;*
  981. ;*  SHELL SORT --
  982. ;*    THIS SORT ROUTINE IS ADAPTED FROM "SOFTWARE TOOLS"
  983. ;*    BY KERNIGAN AND PLAUGHER, PAGE 106.  COPYRIGHT, 1976, ADDISON-WESLEY.
  984. ;*  ON ENTRY, BC=NUMBER OF ENTRIES
  985. ;*
  986. SORT:
  987.     XCHG            ; Pointer to directory in de
  988.     LHLD    ORDER        ; Pt to order table
  989. ;*
  990. ;*  SET UP ORDER TABLE; HL PTS TO NEXT ENTRY IN ORDER TABLE, DE PTS TO NEXT
  991. ;*    ENTRY IN DIRECTORY, BC = NUMBER OF ELEMENTS REMAINING
  992. ;*
  993. SORT1:
  994.     MOV    M,E        ; Store low-order address
  995.     INX    H        ; Pt to next order byte
  996.     MOV    M,D        ; Store high-order address
  997.     INX    H        ; Pt to next order entry
  998.     PUSH    H        ; Save ptr
  999.     LXI    H,ESIZE        ; Hl=number of bytes/entry
  1000.     DAD    D        ; Pt to next dir1 entry
  1001.     XCHG            ; De pts to next entry
  1002.     POP    H        ; Get ptr to order table
  1003.     DCX    B        ; Count down
  1004.     MOV    A,B        ; Done?
  1005.     ORA    C
  1006.     JNZ    SORT1
  1007. ;*
  1008. ;*  THIS IS THE MAIN SORT LOOP FOR THE SHELL SORT IN "SOFTWARE TOOLS" BY K&P
  1009. ;*
  1010.  
  1011. ;*
  1012. ;*  SHELL SORT FROM "SOFTWARE TOOLS" BY KERNINGHAN AND PLAUGER
  1013. ;*
  1014.     LHLD    N        ; Number of items to sort
  1015.     SHLD    GAP        ; Set initial gap to n for first division by 2
  1016.  
  1017. ;*  FOR (GAP = N/2; GAP > 0; GAP = GAP/2)
  1018. SRTL0:
  1019.     ORA    A        ; Clear carry
  1020.     LHLD    GAP        ; Get previous gap
  1021.     MOV    A,H        ; Rotate right to divide by 2
  1022.     RAR
  1023.     MOV    H,A
  1024.     MOV    A,L
  1025.     RAR
  1026.     MOV    L,A
  1027.  
  1028. ;*  TEST FOR ZERO
  1029.     ORA    H
  1030.     JZ    SDONE        ; Done with sort if gap = 0
  1031.  
  1032.     SHLD    GAP        ; Set value of gap
  1033.     SHLD    I        ; Set i=gap for following loop
  1034.  
  1035. ;*  FOR (I = GAP + 1; I <= N; I = I + 1)
  1036. SRTL1:
  1037.     LHLD    I        ; Add 1 to i
  1038.     INX    H
  1039.     SHLD    I
  1040.  
  1041. ;*  TEST FOR I <= N
  1042.     XCHG            ; I is in de
  1043.     LHLD    N        ; Get n
  1044.     MOV    A,L        ; Compare by subtraction
  1045.     SUB    E
  1046.     MOV    A,H
  1047.     SBB    D        ; Carry set means i > n
  1048.     JC    SRTL0        ; Don't do for loop if i > n
  1049.  
  1050.     LHLD    I        ; Set j = i initially for first subtraction of gap
  1051.     SHLD    J
  1052.  
  1053. ;*  FOR (J = I - GAP; J > 0; J = J - GAP)
  1054. SRTL2:
  1055.     LHLD    GAP        ; Get gap
  1056.     XCHG            ; In de
  1057.     LHLD    J        ; Get j
  1058.     MOV    A,L        ; Compute j - gap
  1059.     SUB    E
  1060.     MOV    L,A
  1061.     MOV    A,H
  1062.     SBB    D
  1063.     MOV    H,A
  1064.     SHLD    J        ; J = j - gap
  1065.     JC    SRTL1        ; If carry from subtractions, j < 0 and abort
  1066.     MOV    A,H        ; J=0?
  1067.     ORA    L
  1068.     JZ    SRTL1        ; If zero, j=0 and abort
  1069.  
  1070. ;*  SET JG = J + GAP
  1071.     XCHG            ; J in de
  1072.     LHLD    GAP        ; Get gap
  1073.     DAD    D        ; J + gap
  1074.     SHLD    JG        ; Jg = j + gap
  1075.  
  1076. ;*  IF (V(J) <= V(JG))
  1077.     CALL    ICOMPARE    ; J in de, jg in hl
  1078.  
  1079. ;*  ... THEN BREAK
  1080.     JC    SRTL1
  1081.  
  1082. ;*  ... ELSE EXCHANGE
  1083.     LHLD    J        ; Swap j, jg
  1084.     XCHG
  1085.     LHLD    JG
  1086.     CALL    ISWAP        ; J in de, jg in hl
  1087.  
  1088. ;*  END OF INNER-MOST FOR LOOP
  1089.     JMP    SRTL2
  1090.  
  1091. ;*
  1092. ;*  SORT IS DONE -- RESTRUCTURE DIR1 IN SORTED ORDER IN PLACE
  1093. ;*
  1094. SDONE:
  1095.     LHLD    N        ; Number of entries
  1096.     MOV    B,H        ; In bc
  1097.     MOV    C,L
  1098.     LHLD    ORDER        ; Ptr to ordered pointer table
  1099.     SHLD    PTPTR        ; Set ptr ptr
  1100.     LHLD    DIRBUF        ; Ptr to unordered directory
  1101.     SHLD    PTDIR        ; Set ptr dir buffer
  1102.  
  1103. ;*  FIND PTR TO NEXT DIR1 ENTRY
  1104. SRTDN:
  1105.     LHLD    PTPTR        ; Pt to remaining pointers
  1106.     XCHG            ; In de
  1107.     LHLD    PTDIR        ; Hl pts to next dir entry
  1108.     PUSH    B        ; Save count of remaining entries
  1109.  
  1110. ;*  FIND PTR TABLE ENTRY
  1111. SRTDN1:
  1112.     LDAX    D        ; Get current pointer table entry value
  1113.     INX    D        ; Pt to high-order pointer byte
  1114.     CMP    L        ; Compare against dir1 address low
  1115.     JNZ    SRTDN2        ; Not found yet
  1116.     LDAX    D        ; Low-order bytes match -- get high-order pointer byte
  1117.     CMP    H        ; Compare against dir1 address high
  1118.     JZ    SRTDN3        ; Match found
  1119. SRTDN2:
  1120.     INX    D        ; Pt to next ptr table entry
  1121.     DCX    B        ; Count down
  1122.     MOV    A,C        ; End of table?
  1123.     ORA    B
  1124.     JNZ    SRTDN1        ; Continue if not
  1125.  
  1126. ;*  FATAL ERROR -- INTERNAL ERROR; POINTER TABLE NOT CONSISTENT
  1127. FERR$PTR:
  1128.     MVI    E,7        ; Ring bell
  1129.     MVI    C,2        ; Output
  1130.     CALL    BDOS
  1131.     JMP    CPM
  1132.  
  1133. ;*  FOUND THE POINTER TABLE ENTRY WHICH POINTS TO THE NEXT UNORDERED DIR1 ENTRY
  1134. ;*    MAKE BOTH POINTERS (PTR TO NEXT, PTR TO CURRENT UNORDERED DIR1 ENTRY)
  1135. ;*    POINT TO SAME LOCATION (PTR TO NEXT DIR1 ENTRY TO BE ORDERED)
  1136. SRTDN3:
  1137.     LHLD    PTPTR        ; Get ptr to next ordered entry
  1138.     DCX    D        ; De pts to low-order pointer address
  1139.     MOV    A,M        ; Make ptr to next unordered dir1 pt to buffer for
  1140.     STAX    D        ; Dir1 entry to be moved to next unordered dir1 pos
  1141.     INX    H        ; Pt to next ptr address
  1142.     INX    D
  1143.     MOV    A,M        ; Make high point similarly
  1144.     STAX    D
  1145.  
  1146. ;*  COPY NEXT UNORDERED DIR1 ENTRY TO HOLD BUFFER
  1147.     MVI    B,ESIZE        ; B=number of bytes/entry
  1148.     LHLD    HOLD        ; Pt to hold buffer
  1149.     XCHG
  1150.     LHLD    PTDIR        ; Pt to entry
  1151.     PUSH    B        ; Save b=number of bytes/entry
  1152.     CALL    SDMOVE
  1153.     POP    B
  1154.  
  1155. ;*  COPY TO-BE-ORDERED DIR1 ENTRY TO NEXT ORDERED DIR1 POSITION
  1156.     LHLD    PTPTR        ; Point to its pointer
  1157.     MOV    E,M        ; Get low-address pointer
  1158.     INX    H
  1159.     MOV    D,M        ; Get high-address pointer
  1160.     LHLD    PTDIR        ; Destination address for next ordered dir1 entry
  1161.     XCHG            ; Hl pts to entry to be moved, de pts to dest
  1162.     PUSH    B        ; Save b=number of bytes/entry
  1163.     CALL    SDMOVE
  1164.     POP    B
  1165.     XCHG            ; Hl pts to next unordered dir1 entry
  1166.     SHLD    PTDIR        ; Set pointer for next loop
  1167.  
  1168. ;*  COPY ENTRY IN HOLD BUFFER TO LOC PREVIOUSLY HELD BY LATEST ORDERED ENTRY
  1169.     LHLD    PTPTR        ; Get ptr to ptr to the destination
  1170.     MOV    E,M        ; Get low-address pointer
  1171.     INX    H
  1172.     MOV    D,M        ; High-address pointer
  1173.     LHLD    HOLD        ; Hl pts to hold buffer, de pts to entry dest
  1174.     CALL    SDMOVE        ; B=number of bytes/entry
  1175.  
  1176. ;*  POINT TO NEXT ENTRY IN POINTER TABLE
  1177.     LHLD    PTPTR        ; Pointer to current entry
  1178.     INX    H        ; Skip over it
  1179.     INX    H
  1180.     SHLD    PTPTR
  1181.  
  1182. ;*  COUNT DOWN
  1183.     POP    B        ; Get counter
  1184.     DCX    B        ; Count down
  1185.     MOV    A,C        ; Done?
  1186.     ORA    B
  1187.     JNZ    SRTDN
  1188.     POP    B        ; Restore regs
  1189.     POP    D
  1190.     POP    H
  1191.     RET            ; Done
  1192.  
  1193. ;*
  1194. ;*  SWAP (Exchange) the pointers in the ORDER table whose indexes are in
  1195. ;*    HL and DE
  1196. ;*
  1197. ISWAP:
  1198.     PUSH    H        ; Save hl
  1199.     LHLD    ORDER        ; Address of order table - 2
  1200.     MOV    B,H        ; In bc
  1201.     MOV    C,L
  1202.     POP    H
  1203.     DCX    H        ; Adjust index to 0...n-1 from 1...n
  1204.     DAD    H        ; Hl pts to offset address indicated by index
  1205.                 ; Of original hl (1, 2, ...)
  1206.     DAD    B        ; Hl now pts to pointer involved
  1207.     XCHG            ; De now pts to pointer indexed by hl
  1208.     DCX    H        ; Adjust index to 0...n-1 from 1...n
  1209.     DAD    H        ; Hl pts to offset address indicated by index
  1210.                 ; Of original de (1, 2, ...)
  1211.     DAD    B        ; Hl now pts to pointer involved
  1212.     MOV    C,M        ; Exchange pointers -- get old (de)
  1213.     LDAX    D        ; -- get old (hl)
  1214.     XCHG            ; Switch
  1215.     MOV    M,C        ; Put new (hl)
  1216.     STAX    D        ; Put new (de)
  1217.     INX    H        ; Pt to next byte of pointer
  1218.     INX    D
  1219.     MOV    C,M        ; Get old (hl)
  1220.     LDAX    D        ; Get old (de)
  1221.     XCHG            ; Switch
  1222.     MOV    M,C        ; Put new (de)
  1223.     STAX    D        ; Put new (hl)
  1224.     RET
  1225. ;*
  1226. ;*  ICOMPARE compares the entry pointed to by the pointer pointed to by HL
  1227. ;*    with that pointed to by DE (1st level indirect addressing); on entry,
  1228. ;*    HL and DE contain the numbers of the elements to compare (1, 2, ...);
  1229. ;*    on exit, Carry Set means ((DE)) < ((HL)), Zero Set means ((HL)) = ((DE)),
  1230. ;*    and Non-Zero and No-Carry means ((DE)) > ((HL))
  1231. ;*
  1232. ICOMPARE:
  1233.     PUSH    H        ; Save hl
  1234.     LHLD    ORDER        ; Address of order - 2
  1235.     MOV    B,H        ; In bc
  1236.     MOV    C,L
  1237.     POP    H
  1238.     DCX    H        ; Adjust index to 0...n-1 from 1...n
  1239.     DAD    H        ; Double the element number to point to the ptr
  1240.     DAD    B        ; Add to this the base address of the ptr table
  1241.     XCHG            ; Result in de
  1242.     DCX    H        ; Adjust index to 0...n-1 from 1...n
  1243.     DAD    H        ; Do the same with the original de
  1244.     DAD    B
  1245.     XCHG
  1246.  
  1247. ;*
  1248. ;*  HL NOW POINTS TO THE POINTER WHOSE INDEX WAS IN HL TO BEGIN WITH
  1249. ;*  DE NOW POINTS TO THE POINTER WHOSE INDEX WAS IN DE TO BEGIN WITH
  1250. ;*    FOR EXAMPLE, IF DE=5 AND HL=4, DE NOW POINTS TO THE 5TH PTR AND HL
  1251. ;* TO THE 4TH POINTER
  1252. ;*
  1253.     MOV    C,M        ; Bc is made to point to the object indexed to
  1254.     INX    H        ; By the original hl
  1255.     MOV    B,M
  1256.     XCHG
  1257.     MOV    E,M        ; De is made to point to the object indexed to
  1258.     INX    H        ; By the original de
  1259.     MOV    D,M
  1260.     MOV    H,B        ; Set hl = object pted to indirectly by bc
  1261.     MOV    L,C
  1262.  
  1263. ;*
  1264. ;*  COMPARE DIR ENTRY PTED TO BY HL WITH THAT PTED TO BY DE;
  1265. ;*    NO NET EFFECT ON HL, DE; RET W/CARRY SET MEANS DE<HL
  1266. ;*    RET W/ZERO SET MEANS DE=HL
  1267. ;*
  1268. CMP$ENTRY:
  1269.     LDA    SELFLG        ; Group by file type?
  1270.     ANI    00100000B
  1271.     JZ    CMP$FN$FT
  1272. ;*
  1273. ;*  COMPARE BY FILE TYPE AND FILE NAME (IN THAT ORDER)
  1274. ;*
  1275.     PUSH    H
  1276.     PUSH    D
  1277.     LXI    B,9        ; Pt to ft (8 bytes + 1 byte for user number)
  1278.     DAD    B
  1279.     XCHG
  1280.     DAD    B
  1281.     XCHG            ; De, hl now pt to their ft's
  1282.     MVI    B,3        ; 3 bytes
  1283.     CALL    COMP        ; Compare ft's
  1284.     POP    D
  1285.     POP    H
  1286.     RNZ            ; Continue if complete match
  1287.     MVI    B,8        ; 8 bytes
  1288.     JMP    CMP$FT1
  1289. ;*
  1290. ;*  COMPARE BY FILE NAME AND FILE TYPE (IN THAT ORDER)
  1291. ;*
  1292. CMP$FN$FT:
  1293.     MVI    B,11        ; 11 bytes for fn and ft
  1294. CMP$FT1:
  1295.     PUSH    H
  1296.     PUSH    D
  1297.     INX    H        ; Pt to fn
  1298.     INX    D
  1299.     CALL    COMP        ; Do comparison
  1300.     POP    D
  1301.     POP    H
  1302.     RET
  1303. ;*
  1304. ;*  COMP COMPARES DE W/HL FOR B BYTES; RET W/CARRY IF DE<HL
  1305. ;*    MSB IS DISREGARDED
  1306. ;*
  1307. COMP:
  1308.     MOV    A,M        ; Get (hl)
  1309.     ANI    7FH        ; Mask msb
  1310.     MOV    C,A        ; In c
  1311.     LDAX    D        ; Compare
  1312.     ANI    7FH        ; Mask msb
  1313.     CMP    C
  1314.     RNZ
  1315.     INX    H        ; Pt to next
  1316.     INX    D
  1317.     DCR    B        ; Count down
  1318.     JNZ    COMP
  1319.     RET
  1320.  
  1321. ;*
  1322. ;* COPY FROM HL TO DE FOR B BYTES
  1323. ;*
  1324. SDMOVE:
  1325.     MOV    A,M        ; Copy
  1326.     STAX    D
  1327.     INX    H        ; Pt to next
  1328.     INX    D
  1329.     DCR    B        ; Count down
  1330.     JNZ    SDMOVE
  1331.     RET
  1332.  
  1333. ;*
  1334. ;*  BUFFERS
  1335. ;*
  1336. HOLD:
  1337.     DS    2        ; Exchange hold buffer for fcb's
  1338. PTPTR:
  1339.     DS    2        ; Pointer pointer
  1340. PTDIR:
  1341.     DS    2        ; Directory pointer
  1342. I:
  1343.     DS    2        ; Indexes for sort
  1344. J:
  1345.     DS    2
  1346. JG:
  1347.     DS    2
  1348. N:
  1349.     DS    2        ; Number of elements to sort
  1350. GAP:
  1351.     DS    2        ; Binary gap size
  1352.  
  1353. TFCB:
  1354.     DS    2        ; Address of temporary fcb
  1355. DSTART:
  1356.     DS    2        ; Pointer to first directory entry
  1357. FCOUNT0:
  1358.     DS    2        ; Total number of files/number of selected files
  1359.  
  1360. BLKSHF:
  1361.     DB    0        ; Block shift factor
  1362. BLKMSK:
  1363.     DB    0        ; Block mask
  1364. BLKMAX:
  1365.     DW    0        ; Max number of blocks
  1366. DIRMAX:
  1367.     DW    0        ; Max number of directory entries
  1368. SELFLG:
  1369.     DB    0        ; File attribute flag
  1370. ORDER:
  1371.     DW    0        ; Pointer to order table
  1372. DIRBUF:
  1373.     DW    0        ; Pointer to directory
  1374.  
  1375. ;    END
  1376. ;
  1377. ; Buffers
  1378. ;
  1379. COUNT:    DS    1        ; Counter used in display
  1380. FCOUNT:    DS    2        ; Number of files displayed
  1381. LCOUNT:    DS    1        ; Line counter
  1382. TOTCOUNT: DS    2        ; Total of sizes of all files
  1383. BLS:    DS    1        ; Block shift factor
  1384. LINES:    DS    2        ; Lines to be displayed
  1385. DIRBEG:    DS    2        ; Beginning of directory area
  1386. DIREND:    DS    2        ; End of directory area
  1387.  
  1388. ;    END
  1389. ;
  1390. ; SYSLIB Module Name:  SDIR04
  1391. ; Author:  Richard Conn
  1392. ; Part of SYSLIB3 SDIR Series
  1393. ; SYSLIB Version Number:  3.0
  1394. ; Module Version Number:  1.4
  1395. ; Module Entry Points:
  1396. ;    FSIZE
  1397. ; Module External References:
  1398. ;
  1399. ;
  1400.  
  1401. ;    INCLUDE SDIRHDR.LIB
  1402.  
  1403. ;*
  1404. ;*  COMPUTE SIZE OF FILE WHOSE LAST EXTENT IS POINTED TO BY HL
  1405. ;*    FILE SIZE IS RETURNED IN DE IN K
  1406. ;*  NOTE THAT THE ROUTINE DPARAMS MUST HAVE BEEN CALLED BEFORE THIS ROUTINE
  1407. ;*    IS USED
  1408. ;*
  1409. FSIZE:
  1410.     PUSH    B        ; Save regs
  1411.     PUSH    H
  1412.     PUSH    PSW
  1413.     LXI    D,12        ; Point to extent
  1414.     DAD    D
  1415.     MOV    E,M        ; Get extent #
  1416.     MVI    D,0
  1417.     INX    H        ; S1
  1418.     INX    H        ; S2 is the module number (512 k)
  1419.     MOV    A,M        ; Get module #
  1420.     ORA    A        ; Reset carry
  1421.     RAL
  1422.     RAL
  1423.     RAL
  1424.     RAL
  1425.     RAL            ; * 32 extents
  1426.     ORA    E
  1427.     MOV    E,A        ; Add to e
  1428.     JNC    FS0        ; Check high order bit
  1429.     INR    D        ; If carry
  1430. FS0:    INX    H        ; Hl pts to record count field
  1431.     MOV    A,M        ; Get record count of last extent
  1432.     XCHG
  1433.     DAD    H        ; Number of extents times 16k
  1434.     DAD    H
  1435.     DAD    H
  1436.     DAD    H
  1437.     XCHG            ; Total size of previous extents in de
  1438.     LXI    H,BLKMSK
  1439.     ADD    M        ; Round last extent to block size
  1440.     RRC
  1441.     RRC            ; Convert from records to k
  1442.     RRC
  1443.     ANI    1FH
  1444.     MOV    L,A        ; Add size of last extent to total of previous
  1445.                 ; extents
  1446.     MVI    H,0        ; Hl=size of last extent, de=total of previous
  1447.                 ; extents
  1448.     DAD    D        ; Hl=total file size in blocks
  1449.     LDA    BLKMSK        ; Get records/blk-1
  1450.     RRC
  1451.     RRC            ; Convert to k/blk
  1452.     RRC
  1453.     ANI    1FH
  1454.     CMA            ; Use to finish rounding
  1455.     ANA    L
  1456.     MOV    L,A        ; Hl now equals the size of the file in k
  1457.                 ; increments
  1458.     XCHG            ; De=file size in k
  1459.     POP    PSW        ; Restore regs
  1460.     POP    H
  1461.     POP    B
  1462.     RET
  1463.  
  1464.     END
  1465.