home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / lambda / soundpot / p / sap50.lbr / SAP45.AZM / SAP45.ASM
Encoding:
Assembly Source File  |  1993-10-25  |  19.8 KB  |  1,009 lines

  1. ; SAP v45 -- Sort & Pack Directory 06/28/86
  2. ;
  3.     ASEG        ; Needed for M80, ignore error if using MAC
  4. ;
  5. ; THIS PROGRAM READS THE DISK DIRECTORY TRACKS, SORTS THEM ALPHABETICALLY
  6. ; THEN REPLACES THEM ON THE DISK.  ALL UNUSED OR ERASED AREAS ON THE DI-
  7. ; RECTORY TRACK ARE REFORMATTED WITH CONTINUOUS 'E5' CHARACTERS.  (THIS
  8. ; ERASES PREVIOUS FILE NAMES WHICH HAVE BEEN DEACTIVATED.)  SORTING THE
  9. ; DIRECTORY IN THIS MANNER OFFERS MANY ADVANTAGES.  SOME OF THEM ARE:
  10. ;
  11. ;    1)  ALLOWS 'DIR' TO SHOW AN ALPHABETIZED LISTING
  12. ;    2)  ELIMINATES POTENTIAL PROBLEMS WITH "UNERASE" PROGRAMS
  13. ;    3)  SPEEDS UP ACCESS VIA 'SD' AND OTHER SPECIAL PROGRAMS
  14. ;    4)  ASSISTS ON WORKING DIRECTLY ON THE DISK WITH 'DU', ETC.
  15. ;    5)  REMOVES FILES FROM THE DISK SOMEBODY ELSE COULD RECOVER
  16. ;    6)  OPTIONALLY ERASES ALL FILES OF ZERO LENGTH (EXCEPT THOSE
  17. ;        STARTING WITH '-' FOR CATALOG USE WITH MAST.CAT)
  18. ;
  19. ;                - Notes by Irv Hoff W6FFC
  20. ;
  21. ;=======================================================================
  22. ;
  23. NO    EQU    0
  24. YES    EQU    NOT NO
  25. ;
  26. ;=======================================================================
  27. ;
  28. ; User-customizable options:
  29. ;
  30. ONLY22    EQU    YES        ; Set this to YES if SAP will be running ONLY
  31.                 ; Under CP/M v2.2.  If not sure, set to NO.
  32.  
  33. ONLY14    EQU    NO        ; Set this to YES if SAP will be running ONLY
  34.                 ; Under CP/M v1.4.  If not sure, set to NO.
  35.  
  36. CPMONLY    EQU    YES        ; Set this to YES if SAP will be running ONLY
  37.                 ; Under CP/M, either v1.4 or 2.2   If possi-
  38.                 ; Bility exists that SAP might be executed
  39.                 ; Under MP/M or CP/M+, set to NO.
  40.  
  41. DELZRO    EQU    YES        ; Set this to YES to cause SAP to delete all
  42.                 ; Zero-length files if SAVDASH is NO, or to delete
  43.                 ; All zero-length files not beginning with "-" if
  44.                 ; SAVDASH is YES.
  45.  
  46. SAVDASH    EQU    NO        ; Set this to YES and DELZRO to YES to cause SAP to
  47.                 ; Delete all zero-length files not beginning with
  48.                 ; "-" (as in SAP40).  Set this to NO to not check
  49.                 ; Filenames before deleting zero-length files (if
  50.                 ; DELZRO is set YES).
  51.  
  52. USE8080    EQU    NO        ; Set this to yes to be 8080 compatible and foolish.
  53.  
  54. USEZ80    EQU    YES        ; Set this to yes to be efficient with Z80 op codes.
  55. ;
  56. ;        End of user-selected options
  57. ;=======================================================================
  58.  
  59. ;
  60. ; Various system equates
  61. ;
  62. UNSPECI    EQU    NOT (ONLY22 OR ONLY14)
  63.  
  64.      IF    ONLY22 AND ONLY14
  65.     ERROR    'you must set either only22 or only14 to yes, not both'
  66.      ENDIF
  67.  
  68.      IF    USE8080    AND USEZ80
  69.     ERROR    'you can not pick both use8080 and useZ80'
  70.      ENDIF
  71.  
  72.      IF    NOT (USE8080 OR    USEZ80)
  73.     ERROR    'you must pick either use8080 or useZ80'
  74.      ENDIF
  75.  
  76. BYEBYE    EQU    0000H        ; BDOS warm boot vector
  77. BDOS    EQU    0005H
  78. PRINT    EQU    9        ; BDOS print string function
  79. GETDSK    EQU    25        ; BDOS "get disk #" function
  80. SELDRV    EQU    14        ; BDOS select drive function
  81. VERNO    EQU    12        ; BDOS CP/M version number function
  82.  
  83. VCTRLEN    EQU    53        ; Length of BIOS jump vectors
  84. DPBLEN    EQU    15        ; Size of CP/M 2.2 disk parameter block
  85. FCB    EQU    5CH        ; Addr of default CP/M file control block
  86. ENTRYLEN EQU    32        ; Length of directory entry on disk
  87.  
  88. CR    EQU    0DH
  89. LF    EQU    0AH
  90. EOS    EQU    '$'        ; BDOS fcn #9, end of string marker
  91.  
  92. ;
  93. ;=========================================================================
  94. ;
  95.  
  96.     ORG    100H
  97.  
  98. ;
  99. ; Obtain BIOS vectors
  100. ;
  101.     LXI    D,WBOOT        ; Destination
  102.     LHLD    0001H        ; Source
  103.  
  104.      IF    USE8080
  105.     MVI    B,VCTRLEN    ; Length
  106.     CALL    MOVE
  107.      ENDIF
  108.  
  109.      IF    USEZ80
  110.     LXI    B,VCTRLEN
  111.     DB    0EDH,0B0H    ; LDIR Z80 op code
  112.      ENDIF
  113.  
  114.     LXI    SP,STACK    ; Use our own stack
  115.     MVI    C,PRINT
  116.     LXI    D,IDENTITY    ; Tell user who we are
  117.     CALL    BDOS
  118.  
  119.      IF    UNSPECI
  120.     MVI    C,VERNO        ; Check for CP/M ver 2.2
  121.     CALL    BDOS
  122.      ENDIF
  123.  
  124.      IF    UNSPECI    AND (NOT CPMONLY)
  125.     DCR    H        ; H=1 for MPM
  126.     JNZ    NOTMPM        ; Exit if MPM, we can't use it
  127.  
  128. BADOS:    MVI    C,PRINT
  129.     LXI    D,BADOPSYS    ; Tell user can't work with MPM or CP/M 3.0
  130.     CALL    BDOS
  131.     JMP    BYEBYE
  132.  
  133. NOTMPM:    MOV    A,L        ; Hl = 0022h if CP/M ver 2.2
  134.     CPI    30H        ; Check for MPM or CP/M 3.0
  135.     JNC    BADOS        ; Exit if CP/M 3.0, we can't use it
  136.      ENDIF            ; Unspeci and (not cpmonly)
  137.  
  138.      IF    UNSPECI
  139.     STA    VERFLG        ; Store the version
  140.      ENDIF
  141. ;
  142. ;
  143. ;=======================================================================
  144. ;
  145. ;            main program routine
  146. ;
  147. SAP:    CALL    SETUP
  148.     CALL    RDDIR
  149.     CALL    CLEAN
  150.     CALL    SORT
  151.     CALL    PACK
  152.     CALL    WRDIR
  153.     MVI    C,PRINT
  154.     LXI    D,FINISHED
  155.     CALL    BDOS
  156.     JMP    BYEBYE
  157. ;
  158. ;
  159. ;=======================================================================
  160. ;
  161. ;               subroutines
  162. ;
  163. ; Setup for selecting drive and loading disk parameter block
  164. ;
  165. SETUP:    LDA    FCB
  166.     DCR    A
  167.     JP    SETUP1        ; Exit if disk drive mentioned
  168.     MVI    C,GETDSK    ; Otherwise get current default drive
  169.     CALL    BDOS
  170.  
  171. SETUP1:    MOV    C,A
  172.     CALL    SELDSK        ; Returns addr of DPH in HL for selected drive.
  173.  
  174.      IF    UNSPECI
  175.     LDA    VERFLG        ; If CP/M 1.4
  176.     ORA    A
  177.     JNZ    CPM22        ; If not 1.4, then do it the 2.2 way
  178.                 ; Else must be 1.4 since not MP/M
  179.      ENDIF
  180. ;
  181. ; CP/M 1.4 routine
  182. ;
  183.      IF    ONLY14 OR UNSPECI
  184. CPM14:    LHLD    BDOS+1
  185.     MVI    L,0
  186.     MVI    A,(JMP)
  187.     STA    RECTRN
  188.     PUSH    H
  189.     LXI    D,15        ; Rectran offset from BDOS in CP/M 1.4
  190.     DAD    D
  191.     SHLD    RECTRN+1
  192.     POP    H
  193.     LXI    D,3AH        ; Offset from BDOS to 1.4 dpb
  194.     DAD    D
  195.     MVI    D,0        ; Note that D=0 for this whole thing
  196.     MOV    E,M
  197.  
  198.      IF    USE8080
  199.     XCHG
  200.     SHLD    SPT
  201.     XCHG
  202.      ENDIF
  203.  
  204.      IF    USEZ80
  205.     .Z80
  206.     LD    (SPT),DE
  207.     .8080
  208.      ENDIF
  209.  
  210.     INX    H
  211.     MOV    E,M
  212.  
  213.      IF    USE8080
  214.     XCHG
  215.     SHLD    DRM
  216.     XCHG
  217.      ENDIF
  218.  
  219.      IF    USEZ80
  220.     .Z80
  221.     LD    (DRM),DE
  222.     .8080
  223.      ENDIF
  224.  
  225.     LXI    B,5        ; Offset to systrk field
  226.     DAD    B
  227.     MOV    E,M
  228.     XCHG
  229.     SHLD    SYSTRK
  230.  
  231.     JMP    CALCSPACE    ; Determine size of directory
  232.      ENDIF            ; ONLY14 OR UNSPECI
  233.  
  234. ;
  235. ; CP/M 2.2 routine
  236. ;
  237.      IF    ONLY22 OR UNSPECI
  238. CPM22:    MOV    E,M
  239.     INX    H
  240.     MOV    D,M
  241.  
  242.      IF    USE8080
  243.     XCHG
  244.     SHLD    RECTBL
  245.     XCHG
  246.      ENDIF
  247.  
  248.      IF    USEZ80
  249.     .Z80
  250.     LD    (RECTBL),DE
  251.     .8080
  252.      ENDIF
  253.  
  254.     LXI    D,9        ; Offset to dpb within header
  255.     DAD    D        ; Returned by seldsk in CP/M 2.2
  256.     MOV    E,M        ; Get adrress of dpb
  257.     INX    H
  258.     MOV    D,M
  259.     XCHG            ; Now HL = addr of real dpb
  260.     MOV    E,M
  261.     INX    H
  262.     MOV    D,M        ; Now DE = spt
  263.  
  264.      IF    USE8080
  265.     XCHG
  266.     SHLD    SPT
  267.     XCHG
  268.      ENDIF
  269.  
  270.      IF    USEZ80
  271.     .Z80
  272.     LD    (SPT),DE
  273.     .8080
  274.      ENDIF
  275.  
  276.     LXI    D,6        ; Offset to drm within dpb
  277.     DAD    D
  278.     MOV    E,M
  279.     INX    H
  280.     MOV    D,M        ; Now DE = DRM
  281.  
  282.      IF    USE8080
  283.     XCHG
  284.     SHLD    DRM
  285.     XCHG
  286.      ENDIF
  287.  
  288.      IF    USEZ80
  289.     .Z80
  290.     LD    (DRM),DE
  291.     .8080
  292.      ENDIF
  293.  
  294.     LXI    D,5        ; Offset to SYSTRK
  295.     DAD    D
  296.     MOV    E,M
  297.     INX    H
  298.     MOV    D,M        ; Now DE = SYSTRK
  299.     XCHG
  300.     SHLD    SYSTRK        ; Now drop into calcspace
  301.      ENDIF            ; ONLY22 OR UNSPECI
  302.  
  303. ;
  304. ;======================================================================
  305. ;
  306. ; Determine if directory will fit in available memory.
  307. ; if not, determine how much of it will.
  308. ;
  309. CALCSPACE:
  310.                 ; First compute amount of free space
  311.                 ;   in 128-byte records
  312.     LHLD    BDOS+1        ; Get addr of 1st byte of BDOS
  313.     LXI    D,BUF        ; Get addr of 1st byte of buffer
  314.  
  315. ;     IF    USE8080
  316. ;    CALL    SUBDE        ; Now HL = # free bytes for buffer
  317. ;     ENDIF
  318. ;
  319. ;     IF    USEZ80
  320. ;    ORA    A        ; clear carry
  321. ;    DB    0EDH,52H    ; A SBC HL,DE Z80 opcode
  322. ;     ENDIF
  323. ;
  324. ; Since we know that buf starts on an even page boundary, E=0, so just go:
  325. ;
  326.     MOV    A,H
  327.     SUB    D
  328.     MOV    H,A        ; Now HL = HL - DE,  (since E=0).
  329.  
  330.     MOV    A,L        ; Compute HL = HL/128 by . . .
  331.     RAL            ; Carry flag = high bit of L
  332.     MOV    A,H        ; No affect on flags
  333.     RAL            ; Move carry flag into low bit of A
  334.                 ; Now carry flag = high bit of H
  335.     MOV    L,A        ; No affect on flags
  336.     MVI    A,0        ; No affect on flags
  337.     RAL            ; Move carry flag into low bit of A
  338.     MOV    H,A        ; Now HL = HL/128
  339.  
  340.     SHLD    NUMDIRRECS    ; Assume that we need them all until proven false
  341.  
  342.                 ; Now determine how many 128-byte records the directory takes up
  343.     LHLD    DRM        ; Get # 32-byte directory entries . . .
  344.     INX    H        ; Relative to 1.
  345.     SHLD    NUMFNAMES    ; Save as a more convenient count
  346.     CALL    ROTRHL        ; Divide by 2
  347.     CALL    ROTRHL        ; Divide by 2.    now hl = # 128-byte records needed
  348.  
  349.                 ; Now see if it all fits in available memory
  350.     XCHG            ; Now DE = needed records
  351.     LHLD    NUMDIRRECS    ; Now HL = available space in records
  352.  
  353.      IF    USE8080
  354.     CALL    SUBDE        ; Now HL = HL-DE
  355.      ENDIF
  356.  
  357.      IF    USEZ80
  358.     ORA    A        ; Clear carry
  359.     DB    0EDH,52H    ; A SBC HL,DE Z80 opcode
  360.      ENDIF
  361.  
  362.     JC    NOMEM        ; If need > space then process exception
  363.     XCHG            ; Now HL = need
  364.     SHLD    NUMDIRRECS    ; Save as number records we'll process
  365.     RET
  366.  
  367. NOMEM:    LHLD    NUMDIRRECS    ; Recall available space (in records)
  368.     DAD    H        ; Mult by 2.
  369.     DAD    H        ; Now HL = available space (in directory entries)
  370.     SHLD    NUMFNAMES    ; Save as new number of directory entries
  371.  
  372.     MVI    C,PRINT
  373.     LXI    D,LACKMEMORY    ; Tell user we'll do as much as we can
  374.     JMP    BDOS        ; BDOS will return for me
  375.  
  376. ;
  377. ;==================================================================
  378. ;
  379. ; Entry point to routines for directory read.
  380. ;
  381. RDDIR:    MVI    C,PRINT
  382.     LXI    D,READING    ; Tell user we're about to read directory.
  383.     CALL    BDOS
  384.     XRA    A        ; Zero A to indicate directory read.
  385.     JMP    DODIR        ; Enter main directory routines
  386. ;
  387. ; Entry point to routines for directory write.
  388. ;
  389. WRDIR:    LDA    NOSWAP
  390.     ORA    A        ; Is noswap = 0?
  391.     JNZ    WRDIR1        ; If not then not previously sorted
  392.     MVI    C,PRINT
  393.     LXI    D,PREVIOUS    ; Tell user no swaps were needed
  394.     CALL    BDOS
  395.  
  396. WRDIR1:    MVI    C,PRINT
  397.     LXI    D,WRITING    ; Tell user we're now writing out the directory
  398.     CALL    BDOS
  399.  
  400.     MVI    A,1        ; A = 1 signals writes versus reads.
  401.                 ; Fall into dodir.
  402. ;
  403. ;===================================================================
  404. ;
  405. ; This is the main read/write directory routine.
  406. ;
  407. DODIR:    STA    WRFLAG        ; Save read/write flag
  408.     LHLD    SYSTRK        ; Get track num of directory
  409.     SHLD    TRACK        ; Save as current track
  410.     MOV    B,H
  411.     MOV    C,L
  412.     CALL    SETTRK
  413.     LXI    H,0
  414.     SHLD    RECORD        ; Set current record to 0
  415.     LHLD    NUMDIRRECS    ; Get number of 128-byte records to process
  416.     SHLD    DIRCNT        ; Save in a loop counter
  417.     LXI    H,BUF        ; Start at buf . . .
  418.     SHLD    ADDR        ; For dma address
  419.  
  420. DIRLOP:    LHLD    RECORD        ; Get current record
  421.     INX    H        ; Bump to next
  422.     XCHG
  423.     LHLD    SPT        ; Get num records per track
  424.  
  425.      IF    USE8080
  426.     CALL    SUBDE        ; Now HL = HL-DE
  427.      ENDIF
  428.  
  429.      IF    USEZ80
  430.     XRA    A        ; Clear carry (and reg A)
  431.     DB    0EDH,52H    ; A SBC HL,DE Z80 opcode
  432.      ENDIF
  433.  
  434.     XCHG
  435.     JNC    NOTROV        ; If SPT >= record then we're ok
  436.                 ; Else we drop into track bumping
  437. ;
  438. ; Track overflow, bump to next
  439. ;
  440.     LHLD    TRACK
  441.     INX    H
  442.     SHLD    TRACK
  443.     MOV    B,H
  444.     MOV    C,L
  445.     CALL    SETTRK
  446.     LXI    H,1        ; Rewind record number
  447.  
  448. NOTROV:    SHLD    RECORD
  449.     MOV    B,H
  450.     MOV    C,L
  451.     LHLD    RECTBL
  452.     XCHG
  453.     DCX    B
  454.     CALL    RECTRN
  455.     MOV    B,H
  456.     MOV    C,L
  457.  
  458.      IF    UNSPECI
  459.     LDA    VERFLG
  460.     ORA    A
  461.     CNZ    SETREC        ; If CP/M 2.2 then call setrec
  462.      ENDIF
  463.  
  464.      IF    ONLY22
  465.     CALL    SETREC
  466.      ENDIF
  467.  
  468.     LHLD    ADDR
  469.     MOV    B,H        ; Set up dma address
  470.     MOV    C,L
  471.     CALL    SETDMA
  472.     LDA    WRFLAG        ; Time to figure out . . .
  473.     ORA    A        ; If we are reading . . .
  474.     JNZ    DWRT        ; Or writing
  475. ;
  476. ; read
  477. ;
  478.     CALL    READ
  479.     ORA    A        ; Test flags on read
  480.     JZ    MORE        ; If z then ok, else fall through to read error
  481. ;
  482. ; Come here if we get a read error
  483. ;
  484.     MVI    C,PRINT
  485.     LXI    D,RDERR
  486.     CALL    BDOS
  487.     JMP    BYEBYE
  488. ;
  489. ; Write
  490. ;
  491. DWRT:    MVI    C,1        ; For CP/M 2.2 deblocking bios's
  492.     CALL    WRITE
  493.     ORA    A        ; Test flags on write
  494.     JZ    MORE        ; If z then ok, else fall through to write error
  495. ;
  496. ; Come here if we get a write error
  497. ;
  498.     MVI    C,PRINT
  499.     LXI    D,WRTERR
  500.     CALL    BDOS
  501.     JMP    BYEBYE
  502.  
  503. ;
  504. ; Good read or write
  505. ;
  506. MORE:    LHLD    ADDR        ; Bump DMA address for next pass
  507.     LXI    D,80H        ; By 128 bytes = 1 record.
  508.     DAD    D
  509.     SHLD    ADDR
  510.     LHLD    DIRCNT        ; Countdown entries
  511.     DCX    H
  512.     SHLD    DIRCNT
  513.     MOV    A,H        ; Test for zero left
  514.     ORA    L
  515.     JNZ    DIRLOP        ; Loop till zero
  516.     RET            ; And then we're done.
  517. ;
  518. ;====================================================================
  519. ;
  520. ; Clean out all of the erased file entries to all E5's.
  521. ;
  522. CLEAN:    LXI    H,0        ; i = 0
  523.  
  524. CLNLOP:    PUSH    H        ; Save index i
  525.     DAD    H
  526.     DAD    H
  527.     DAD    H
  528.     DAD    H
  529.     DAD    H        ; Compute HL = 32 * i
  530.     LXI    D,BUF
  531.     DAD    D        ; Now HL = buf + 32 * i = addr of deleted status
  532.     MOV    A,M        ; Get user area/deleted status byte
  533.     CPI    0E5H        ; Is this file deleted ?
  534.  
  535.      IF    DELZRO
  536.     JZ    FILLE5        ; If marked deleted then fill it w/E5's
  537.     LXI    B,12
  538.     DAD    B        ; Hl = hl + 12
  539.     MOV    A,M        ; Check extent field
  540.     ORA    A
  541.     JNZ    CLBUMP        ; Skip if not extent 0
  542.     INX    H        ; Point to record count field
  543.     INX    H
  544.     MOV    A,M        ; Get s2 byte (extended rc)
  545.     ANI    0FH        ; For CP/M 2.2, 0 for CP/M 1.4
  546.     MOV    B,A
  547.     INX    H
  548.     MOV    A,M        ; Check record count field
  549.     ORA    B
  550.     JNZ    CLBUMP        ; Jump if non-zero
  551.      ENDIF            ; Delzro
  552.  
  553.      IF    DELZRO AND SAVDASH
  554.     LXI    B,65522        ; -14 = 65536 - 14 = 65522 in two's complement
  555.     DAD    B        ; Now HL = addr of 1st char of file name
  556.     MOV    A,M        ; Get first character of filename
  557.     DCX    H        ; Point back to 1st byte of directory entry
  558.     CPI    '-'        ; Mast.cat catalog programs have 0 length files
  559.     JZ    CLBUMP        ; W/names that start with '-', don't delete
  560.      ENDIF
  561.  
  562.      IF    NOT DELZRO
  563.     JNZ    CLBUMP        ; If not a deleted file then skip it
  564.      ENDIF
  565.  
  566. FILLE5:    MVI    B,ENTRYLEN    ; Number of bytes to clear
  567.  
  568.     MVI    A,0E5H        ; Load up char to replicate
  569. FILLOP:    MOV    M,A        ; Make it all E5's
  570.     INX    H
  571.  
  572.      IF    USE8080
  573.     DCR    B
  574.     JNZ    FILLOP
  575.      ENDIF
  576.  
  577.      IF    USEZ80
  578.     .Z80
  579.     DJNZ    FILLOP
  580.     .8080
  581.      ENDIF
  582.  
  583. CLBUMP:    POP    D        ; Recall index i
  584.     INX    D        ; DE = i + 1
  585.     LHLD    NUMFNAMES    ; HL = count of filenames
  586.  
  587.      IF    USE8080
  588.     CALL    SUBDE        ; Now hl = hl - de
  589.      ENDIF
  590.  
  591.      IF    USEZ80
  592.     ORA    A        ; Clear carry
  593.     DB    0EDH,52H    ; A sbc hl,de Z80 opcode
  594.      ENDIF
  595.  
  596.     XCHG            ; HL = i
  597.     JNZ    CLNLOP        ; Loop till all cleaned (i.e. i = numfnames)
  598.     RET
  599.  
  600. ;
  601. ;==============================================================
  602. ;
  603. ; Sort the directory
  604. ;
  605. SORT:    XRA    A
  606.     STA    NOSWAP        ; Zero the flag in case already sorted
  607.     MVI    C,PRINT
  608.     LXI    D,SORTING
  609.     CALL    BDOS
  610. ;
  611. ; Shell-Metzner sort
  612. ;
  613.     LHLD    NUMFNAMES    ; Get # file names to process
  614.     SHLD    SNUMRECW
  615. ;
  616. ; Now divide # of fields by 2
  617. ;
  618. DIVIDE:    LHLD    SNUMRECW    ; Get value
  619.     CALL    ROTRHL        ; Divide by 2
  620.     SHLD    SNUMRECW    ; Save result
  621.     MOV    A,L        ; If snumrecw = 0 . . .
  622.     ORA    H        ; Then . . .
  623.     RZ            ; We're done
  624. ;
  625. ; Not done yet
  626. ;
  627. NOTDONE:
  628.     XCHG            ; DE = snumrecw
  629.     LHLD    NUMFNAMES    ; Get # file names to process
  630.  
  631.      IF    USE8080
  632.     MOV    A,L        ; This is SUBDE put inline for speed
  633.     SUB    E
  634.     MOV    L,A
  635.     MOV    A,H
  636.     SBB    D
  637.     MOV    H,A
  638.      ENDIF
  639.  
  640.      IF    USEZ80
  641.     ORA    A        ; Clear carry
  642.     DB    0EDH,52H    ; A sbc hl,de Z80 opcode
  643.      ENDIF
  644.  
  645.     SHLD    SRECLEN
  646.     LXI    H,1
  647.     SHLD    SSORTV1
  648.     SHLD    SSTADR
  649.     DCR    L        ; Now HL = 0
  650.  
  651.     XCHG            ; Now HL = old DE, DE = 0
  652.     DAD    H        ; Now take advantage of entrylen = 32 = 2 ^ 5
  653.     DAD    H
  654.     DAD    H
  655.     DAD    H
  656.     DAD    H        ; Now HL = old DE * 32
  657.  
  658.     SHLD    SSORTV2
  659.     XCHG
  660.     LXI    H,BUF
  661.  
  662. NDONE2:    SHLD    SSORTV4
  663.     SHLD    SSORTV3
  664.     XCHG
  665.     DAD    D
  666.     XCHG
  667.  
  668. COMPARE:
  669.     MVI    B,ENTRYLEN
  670.  
  671. COMPAR1:
  672.     MOV    A,M
  673.     ANI    7FH
  674.     MOV    C,A        ; C = (HL) AND 7Fh
  675.     LDAX    D
  676.     ANI    7FH        ; A = (DE) AND 7Fh
  677.     SUB    C        ; Form A - C == (DE) - (HL)
  678.     JNZ    NOTEQU
  679.     INX    H
  680.     INX    D
  681.  
  682.      IF    USE8080
  683.     DCR    B
  684.     JNZ    COMPAR1
  685.      ENDIF
  686.  
  687.      IF    USEZ80
  688.     .Z80
  689.     DJNZ    COMPAR1
  690.     .8080
  691.      ENDIF
  692. ;
  693. ; Either drop into here from compare or jump in from switch or NOTEQU
  694. ;
  695. NOSWITCH:
  696.     LHLD    SSTADR
  697.     INX    H
  698.     SHLD    SSTADR
  699.     SHLD    SSORTV1
  700.     XCHG
  701.     LHLD    SRECLEN
  702.     MOV    A,L
  703.     SUB    E
  704.     MOV    A,H
  705.     SBB    D
  706.     JC    DIVIDE
  707.     LHLD    SSORTV4
  708.     LXI    D,ENTRYLEN
  709.     DAD    D
  710.     XCHG
  711.     LHLD    SSORTV2
  712.     XCHG
  713.     JMP    NDONE2
  714.  
  715. ;
  716. ; The condition at NOTEQU has to be changed for descending sort.
  717. ; Note that on entry B contains the number of chars we need to move.
  718. ;
  719. NOTEQU:    JNC    NOSWITCH    ; If (DE) > (HL) then don't switch
  720.     MVI    A,1
  721.     STA    NOSWAP        ; Mark that we've switched something once
  722.  
  723. SWITCH:    MOV    C,M
  724.     LDAX    D
  725.     MOV    M,A        ; (HL) <== (DE)
  726.     MOV    A,C
  727.     STAX    D        ; (HL) ==> (DE)
  728.     INX    H        ; Bump both . . .
  729.     INX    D        ; Pointers
  730.  
  731.      IF    USE8080
  732.     DCR    B
  733.     JNZ    SWITCH
  734.      ENDIF
  735.  
  736.      IF    USEZ80
  737.     .Z80
  738.     DJNZ    SWITCH
  739.     .8080
  740.      ENDIF
  741.  
  742.      IF    USE8080
  743.     LHLD    SNUMRECW
  744.     MOV    A,H        ; These first few instructions . . .
  745.     CMA
  746.     MOV    D,A
  747.     MOV    A,L
  748.     CMA
  749.     MOV    E,A        ; Just form HL = - DE - 1
  750.     LHLD    SSORTV1
  751.     DAD    D        ; Now HL = HL - DE - 1
  752.      ENDIF
  753.  
  754.      IF    USEZ80
  755.     LHLD    SNUMRECW
  756.     XCHG            ; DE = snumrecw
  757.     LHLD    SSORTV1
  758.     STC            ; Set carry flag
  759.     DB    0EDH,52H    ; An SBC HL,DE    Z80 opcode
  760.      ENDIF
  761.  
  762.     JNC    NOSWITCH
  763.     INX    H
  764.     SHLD    SSORTV1
  765.     LHLD    SSORTV3
  766.     XCHG
  767.     LHLD    SSORTV2
  768.     MOV    A,E
  769.     SUB    L
  770.     MOV    L,A
  771.     MOV    A,D
  772.     SBB    H
  773.     MOV    H,A
  774.     SHLD    SSORTV3
  775.     JMP    COMPARE
  776.  
  777. ;
  778. ;=======================================================================
  779. ;
  780. ; Pack the directory entries.
  781. ;
  782. PACK:    LXI    H,0        ; I = 0
  783.     LXI    B,BUF+9        ; This is a constant taken out of the loop
  784.  
  785. PACK1:    PUSH    H        ; Save index i
  786.     DAD    H
  787.     DAD    H
  788.     DAD    H
  789.     DAD    H
  790.     DAD    H        ; Compute HL = 32 * i
  791.     DAD    B        ; Now HL = buf + 9 + 32 * i = addr of file type
  792.  
  793.     MOV    A,M        ; Jump if filetype not 'x??'
  794.     SUI    '0'
  795.     JC    PACK2
  796.     CPI    10
  797.     JNC    PACK2
  798.  
  799.      IF    USE8080
  800.     STA    J        ; Save value of x
  801.      ENDIF
  802.  
  803.      IF    USEZ80
  804.     DB    08H        ; A Z80 opcode:  EX AF,AF'
  805.      ENDIF
  806.  
  807.     INX    H        ; Make sure file type is .x$$
  808.     MOV    A,M
  809.     CPI    '$'
  810.     JNZ    PACK2
  811.     INX    H
  812.     MOV    A,M
  813.     CPI    '$'
  814.     JNZ    PACK2
  815.  
  816.     INX    H        ; Bump to extent number field
  817.  
  818.      IF    USE8080
  819.     LDA    J        ; Recall x
  820.      ENDIF
  821.  
  822.      IF    USEZ80
  823.     DB    08H        ; A Z80 opcode:  EX AF,AF'
  824.      ENDIF
  825.  
  826.     MOV    M,A        ; Set extent number to x
  827.     DCX    H
  828.     DCX    H
  829.     DCX    H        ; Point back to the x
  830.     MVI    M,'$'        ; Make file type .$$$ once again
  831.  
  832. PACK2:    POP    D        ; Recall index i
  833.     INX    D        ; DE = i + 1
  834.     LHLD    NUMFNAMES    ; HL = number of file names
  835.  
  836.      IF    USE8080
  837.     CALL    SUBDE        ; Now HL = HL-DE
  838.      ENDIF
  839.  
  840.      IF    USEZ80
  841.     ORA    A        ; Clear carry
  842.     DB    0EDH,52H    ; A SBC HL,DE Z80 opcode
  843.      ENDIF
  844.  
  845.     XCHG            ; Now HL = i
  846.     JNZ    PACK1        ; Loop until i = # file names process
  847.     RET
  848.  
  849. ;
  850. ;====================================================================
  851. ;
  852. ; Various Quickie Routines
  853. ;
  854. ; Divide HL by 2
  855. ;
  856. ROTRHL:    ORA    A        ; Clear carry
  857.     MOV    A,H
  858.     RAR
  859.     MOV    H,A
  860.     MOV    A,L
  861.     RAR
  862.     MOV    L,A
  863.     RET
  864.  
  865.      IF    USE8080
  866. ;
  867. ; Move utility subroutine
  868. ;
  869. MOVE:    MOV    A,M
  870.     STAX    D
  871.     INX    H
  872.     INX    D
  873.     DCR    B
  874.     JNZ    MOVE
  875.     RET
  876.  
  877. ;
  878. ; Utility subtraction subroutine:  HL = HL-DE
  879. ;
  880. SUBDE:    MOV    A,L
  881.     SUB    E
  882.     MOV    L,A
  883.     MOV    A,H
  884.     SBB    D
  885.     MOV    H,A
  886.     RET
  887.      ENDIF            ; Use8080
  888.  
  889. ;
  890. ;====================================================================
  891. ;
  892. ; Various messages
  893. ;
  894.  
  895. IDENTITY:
  896.     DB    CR,LF,'Sort and Pack Directory V'
  897.     DB    '45 06/28/86'
  898.     DB    CR,LF,EOS
  899.  
  900. READING:
  901.     DB    CR,LF,'---> Reading, ',0
  902.  
  903. SORTING:
  904.     DB    'Sorting, ',EOS
  905.  
  906. PREVIOUS:
  907.     DB    '(previously sorted) - ',EOS
  908.  
  909. WRITING:
  910.     DB    'Writing, ',EOS
  911.  
  912. FINISHED:
  913.     DB    'done'
  914.     DB    CR,LF,EOS
  915.  
  916. RDERR:
  917.     DB    '++ Read Error - no change made ++'
  918.     DB    CR,LF,EOS
  919.  
  920. WRTERR:
  921.     DB    '++ Write Error - '
  922.     DB    'directory left in unknown condition ++'
  923.     DB    CR,LF,EOS
  924.  
  925.      IF    UNSPECI    AND (NOT CPMONLY)
  926. BADOPSYS:
  927.     DB    CR,LF
  928.     DB    '++ SAP not useable with MP/M or CP/M 3.0 ++'
  929.     DB    CR,LF,EOS
  930.      ENDIF            ; Unspeci and (not cpmonly)
  931.  
  932. LACKMEMORY:
  933.     DB    '++ directory too large - '
  934.     DB    'SAP will process as much as possible. ++'
  935.     DB    CR,LF,EOS
  936.  
  937. ;
  938. ;====================================================================
  939. ;
  940. ; Data area
  941. ;
  942. VECTRS:    DS    VCTRLEN        ; Room for jump vectors (53 bytes)
  943.  
  944. WBOOT    EQU    VECTRS+3    ; Do not change these equates
  945. CSTS    EQU    VECTRS+6
  946. CI    EQU    VECTRS+9
  947. CO    EQU    VECTRS+12
  948. LO    EQU    VECTRS+15
  949. PO    EQU    VECTRS+18
  950. RI    EQU    VECTRS+21
  951. HOME    EQU    VECTRS+24
  952. SELDSK    EQU    VECTRS+27    ; Used
  953. SETTRK    EQU    VECTRS+30    ; Used
  954. SETREC    EQU    VECTRS+33    ; Used
  955. SETDMA    EQU    VECTRS+36    ; Used
  956. READ    EQU    VECTRS+39    ; Used
  957. WRITE    EQU    VECTRS+42    ; Used
  958. LSTS    EQU    VECTRS+45    ; Only in CP/M 2.2  (not used)
  959. RECTRN    EQU    VECTRS+48    ; Only in CP/M 2.2  (used)
  960.  
  961.      IF    UNSPECI
  962. VERFLG    EQU    VECTRS+45    ; Squeeze him in where he fits!
  963.      ENDIF
  964.  
  965. NUMDIRRECS EQU    VECTRS+46    ; Squeeze him in where he fits!
  966.  
  967. ;
  968. ; Disk parameter block variables
  969. ;
  970. SPT    EQU    VECTRS+0
  971. DRM    EQU    VECTRS+2
  972. SYSTRK    EQU    VECTRS+4
  973. RECTBL    EQU    VECTRS+6
  974. NUMFNAMES EQU    DRM        ; This is drm+1 = # direc entries after calcspace
  975.  
  976. ;
  977. ; The rest of the variables for reads/writes
  978. ;
  979. ADDR    EQU    VECTRS+8
  980. DIRCNT    EQU    VECTRS+10
  981. WRFLAG    EQU    VECTRS+12
  982. RECORD    EQU    VECTRS+13
  983. TRACK    EQU    VECTRS+15
  984.  
  985.      IF    USE8080
  986. J    EQU    VECTRS+17
  987.      ENDIF
  988.  
  989. ;
  990. ; The rest of the variables for sorting
  991. ;
  992. NOSWAP    EQU    VECTRS+8
  993. SRECLEN    EQU    VECTRS+9
  994. SSTADR    EQU    VECTRS+11
  995. SSORTV1    EQU    VECTRS+13
  996. SSORTV2    EQU    VECTRS+15
  997. SSORTV3    EQU    VECTRS+17
  998. SSORTV4    EQU    VECTRS+19
  999. SNUMRECW EQU    VECTRS+21
  1000.  
  1001.     DS    32          ; Minimum stack depth
  1002. EVEN    EQU    (($+255)/256)*256 ; Start buffer on even page, which
  1003.                   ;   also increases stack area greatly
  1004.     ORG    EVEN
  1005. STACK    EQU    $-2
  1006. BUF    EQU    $
  1007.  
  1008.     END
  1009.