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 / ENTERPRS / CPM / UTILS / S / SAPP20.LBR / SAPP20.ZZ0 / SAPP20.Z80
Text File  |  2000-06-30  |  32KB  |  1,283 lines

  1.     TITLE    'SAPP Sort & Pack Directory for CP/M 2.2 or 3.0'
  2. ;
  3. ;    ASEG            ; Needed for M80
  4. ;    .Z80            ; Needed for M80
  5. ;
  6. ;-----------------------------------------------------------------------
  7. ;
  8. ; SAPP v2.0 Sort & Pack Directory for CP/M 2.2 & 3.0
  9. ;  08/02/87        By George F. Reding
  10. ;        Based upon (and many routines from)
  11. ;        SAP v44 Sort & Pack program for CP/M 2.2
  12. ;        A Public Domain utility program.
  13. ;        Not to be sold (in whole or part).
  14. ;
  15. ;-----------------------------------------------------------------------
  16. ;
  17. ; 08/02/87  CP/M 2 bug was found; where the DMA pointer was
  18. ;   v2.0    not advanced, so the buffer under 2.2 was being
  19. ;        overwritten. Corrected with the move of 1 label
  20. ;        and addition of 1 label; e.g., DIRLOP & DIRLP1.
  21. ;        Thanks to David Bowerman, sysop of    Frog Hollow
  22. ;        RCPM System (604-937-0906),  for having located
  23. ;        the cause of the problem.  David then tested it
  24. ;        on disk with 250 of 256 directory entries used,
  25. ;        under CP/M 2.2 and all is now fine. <GFR>
  26. ;
  27. ; 07/13/87  Found that vers 1.8 clobbered the DE reg in the
  28. ;   v1.9    XBIOS2 thus causing SECTRAN function for CP/M 2
  29. ;        to not work properly.        <GFR>
  30. ;
  31. ; 06/21/87  Added Z80 & version tests and restored CP/M 2.2
  32. ;   v1.8    code so the program is usable under CP/M 2.2 or
  33. ;        3.0. Added adjustment for TPA size diffences so
  34. ;        this may be used, at user discretion when TPA's
  35. ;        are too low and/or maximum number of entries is
  36. ;        too large.     User options may now be set in the
  37. ;        COM file using DDT, SID, or SZAP if desired.
  38. ;                        <GFR>
  39. ;
  40. ; 06/15/87  Reinstated disk reset in new location after the
  41. ;   v1.7    current or specified drive is obtained. <GFR>
  42. ;
  43. ; 04/16/87  Removed reset disk function which forced a drive
  44. ;   v1.6    specification to be required for other drives.
  45. ;        Added check for second hard drive.    <GFR>
  46. ;
  47. ; 01/11/87  Modified use of relative jumps to ensure they're
  48. ;   v1.5    only used to optimize speed (faster if condition
  49. ;        is NOT met).  Now use alt reg in SWITCH routine.
  50. ;        Some more comments added.        <GFR>
  51. ;
  52. ; 12/10/86  Uses alt regs in COMPR1 and PRNTL routines.
  53. ;   v1.4                    <GFR>
  54. ;
  55. ; 11/15/86  Modified the program by removing some unused code
  56. ;   v1.3    and by utilizing z80 code anywhere possible.  Use
  57. ;        ZASM or other equivilent z80 assembler.
  58. ;                        <GFR>
  59. ;
  60. ; SAPP (for CP/M Plus) was created from SAP (for CP/M 1.4 or 2.2)
  61. ;
  62. ;-----------------------------------------------------------------------
  63. ;
  64. NO    EQU    0
  65. YES    EQU    NOT NO        ; For conditional assembly
  66. ;
  67. ; Version number and date
  68. ;
  69. VER    EQU    20        ; Version number
  70. VERM    EQU    08        ; Version month
  71. VERD    EQU    02        ; Version day
  72. VERY    EQU    87        ; Version year
  73. ;
  74. ; System equates
  75. ;
  76. BASE    EQU    0        ; Base of system (warm boot)
  77. BDOS    EQU    BASE+5        ; BDOS
  78. FCB    EQU    5CH        ; File control block
  79. ;
  80. DPB2OF    EQU    10        ; Offset to CP/M 2.2 DPB
  81. DPB2LN    EQU    15        ; Length of CP/M 2.2 DPB
  82. DPB3OF    EQU    12        ; Offset to CP/M 3.0
  83. DPB3LN    EQU    17        ; Length of CP/M 3.0
  84. ;
  85. ; BDOS functions
  86. ;
  87. CONOUF    EQU    2        ; Console output
  88. RDCBUF    EQU    10        ; Read console buffer
  89. RETVER    EQU    12        ; Return version number
  90. RESET    EQU    13        ; Reset disk
  91. GETDSK    EQU    25        ; Get current disk
  92. ;
  93. ; ASCII equates
  94. ;
  95. BEL    EQU    07H        ; Bell
  96. BS    EQU    08H        ; Backspace
  97. CR    EQU    0DH        ; Carriage return
  98. LF    EQU    0AH        ; Line feed
  99. ;
  100. ;-----------------------------------------------------------------------
  101. ;
  102. ; User configuration equates
  103. ;
  104. DELZRO    EQU    NO        ; Yes deletes all zero-length
  105.                 ;   files not starting with "-"
  106.                 ;   (as in SAP44).
  107.                 ; No to delete solely retains all zero-
  108.                 ;   length files
  109. ;
  110. CLRS1    EQU    1AH        ; To clear screen on start up
  111. CLRS2    EQU    00H        ; Room for maximum 6 bytes
  112. CLRS3    EQU    00H        ; Set terminating byte to 0
  113. CLRS4    EQU    00H        ; If clear screen undesired then
  114. CLRS5    EQU    00H        ; Set 1st (or all) bytes to 0
  115. CLRS6    EQU    00H        ; Nul terminator is in program
  116. ;
  117. ; Following is set to 0E5H, except Morrow MD5 -> MD34 set to 0
  118. ;
  119. RCVALU    EQU    0E5H        ; Set 0 if Morrow, else 0e5h
  120. ;
  121. ; Following for CP/M 3.0 users only
  122. ;
  123. SSCPM3    EQU    1024        ; Your largest record size
  124. ;
  125. ;-----------------------------------------------------------------------
  126. ;
  127.     ORG    100H
  128. ;
  129.     JP    START        ; Jump over stuff
  130. ;
  131. TITLM:    DB    'SAPP v'
  132.     DB    VER/10+'0',VER MOD 10+'0',' '
  133.     DB    VERM/10+'0',VERM MOD 10+'0','/'
  134.     DB    VERD/10+'0',VERD MOD 10+'0','/'
  135.     DB    VERY/10+'0',VERY MOD 10+'0'
  136.     DB    ' GFR',0
  137.     DB    1AH        ; EOF in case .COM file typed
  138. ;
  139. ;-----------------------------------------------------------------------
  140. ;
  141. ; Following may be patched with DDT, SID, or SZAP
  142. ;
  143. CLRCOD:    DB    CLRS1,CLRS2    ; Clear screen code
  144.     DB    CLRS3,CLRS4
  145.     DB    CLRS5,CLRS6
  146.     DB    0
  147. ;
  148. RECSIZ:    DW    SSCPM3        ; Size of CP/M 3.0 rec buffer
  149. RFIELD:    DB    RCVALU        ; Normally 0E5h, Morrow is 0
  150.                 ; Set 0E5h if not MD5, MD11, etc
  151. SKPWRN:    DB    0        ; Zero = warning. Nonzero = none.
  152.                 ; Normally should be 0 (false)
  153. ;
  154. ;-----------------------------------------------------------------------
  155. ;
  156. START:    SUB    A        ; Z80 test
  157.     JP    PO,START1    ; Continue if z80
  158.     LD    HL,NDZ80    ; Need z80 msg
  159.     JP    PRNTL        ; Print it & ret to system
  160. ;
  161. ; Is Z80 CPU, so get CP/M version
  162. ;
  163. START1:    LD    C,RETVER    ; Get version
  164.     CALL    BDOS
  165.     LD    A,L        ; Version to 'A'
  166.     LD    (VERFLG),A    ; Store it
  167.     CP    22H        ; Must be at least 2.2
  168.     JP    C,BASE        ; If less, then quit
  169.     LD    A,H
  170.     OR    A        ; Test for 0 for CP/M
  171.     JP    NZ,BASE        ; If not, quit as MP/M untested
  172. ;
  173. ; Clear screen and/or give signon message
  174. ;
  175. START2:    LD    HL,CLRCOD    ; Clear screen at start
  176.     CALL    PRNTL        ; Of program
  177.     LD    HL,TITLM    ; Program signon msg
  178.     CALL    PRNTL
  179. ;
  180. ; Now initialize the data and buffers
  181. ;
  182. START3:    XOR    A        ; Zero for fill
  183.     LD    HL,DATA        ; Point to data start (source)
  184.     LD    (HL),A        ; Fill it
  185.     LD    DE,DATA+1    ; Point to next (destination)
  186.     LD    BC,DATSIZ    ; Length
  187.     LDIR            ; Zero it all
  188. ;
  189. ; This buffer is only used by CP/M 3.0
  190. ;
  191. START4:    CALL    V3CHEK        ; Check version
  192.     JR    C,START5    ; Skip if 2.2
  193.     LD    (HSTBUF),HL    ; Save CP/M 3.0 sec buf addr
  194.     LD    BC,(RECSIZ)    ; Get size of rec buffer
  195.     LDIR            ; Zero it too
  196. ;
  197. ; Do program buffer for directory
  198. ;
  199. START5:    LD    (PRGBUF),HL    ; Save program buffer addrress
  200.     EX    DE,HL        ; Move buffer addrress to DE
  201.     LD    HL,(BDOS+1)    ; Get BDOS address
  202.     DEC    H        ; Make 1 lower
  203.     LD    (MEMTOP),HL    ; Store memory top address
  204.     OR    A        ; Clear carry for subtract
  205.     SBC    HL,DE        ; Subtract to be byte count
  206.     LD    B,H        ; Move to BC
  207.     LD    C,L        ; For length of our fill
  208.     INC    DE        ; Increment buffer address (destination)
  209.     LD    HL,(PRGBUF)    ; Get back buffer start (source)
  210.     LDIR            ; Zero it too
  211. ;
  212. ; Data & buffers done so set up stack and  offset/length (3.0)
  213. ;
  214.     LD    SP,STACK    ; Use our own stack
  215.     CALL    V3CHEK        ; Check version
  216.     JR    C,START6    ; Skip if 2.2
  217.     LD    HL,DPB3OF    ; Offset xlt address to address
  218.     LD    (DPBOF),HL    ; Was default for CP/M 2.2
  219.     LD    HL,DPB3LN    ; Length of CP/M 3.0  table
  220.     LD    (DPBLN),HL    ; Was default for CP/M 2.2
  221. ;
  222. ;-----------------------------------------------------------------------
  223. ;
  224. ; Now select drive, copy DBP (make fake if needed), run program
  225. ;
  226. START6:    CALL    SETUP        ; Select disk, do , etc
  227.     CALL    RDDIR        ; Read the directory
  228.     CALL    CLEAN        ; Set erased files to all E5
  229.     CALL    SORT        ; Sort the entries
  230.     CALL    PACK
  231.     CALL    WRDIR        ; Write new directory back
  232.     LD    HL,DONEM    ; 'Done' message
  233.     CALL    PRNTL
  234. ;
  235. EXIT:    JP    BASE        ; Go warm boot
  236. ;
  237. ;-----------------------------------------------------------------------
  238. ;
  239. ; Select disk, get translation table address and copy
  240. ;
  241. SETUP:    LD    A,(FCB)        ; Get any option
  242.     DEC    A
  243.     JP    P,SELDSK    ; Skip if disk mentioned
  244.     LD    C,GETDSK    ; Else get current disk
  245.     CALL    BDOS        ; Returns 0=A,1=B,2=C,...
  246. ;
  247. SELDSK:    LD    (LOGDSK),A    ; Store selected disk
  248.     LD    (BCREG),A    ; Set C reg in BIOSPB
  249.     LD    C,RESET        ; Reset disk system
  250.     CALL    BDOS        ; In case new disk
  251.     CALL    V3CHEK        ; Check version
  252.     JR    C,SELEC2    ; Skip if 2.2
  253.     LD    DE,1        ; First call flag
  254.     LD    (DEREG),DE    ; Set E register in BIOSPB
  255.     LD    A,9        ; BIOS select function
  256.     CALL    XBIOS3        ; CP/M 3.0 select
  257.     JP    SELEC3        ; Skip over
  258. ;
  259. SELEC2:    LD    A,(LOGDSK)    ; Get disk back
  260.     LD    C,A        ; To C
  261.     LD    A,9        ; BIOS select function
  262.     CALL    XBIOS2        ; Do it
  263. ;
  264. SELEC3:    LD    A,H
  265.     OR    L        ; Check for HL=0
  266.     JR    Z,EXIT        ; Quit if select error
  267. ;
  268.     LD    E,(HL)        ; Get address of xlat table
  269.     INC    HL
  270.     LD    D,(HL)
  271.     DEC    HL
  272.     EX    DE,HL
  273.     LD    (RECTBL),HL    ; Save xlat address
  274.     LD    HL,DPB2OF    ; Default, CP/M 2.2 offset to
  275. ;
  276. DPBOF    EQU    $-2
  277.     ADD    HL,DE
  278.     LD    A,(HL)        ; Get address of
  279.     INC    HL
  280.     LD    H,(HL)
  281.     LD    L,A        ; Into HL
  282.     LD    DE,DPB        ; Destination - our own
  283.     LD    BC,DPB2LN    ; Default,  size for CP/M 2.2
  284. ;
  285. DPBLN    EQU    $-2
  286. ;
  287.     LDIR
  288. ;
  289. ; Calculate memory bytes free for directory
  290. ;
  291.     LD    HL,(MEMTOP)    ; Get memory top
  292.     LD    DE,(PRGBUF)    ; Get buffer start
  293.     OR    A        ; Clear cy for subtr
  294.     SBC    HL,DE        ; Subtr to get room (bytes) free
  295.     LD    (PRGMAX),HL    ; Save free room available
  296. ;
  297. ; This portion is for Morrow computors. Should not matter to others.
  298. ;
  299.     LD    HL,(AL0)    ; Get dir alloc
  300.     INC    HL        ; If hard disk, was 0FFFFh
  301.     LD    A,H        ; Incr would make it 0000h
  302.     OR    L        ; Test if zero now
  303.     JP    NZ,SELEC4    ; Skip if not Morrow hard disk
  304.     LD    A,(RFIELD)    ; Value for Morrow's rc field
  305.     LD    (FILLR2+1),A    ; Modify value in program
  306. ;
  307. ; Do initial test of number of directory entries
  308. ;
  309. SELEC4:    LD    HL,(DRM)    ; Get real maximum number of entries
  310.     LD    DE,2047        ; Cannot be > 2047 for 64k TPA
  311.     EX    DE,HL        ; Limit to HL, real maximum to DE
  312.     OR    A        ; Clear carryy for subtract
  313.     SBC    HL,DE        ; Subtract to see if it is greater
  314.     JR    C,SELEC5    ; Skip next if greater
  315. ;
  316. ; See if enough room for real number of directory entries
  317. ;
  318.     EX    DE,HL        ; Real maximum to HL
  319.     LD    DE,32        ; Multiply by directory entry length
  320.     CALL    MULT        ; To get bytes normally needed
  321.     LD    DE,(PRGMAX)    ; Get back free room available
  322.     EX    DE,HL        ; Swap so HL=free room DE=needed
  323.     OR    A        ; Clear carry for subtract
  324.     SBC    HL,DE        ; Subtract to see if enough room
  325.     RET    NC        ; Return if ok (no borrow)
  326. ;
  327. ; Not enough room for real maximum, so calculate the program's maximum
  328. ;
  329. SELEC5:    LD    HL,(PRGMAX)    ; Maximum free room
  330.     LD    DE,32        ; Each entry is 32 bytes long
  331.     CALL    UDIVID        ; Divide to get fake DRM value
  332.     DEC    HL        ; Make 1 less (...to be sure)
  333.     LD    (DRM),HL    ; For the program
  334. ;
  335. ; See if use set the flag for no warning (experienced users)
  336. ;
  337.     LD    A,(SKPWRN)    ; See if we skip this warning
  338.     CP    0        ; If 0, will give warning message
  339.     RET    NZ        ; If <> 0, return and continue
  340. ;
  341.     LD    HL,FAK1M    ; Tell user about
  342.     CALL    PRNTL        ; Limitation of the
  343.     LD    HL,(DRM)    ; Number of directory entries
  344.     CALL    PHLFDC        ; That the program can handle
  345.     LD    HL,FAK2M    ; And prompt for continue
  346.     CALL    PRNTL
  347. ;
  348. ; See if user wants to continue with fake max number or to abort
  349. ;
  350.     CALL    CONBUF        ; Get response
  351.     LD    A,(INBUF+2)
  352.     AND    31        ; "Y", "y", and "^Y" are equiv
  353.     CP    'Y'-40H
  354.     RET    Z        ; Continue if yes
  355. ;
  356.     JP    BASE        ; Else quit
  357. ;
  358. ;-----------------------------------------------------------------------
  359. ;
  360. ; Read/write directory routines
  361. ;
  362. RDDIR:    LD    HL,READM    ; Read message
  363.     CALL    PRNTL        ; Zero last in A register (from message)
  364.     JP    DODIR
  365. ;
  366. WRDIR:    LD    A,(NOSWAP)
  367.     OR    A
  368.     JP    NZ,WRDIR1
  369.     LD    HL,PRESM    ; Pre-sorted message
  370.     CALL    PRNTL
  371. ;
  372. WRDIR1:    LD    HL,WRITM    ; Write message
  373.     CALL    PRNTL
  374.     LD    A,1        ; Put 1 in A register
  375. ;
  376. DODIR:    LD    (WRFLAG),A    ; Store for read/write
  377.     LD    HL,(SYSTRK)    ; Get number of system tracks
  378.     LD    (LOGTRK),HL    ; Set the track
  379. ;
  380.     CALL    V3CHEK        ; Check version
  381.     JP    NC,DODIR2    ; Skip if 3.0
  382.     LD    BC,(LOGTRK)    ; Track to BC
  383.     LD    A,10        ; BIOS SETTRK function
  384.     CALL    XBIOS2        ; Do it for CP/M 2.2
  385. ;
  386. DODIR2:    LD    HL,0
  387.     LD    (RECORD),HL
  388.     LD    HL,(DRM)    ; Get number of directory entries
  389.     INC    HL        ; Relative to 1
  390.     OR    A        ; Clear carry for division
  391.     RR    H        ; Divide HL by 2
  392.     RR    L
  393.     OR    A
  394.     RR    H        ; Again makes total division by 4
  395.     RR    L        ; To get 128-byte record count
  396.     LD    (DIRCNT),HL
  397.     LD    HL,(PRGBUF)    ; Get buffer address
  398.     LD    (DMAADR),HL    ; For DMA addr
  399. ;
  400. DIRLOP:    CALL    V3CHEK        ; Check version
  401.     JP    NC,DIRLP1    ; Skip if 3.0
  402.     LD    BC,(DMAADR)    ; Track to BC
  403.     LD    A,12        ; BIOS SETDMA function
  404.     CALL    XBIOS2        ; Do it for CP/M 2.2
  405. ;
  406. DIRLP1:    LD    DE,(RECORD)    ; Current record
  407.     INC    DE        ; Increment it
  408.     LD    HL,(SPT)    ; Get records per track
  409.     OR    A        ; Clear carry for subtract
  410.     SBC    HL,DE        ; Subtract SPT - Records
  411.     EX    DE,HL        ; Current record to HL
  412.     JR    NC,NOTROV
  413. ;
  414. ; Track overflow, bump to next
  415. ;
  416.     LD    HL,(LOGTRK)    ; Get current track
  417.     INC    HL        ; Increment it
  418.     LD    (LOGTRK),HL    ; Set the track
  419.     CALL    V3CHEK        ; Check version
  420.     JP    NC,DIRLP2    ; Skip if 3.0
  421.     LD    BC,(LOGTRK)    ; Track to bc
  422.     LD    A,10        ; Bios settrk func
  423.     CALL    XBIOS2        ; Do it for CP/M 2.2
  424. ;
  425. DIRLP2:    LD    HL,1        ; Rewind record number
  426. ;
  427. NOTROV:    CALL    DOREC        ; Set current record
  428.     LD    A,(WRFLAG)    ; Time to figure out
  429.     OR    A        ; If we are reading
  430.     JP    NZ,DWRT        ; Or writing
  431. ;
  432.     CALL    V3CHEK        ; Check version
  433.     JR    C,READ2        ; Skip if 2.2
  434.     CALL    READ        ; Do CP/M 3.0 way
  435.     JP    READ3        ; Skip over 2.2 stuff
  436. ;
  437. READ2:    LD    A,13        ; BIOS READ function
  438.     CALL    XBIOS2        ; Do it for CP/M 2.2
  439. ;
  440. READ3:    OR    A        ; Test flags on read
  441.     JR    NZ,ERREXT    ; NZ=error
  442.     JP    MORE        ; Good read, go do more
  443. ;
  444. ; Write
  445. ;
  446. DWRT:    LD    C,1        ; For CP/M 2.2 deblocking BIOSs
  447. ;
  448.     CALL    V3CHEK        ; Check version
  449.     JR    C,DWRT2        ; Skip if 2.2
  450.     CALL    WRITE        ; Do CP/M 3.0 way
  451.     JP    DWRT3        ; Skip over 2.2 stuff
  452. ;
  453. DWRT2:    LD    A,14        ; BIOS WRITE function
  454.     CALL    XBIOS2        ; Do it for CP/M 2.2
  455. ;
  456. DWRT3:    OR    A        ; Test flags on write
  457.     JR    NZ,ERREXT    ; NZ=bad directory write
  458. ;
  459. ; Good read or write
  460. ;
  461. MORE:    LD    HL,(DMAADR)    ; Get DMA addr
  462.     LD    DE,80H        ; Add 128 bytes to it
  463.     ADD    HL,DE        ; For next pass
  464.     LD    (DMAADR),HL
  465.     LD    HL,(DIRCNT)    ; Countdown entries
  466.     DEC    HL
  467.     LD    (DIRCNT),HL
  468.     LD    A,H        ; Test for zero left
  469.     OR    L
  470.     JP    NZ,DIRLOP    ; Loop till zero
  471. ;
  472.     LD    HL,80H        ; Directory I/O done, reset DMA address
  473.     LD    (DMAADR),HL    ; Set DMA
  474.     CALL    V3CHEK        ; Check version
  475.     RET    NC        ; Return if 3.0
  476. ;
  477.     LD    BC,(DMAADR)    ; Track to BC
  478.     LD    A,12        ; BIOS SETDMA function
  479.     CALL    XBIOS2        ; Do it for CP/M 2.2
  480.     RET
  481. ;
  482. ; Come here on read/write error
  483. ;
  484. ERREXT:    LD    HL,ERORM    ; Error message
  485.     CALL    PRNTL
  486.     JP    BASE        ; Go warm boot
  487. ;
  488. ;
  489. DOREC:    LD    (RECORD),HL    ; Record update
  490.     LD    B,H
  491.     LD    C,L
  492.     LD    HL,(RECTBL)
  493.     EX    DE,HL
  494.     DEC    BC
  495. ;
  496.     CALL    V3CHEK        ; Check version
  497.     JR    C,DOREC2    ; Skip if 2.2
  498.     CALL    RECTRN        ; Do for CP/M 3.0
  499.     JP    DOREC3        ; Skip 2.2 part
  500. ;
  501. DOREC2:    LD    A,16        ; BIOS SECTRAN function
  502.     CALL    XBIOS2
  503. ;
  504. DOREC3:    LD    B,H        ; Moved to B, but unused
  505.     LD    A,L
  506.     LD    (LOGREC),A    ; Set record
  507.     CALL    V3CHEK        ; Check version
  508.     RET    NC        ; Return if 3.0
  509. ;
  510.     LD    A,(LOGREC)    ; Get recorad for CP/M 2.2
  511.     LD    C,A        ; To register 'C'
  512.     LD    A,11        ; BIOS SETREC function
  513.     CALL    XBIOS2        ; Do it for CP/M 2.2
  514.     RET
  515. ;
  516. CLEAN:    LD    HL,0        ; ICT = 0
  517. ;
  518. CLNLOP:    LD    (ICT),HL
  519.     CALL    INDEX        ; HL = BUF + 16 * ICT
  520.     LD    A,(HL)        ; Jump if this is a deleted file
  521.     CP    0E5H
  522.     JP    Z,FILLR1
  523. ;
  524.      IF    DELZRO
  525.     LD    DE,12
  526.     ADD    HL,DE        ; HL = HL + 12
  527.     LD    A,(HL)        ; Check extent field
  528.     OR    A
  529.     JP    NZ,CLBUMP    ; Skip if not extent 0
  530.     INC    HL        ; Point to record count field
  531.     INC    HL
  532.     LD    A,(HL)        ; Get S2 byte (extended RC)
  533.     AND    0FH        ; For CP/M 2.2, 0 for CP/M 1.4
  534.     LD    E,A
  535.     INC    HL
  536.     LD    A,(HL)        ; Check record count field
  537.     OR    E
  538.     JP    NZ,CLBUMP    ; Jump if non-zero
  539.     LD    HL,(ICT)    ; Clear all 32 bytes of
  540.     CALL    INDEX        ; Directory entry to E5
  541.     INC    HL
  542.     LD    A,(HL)        ; Get first character of filename
  543.     DEC    HL        ; MAST.CAT catalog programs
  544.     CP    '-'        ; Have diskname of zero length
  545.     JP    Z,CLBUMP    ; That start with "-", do not delete
  546.      ENDIF            ; DELZRO
  547. ;
  548.      IF    NOT DELZRO
  549.     JP    CLBUMP        ; Do not delete this file
  550.      ENDIF            ; NOT DELZRO
  551. ;
  552. FILLR1:    LD    (HL),0E5H    ; Fill source memory with E5
  553.     LD    D,H        ; Get HL address to DE
  554.     INC    DE        ; Destination = source + 1
  555.     LD    BC,31        ; Copy 31 times
  556.     LDIR
  557.     LD    DE,17        ; Point to the RC
  558.     OR    A        ; Clear carry for subtract
  559.     SBC    HL,DE        ; Adjust HL to it, by backing up
  560. ;
  561. FILLR2:    LD    (HL),0E5H    ; Set RC to E5 unless Morrow hard disk
  562. ;
  563. CLBUMP:    LD    DE,(DRM)    ; Get count of filenames
  564.     INC    DE        ; Increment it
  565.     LD    HL,(ICT)    ; Our current count
  566.     INC    HL        ; Increment it
  567.     PUSH    HL
  568.     OR    A        ; Clear carry for subtract
  569.     SBC    HL,DE        ; Subtract DRM from ICT
  570.     POP    HL
  571.     JP    C,CLNLOP    ; Loop until all cleaned
  572.     RET
  573. ;
  574. ; Sort the directory
  575. ;
  576. SORT:    XOR    A
  577.     LD    (NOSWAP),A    ; Zero the flag in case pre-sorted
  578.     LD    HL,SORTM    ; Sort message
  579.     CALL    PRNTL
  580. ;
  581. ; Shell-Metzner sort
  582. ;
  583.     LD    HL,(ICT)
  584.     INC    HL
  585.     LD    (SNRECW),HL
  586.     LD    HL,(PRGBUF)    ; Get buffer address
  587.     LD    (SSTADR),HL
  588.     PUSH    HL        ; Save it
  589.     LD    HL,32
  590.     LD    (SRECLN),HL
  591.     PUSH    HL        ; Save it
  592. ;
  593. ; Now divide number of fields by 2
  594. ;
  595. DIVIDE:    LD    HL,(SNRECW)    ; Get value
  596.     OR    A        ; Clear carry for division
  597.     RR    H        ; Divide HL by 2
  598.     RR    L
  599.     LD    (SNRECW),HL    ; Save result
  600.     LD    A,L        ; If SNRECW <> 0
  601.     OR    H        ; Then
  602.     JP    NZ,NDONE    ; Not done
  603. ;
  604.     POP    BC        ; All fields sorted
  605.     POP    DE        ; So clean up stack
  606.     RET
  607. ;
  608. ; Not done yet
  609. ;
  610. NDONE:    EX    DE,HL
  611.     LD    HL,(ICT)
  612.     INC    HL
  613.     OR    A        ; Clear carry for subtract
  614.     SBC    HL,DE        ; HL = HL - DE
  615.     LD    (SRECLN),HL
  616.     LD    HL,1
  617.     LD    (SSRTV1),HL
  618.     LD    (SSTADR),HL
  619.     DEC    L
  620.     POP    BC
  621.     PUSH    BC
  622. ;
  623. NDONE1:    ADD    HL,DE
  624.     DEC    BC
  625.     LD    A,B
  626.     OR    C
  627.     JP    NZ,NDONE1
  628.     LD    (SSRTV2),HL
  629.     EX    DE,HL
  630.     POP    BC
  631.     POP    HL
  632.     PUSH    HL
  633.     PUSH    BC
  634. ;
  635. NDONE2:    LD    (SSRTV4),HL
  636.     LD    (SSRTV3),HL
  637.     EX    DE,HL
  638.     ADD    HL,DE
  639.     EX    DE,HL
  640. ;
  641. COMPR:    POP    BC        ; Get count
  642.     PUSH    BC        ; Save count
  643.     PUSH    DE        ; Save addresses of beginning
  644.     PUSH    HL        ; Of these 2 directory entries
  645. ;
  646. COMPR1:    LD    A,(DE)        ; Get (DE) byte
  647.     AND    7FH        ; Strip parity (in case TO, SYS, etc.)
  648.     PUSH    BC        ; Save count
  649.     EX    AF,AF'          ; Use alt register - saves (DE) byte
  650.     LD    A,(HL)        ; Get (hl) byte
  651.     AND    7FH        ; Strip parity (for same reason)
  652.     LD    B,A        ; Save it
  653.     EX    AF,AF'          ; Restore register - restores (DE) byte
  654.     SUB    B        ; Subtract (HL) from (DE)
  655.     POP    BC        ; Restore count
  656.     JP    NZ,NOTEQU    ; If not equal, jump over
  657.     INC    HL        ; Else bump
  658.     INC    DE        ; Both addresses
  659.     DEC    BC        ; Decr count
  660.     LD    A,B        ; Test
  661.     OR    C        ; For zero
  662.     JP    NZ,COMPR1    ; Do more if <> 0, else fall into next
  663. ;
  664. NSWCH:    POP    HL        ; Clean up the stack
  665.     POP    HL        ; And again
  666. ;
  667. NSWCH1:    LD    DE,(SSTADR)
  668.     INC    DE
  669.     LD    (SSTADR),DE
  670.     LD    (SSRTV1),DE
  671.     LD    HL,(SRECLN)
  672.     OR    A        ; Clear carry
  673.     SBC    HL,DE        ; Subtract HL - DE
  674.     JP    C,DIVIDE
  675.     LD    HL,(SSRTV4)
  676.     POP    DE
  677.     PUSH    DE
  678.     ADD    HL,DE
  679.     LD    DE,(SSRTV2)
  680.     JP    NDONE2
  681. ;
  682. ; The condition at NOTEQU has to be changed for descending sort
  683. ;
  684. NOTEQU:    JP    NC,NSWCH
  685.     LD    A,1
  686.     LD    (NOSWAP),A
  687.     POP    HL        ; Get back addresses of beginning
  688.     POP    DE        ; Of these 2 directory entries
  689.     POP    BC        ; And the number of bytes
  690.     PUSH    BC        ; Leave this on the stack
  691. ;
  692. SWITCH:    LD    A,(HL)        ; Get (HL) byte
  693.     EX    AF,AF'          ; Save it
  694.     LD    A,(DE)        ; Get (DE) byte
  695.     LD    (HL),A        ; Store in (HL)
  696.     EX    AF,AF'          ; Get old (HL) back
  697.     LD    (DE),A        ; Store in (DE)
  698.     INC    HL        ; Bump both
  699.     INC    DE        ; Addresses
  700.     DEC    BC        ; Decr count
  701.     LD    A,B        ; Test
  702.     OR    C        ; For zero
  703.     JP    NZ,SWITCH    ; Go do more if <> 0
  704.     LD    HL,(SNRECW)
  705.     LD    A,H
  706.     CPL
  707.     LD    D,A
  708.     LD    A,L
  709.     CPL
  710.     LD    E,A
  711.     LD    HL,(SSRTV1)
  712.     ADD    HL,DE
  713.     JP    NC,NSWCH1
  714.     INC    HL
  715.     LD    (SSRTV1),HL
  716.     LD    DE,(SSRTV3)
  717.     LD    HL,(SSRTV2)
  718.     LD    A,E        ; Subtr DE - HL
  719.     SUB    L
  720.     LD    L,A
  721.     LD    A,D
  722.     SBC    A,H
  723.     LD    H,A        ; Result in hl, de unaffected
  724.     LD    (SSRTV3),HL    ; Store result here
  725.     JP    COMPR
  726. ;
  727. PACK:    LD    HL,0        ; ICT = 0
  728. ;
  729. PACK1:    LD    (ICT),HL
  730.     CALL    INDEX        ; HL = BUF + 16 * ICT
  731.     LD    DE,9
  732.     ADD    HL,DE        ; HL = HL + 9
  733.     LD    A,(HL)        ; Jump if filetype not "X$$"
  734.     SUB    '0'
  735.     JP    C,PACK2
  736.     CP    10
  737.     JP    NC,PACK2
  738.     LD    (JCT),A
  739.     INC    HL
  740.     LD    A,(HL)
  741.     CP    '$'
  742.     JP    NZ,PACK2
  743.     INC    HL
  744.     LD    A,(HL)
  745.     CP    '$'
  746.     JP    NZ,PACK2
  747.     INC    HL        ; Set extent number to x
  748.     LD    A,(JCT)
  749.     LD    (HL),A
  750.     DEC    HL        ; Set filetype to "$$$"
  751.     LD    (HL),'$'
  752.     DEC    HL
  753.     LD    (HL),'$'
  754.     DEC    HL
  755.     LD    (HL),'$'
  756. ;
  757. PACK2:    LD    HL,(ICT)
  758.     INC    HL        ; ICT = ICT + 1
  759.     LD    DE,(DRM)
  760.     INC    DE        ; DRM = DRM + 1
  761.     PUSH    HL
  762.     OR    A        ; Clear carry for subtract
  763.     SBC    HL,DE        ; Subtract DRM from ICT
  764.     POP    HL        ; Loop until ICT > DRM
  765.     JP    C,PACK1
  766.     RET
  767. ;
  768. INDEX:    ADD    HL,HL
  769.     ADD    HL,HL
  770.     ADD    HL,HL
  771.     ADD    HL,HL
  772.     ADD    HL,HL
  773.     LD    DE,(PRGBUF)    ; Get buffer address
  774.     ADD    HL,DE
  775.     RET
  776. ;
  777. ; Print nul terminated string pointed to by HL
  778. ;
  779. PRNTL:    LD    A,(HL)        ; Get char
  780.     OR    A        ; Test for zero
  781.     RET    Z        ; If yes, we are done
  782.     EXX            ; Use alt primary regs
  783.     LD    E,A        ; Get char to e for output
  784.     LD    C,CONOUF    ; Console out func
  785.     CALL    BDOS
  786.     EXX            ; Restore normal primary regs
  787.     INC    HL        ; Point to next
  788.     JP    PRNTL        ; Try to do more
  789. ;
  790. ;-----------------------------------------------------------------------
  791. ;
  792. ; Print HL as decimal chaacters in N-character field, floating point
  793. ; where field size is from 1 to 5 characters.
  794. ;
  795. PHLFDC:    PUSH    AF        ; Save all registers
  796.     PUSH    BC
  797.     PUSH    DE
  798.     PUSH    HL
  799.     LD    B,1        ; B=1 for leading <sp>
  800.     LD    DE,10000    ; Print 10,000's
  801.     CALL    PHDC1
  802.     LD    DE,1000
  803.     CALL    PHDC1
  804.     LD    DE,100
  805.     CALL    PHDC1
  806.     LD    DE,10        ; Print 10's
  807.     CALL    PHDC1
  808.     LD    A,L        ; Print 1's
  809.     ADD    A,'0'        ; Convert to ascii
  810.     CALL    COUT
  811.     POP    HL        ; Restore all regs
  812.     POP    DE
  813.     POP    BC
  814.     POP    AF
  815.     RET
  816. ;
  817. ; Divide HL by DE and print quotient with leading spaces
  818. ;
  819. PHDC1:    LD    C,0        ; Set count
  820. ;
  821. PHDC2:    OR    A        ; Clear carry for Z80 way
  822.     SBC    HL,DE        ; Subtract DE from HL with borrow
  823.     JR    C,PHDC3        ; Done if carry set (further borrow)
  824.     INC    C        ; Increment count
  825.     JP    PHDC2
  826. ;
  827. PHDC3:    OR    A        ; Clear carry
  828.     ADC    HL,DE        ; Add DE to HL with carry Z80 way
  829.     LD    A,C        ; Get result
  830.     OR    A        ; Check for 0
  831.     JR    NZ,PHDC4
  832.     OR    B        ; 0=no leading <sp>
  833.     RET    NZ        ; (A=0, A or B = 0 means B = 0)
  834. ;
  835. PHDC4:    LD    B,0        ; Turn off leading space
  836.     LD    A,C        ; Get value
  837.     ADD    A,'0'        ; Convert to ASCII
  838.     JP    COUT
  839. ;
  840. COUT:    EXX            ; Use alt primary regs
  841.     PUSH    AF
  842.     LD    E,A
  843.     LD    C,CONOUF    ; Console OUT function
  844.     CALL    BDOS
  845.     POP    AF
  846.     EXX            ; Restore normal primary registers
  847.     RET
  848. ;
  849. CONBUF:    LD    C,RDCBUF
  850.     LD    DE,INBUF
  851.     JP    BDOS
  852. ;
  853. INBUF:    DB    1,0,0
  854. ;
  855. ; Multiply HL by DE, return result in HL
  856. ;
  857. MULT:    PUSH    BC
  858.     PUSH    DE
  859.     EX    DE,HL
  860.     LD    B,D
  861.     LD    C,E
  862.     LD    A,B
  863.     OR    C
  864.     JP    NZ,MULCON
  865.     LD    HL,0        ; Filter special case
  866.     JR    MLDONE        ; Of multiply by 0
  867. ;
  868. MULCON:    DEC    BC
  869.     LD    D,H
  870.     LD    E,L
  871. ;
  872. MULTLP:    LD    A,B
  873.     OR    C
  874.     JR    Z,MLDONE
  875.     ADD    HL,DE
  876.     DEC    BC
  877.     JP    MULTLP
  878. ;
  879. MLDONE:    POP    DE
  880.     POP    BC
  881.     RET
  882. ;
  883. ; Unsigned division.  Divide HL by DE.    Destroys register A.
  884. ; Return HL = quotient, DE = remainder, carry clear if ok.
  885. ; Carry set if DE > HL, or if DE = 0.
  886. ;
  887. UDIVID:    PUSH    BC        ; Save register
  888.     LD    BC,0        ; Initialize quotient
  889.     PUSH    HL        ; Save HL
  890.     OR    A        ; Clear carry
  891.     SBC    HL,DE        ; Test if divisor > dividend
  892.     POP    HL        ; Restore HL
  893.     JR    C,DIVBAD    ; If so, it is bad
  894.     LD    A,E        ; Else test divisor
  895.     OR    D        ; For 0
  896.     JP    NZ,DIVLOP    ; If <> 0 continue
  897. ;
  898. DIVBAD:    POP    BC        ; Restore registers
  899.     SCF            ; Set cy to show bad
  900.     RET
  901. ;
  902. DIVLOP:    INC    BC        ; Increment quotient
  903.     OR    A        ; Clear carryy for subtract
  904.     SBC    HL,DE        ; Division by subtract
  905.     JP    C,DIVOFL    ; If borrow, done dividing
  906.     JP    NZ,DIVLOP    ; If <> 0 more to do
  907.     JP    DIVREM        ; Was 0, skip calculation of remainder
  908. ;
  909. DIVOFL:    ADD    HL,DE        ; HL=neg remainder, DE=divisor
  910.     DEC    BC        ; The even division was 1 less
  911. ;
  912. DIVREM:    EX    DE,HL        ; Positive remainder to DE
  913.     LD    H,B        ; Put quotient into HL
  914.     LD    L,C
  915.     POP    BC        ; Restore registers
  916.     OR    A        ; Clear carry (valid result)
  917.     RET
  918. ;
  919. ;-----------------------------------------------------------------------
  920. ;
  921. ; Test for CP/M 3.0, used by above routines
  922. ;
  923. V3CHEK:    LD    A,(VERFLG)    ; Check for version 3.0
  924.     CP    30H        ; Carry set if not 3.0
  925.     RET
  926. ;
  927. VERFLG:    DB    0        ; Version number of CP/M
  928. ;
  929. ;-----------------------------------------------------------------------
  930. ;
  931. ; For CP/M 2.2, enter with BIOS function in A  eg.,  LD A,9  (SELDSK)
  932. ;
  933. XBIOS2:    PUSH    DE        ; Save DE
  934.     LD    HL,(BASE+1)    ; Warm boot address
  935.     LD    L,A        ; BIOS function number to 'L'
  936.     LD    E,L        ; And to 'E'
  937.     LD    D,0        ; Zero 'D'
  938.     ADD    HL,DE        ; Add so that HL
  939.     ADD    HL,DE        ;   points to BIOS function address
  940.     POP    DE        ; Restore DE
  941.     JP    (HL)        ; Do it an return to call addr
  942. ;
  943. ;-----------------------------------------------------------------------
  944. ;
  945. ; Following is for CP/M 3.0
  946. ;
  947. ; Translate records.  Records are not translated yet.  Wait until we
  948. ; know the physical record number.  This works fine as long as a program
  949. ; trusts the BIOS to do translation.  For programs that directly access
  950. ; the XLAT table to do their own translation, this may give a wrong idea
  951. ; about disk skew but it shouldn't cause harm.
  952. ;
  953. RECTRN:    LD    L,C        ; Return record in HL
  954.     LD    H,B
  955.     RET
  956. ;
  957. ; Read the selected CP/M record
  958. ;
  959. READ:    LD    A,1
  960.     LD    (READOP),A    ; Read operation
  961.     INC    A        ; A=2 (WRUAL)
  962.     LD    (WRTYPE),A    ; Treat as unalloc
  963.     JP    ALLOC        ; Perform read
  964. ;
  965. ; Write the selected CP/M record
  966. ;
  967. WRITE:    XOR    A
  968.     LD    (READOP),A    ; Not a read operation
  969.     LD    A,C
  970.     LD    (WRTYPE),A    ; Save write type
  971.     CP    2        ; Unallocated block?
  972.     JP    NZ,CHKUNA
  973. ;
  974. ; Write to first record of unallocated block
  975. ;
  976.     LD    A,(BLM)        ; Get block shift mask
  977.     INC    A        ; Adjust value
  978.     LD    (UNACNT),A    ; Unallocated record count
  979.     LD    A,(LOGDSK)    ; Set up values for
  980.     LD    (UNADSK),A    ;   writing to an unallocated
  981.     LD    A,(LOGTRK)    ; Block
  982.     LD    (UNATRK),A
  983.     LD    A,(LOGREC)
  984.     LD    (UNAREC),A
  985. ;
  986. CHKUNA:    LD    A,(UNACNT)    ; Any unallocated records
  987.     OR    A        ; In this block
  988.     JP    Z,ALLOC        ; Skip if not
  989.     DEC    A
  990.     LD    (UNACNT),A
  991.     LD    A,(LOGDSK)
  992.     LD    HL,UNADSK
  993.     CP    (HL)        ; LOGDSK = UNADSK ?
  994.     JP    NZ,ALLOC    ; Skip if not
  995.     LD    A,(LOGTRK)
  996.     CP    (HL)        ; LOGTRK = UNATRK ?
  997.     JP    NZ,ALLOC    ; Skip if not
  998.     LD    A,(LOGREC)
  999.     LD    HL,UNAREC
  1000.     CP    (HL)        ; LOGTRK = UNAREC ?
  1001.     JP    NZ,ALLOC    ; Skip if not
  1002.     INC    (HL)        ; Move to next record
  1003.     LD    A,(HL)
  1004.     LD    HL,SPT        ; Address of SPT
  1005.     CP    (HL)        ; Record > SPT ?
  1006.     JP    C,NOOVF        ; Skip if no overflow
  1007.     LD    HL,(UNATRK)
  1008.     INC    HL
  1009.     LD    (UNATRK),HL    ; Bump track
  1010.     XOR    A
  1011.     LD    (UNAREC),A    ; Reset record count
  1012. ;
  1013. NOOVF:    XOR    A
  1014.     LD    (RCFLAG),A    ; Do not pre-read
  1015.     JP    RWOPER        ; Perform write
  1016. ;
  1017. ALLOC:    XOR    A        ; Requires pre-read
  1018.     LD    (UNACNT),A
  1019.     INC    A
  1020.     LD    (RCFLAG),A    ; Force pre-read
  1021. ;
  1022. RWOPER:    XOR    A
  1023.     LD    (ERFLAG),A    ; No errors yet
  1024.     LD    A,(PSH)        ; Get physical shift factor
  1025.     OR    A        ; Set flags
  1026.     LD    B,A
  1027.     LD    A,(LOGREC)    ; Logical record
  1028.     LD    HL,(HSTBUF)    ; Get address of buffer
  1029.     LD    DE,128
  1030.     JP    Z,NOBLK        ; No blocking
  1031.     EX    DE,HL        ; Shuffle registers
  1032. ;
  1033. SHIFT:    EX    DE,HL
  1034.     RRCA
  1035.     JP    NC,SH1
  1036.     ADD    HL,DE        ; Bump buffer address
  1037. ;
  1038. SH1:    EX    DE,HL
  1039.     ADD    HL,HL
  1040.     AND    07FH        ; Zero high bit
  1041.     DJNZ    SHIFT
  1042.     EX    DE,HL        ; HL=buffer address
  1043. ;
  1044. NOBLK:    LD    (RECHST),A
  1045.     LD    (RECBUF),HL
  1046.     LD    HL,HSTACT    ; Buffer active flag
  1047.     LD    A,(HL)
  1048.     LD    (HL),1        ; Set buffer active
  1049.     OR    A        ; Was it already?
  1050.     JP    Z,FILHST    ; Fill buffer if not
  1051.     LD    A,(LOGDSK)
  1052.     LD    HL,HSTDSK    ; Same disk ?
  1053.     CP    (HL)
  1054.     JP    NZ,NMATCH
  1055.     LD    A,(LOGTRK)
  1056.     LD    HL,HSTTRK    ; Same track ?
  1057.     CP    (HL)
  1058.     JP    NZ,NMATCH
  1059.     LD    A,(RECHST)    ; Same buffer ?
  1060.     LD    HL,HSTSEC
  1061.     CP    (HL)
  1062.     JP    Z,MATCH
  1063. ;
  1064. NMATCH:    LD    A,(HSTWRT)    ; Buffer changed?
  1065.     OR    A
  1066.     CALL    NZ,WRTHST    ; Clear buffer
  1067. ;
  1068. FILHST:    LD    A,(LOGDSK)
  1069.     LD    (HSTDSK),A
  1070.     LD    HL,(LOGTRK)
  1071.     LD    (HSTTRK),HL
  1072.     LD    A,(RECHST)
  1073.     LD    (HSTSEC),A
  1074.     LD    A,(RCFLAG)    ; Need to read ?
  1075.     OR    A
  1076.     CALL    NZ,REDHST    ; Yes
  1077.     XOR    A
  1078.     LD    (HSTWRT),A    ; No pending write
  1079. ;
  1080. MATCH:    LD    DE,(DMAADR)
  1081.     LD    HL,(RECBUF)
  1082.     LD    A,(READOP)    ; Which way to move ?
  1083.     OR    A
  1084.     JP    NZ,RWMOVE    ; Skip if read
  1085.     LD    A,1
  1086.     LD    (HSTWRT),A    ; Mark buffer changed
  1087.     EX    DE,HL        ; Hl=DMA  DE=buffer
  1088. ;
  1089. RWMOVE:    LD    BC,128        ; Byte count
  1090.     LDIR            ; Block move
  1091.     LD    A,(WRTYPE)    ; Write type
  1092.     CP    1        ; To directory ?
  1093.     JP    NZ,RWEXIT    ; Done
  1094.     LD    A,(ERFLAG)    ; Check for errors
  1095.     OR    A
  1096.     JP    NZ,RWEXIT    ; Do not write directory if so
  1097.     XOR    A
  1098.     LD    (HSTWRT),A    ; Show buffer written
  1099.     CALL    WRTHST        ; Write buffer
  1100. ;
  1101. RWEXIT:    LD    A,(ERFLAG)
  1102.     RET
  1103. ;
  1104. ; Disk read, call BIOS to fill the buffer with one physical record
  1105. ;
  1106. REDHST:    CALL    RWINIT        ; Init CP/M 3.0 BIOS
  1107.     LD    A,13        ; READ function
  1108.     JP    DORW        ; Go do it
  1109. ;
  1110. ; Disk write, call BIOS to write one phy record from buffer
  1111. ;
  1112. WRTHST:    CALL    RWINIT        ; Init CP/M 3.0 BIOS
  1113.     LD    A,14        ; WRITE function
  1114. ;
  1115. ; Call BIOS to read (or write) 1 physical record to (or from) buffer
  1116. ;
  1117. DORW:    CALL    XBIOS3        ; Go do it to the record
  1118.     LD    (ERFLAG),A
  1119.     RET
  1120. ;
  1121. ; Translate record, set track, record, DMA buffer and DMA bank
  1122. ;
  1123. RWINIT:    LD    HL,(HSTTRK)    ; Get physical track number
  1124.     LD    (BCREG),HL    ; Put track number in BC
  1125.     LD    A,10        ; SETTRK function
  1126.     CALL    XBIOS3
  1127.     LD    A,(HSTSEC)    ; Get physical record number
  1128.     LD    L,A
  1129.     LD    H,0
  1130.     LD    (BCREG),HL    ; Put record number in BC
  1131.     LD    HL,(RECTBL)    ; Address of xlate table
  1132.     LD    (DEREG),HL    ; Xlate address in DE
  1133.     LD    A,16        ; SECTRN function
  1134.     CALL    XBIOS3        ; Get skewed record number
  1135.     LD    A,L
  1136.     LD    (ACTREC),A    ; Actual record
  1137.     LD    (BCREG),HL    ; Record number in BC
  1138.     LD    A,11        ; SETSEC function
  1139.     CALL    XBIOS3        ; Set CP/M 3.0 record
  1140.     LD    HL,(HSTBUF)    ; Get record buffer address
  1141.     LD    (BCREG),HL    ; Buffer address in BC
  1142.     LD    A,12        ; SETDMA function
  1143.     CALL    XBIOS3
  1144.     LD    A,1        ; DMA bank number
  1145.     LD    (AREG),A    ; Put bank number in A
  1146.     LD    A,28        ; SETBNK function
  1147.     CALL    XBIOS3        ; Set DMA bank
  1148.     RET
  1149. ;
  1150. ; Routine to call banked BIOS routines via BDOS function 50.
  1151. ; All disk I/O calls are made through here.
  1152. ;
  1153. XBIOS3:    LD    (BIOSPB),A    ; Set BIOS function
  1154.     LD    C,50        ; Direct BIOS call function
  1155.     LD    DE,BIOSPB    ; BIOS parameter block
  1156.     JP    BDOS        ; Jump to BDOS
  1157. ;
  1158. ;-----------------------------------------------------------------------
  1159. ;
  1160. ; Messages
  1161. ;
  1162. NDZ80:    DB    CR,LF,'Z80 needed',CR,LF,0
  1163. ;
  1164. FAK1M:    DB    CR,LF,LF,'If MORE than ',0
  1165. FAK2M:    DB    ' directory entries exist,'
  1166.     DB    CR,LF,'please reduce entries '
  1167.     DB    'and/or use DU first.',BEL
  1168.     DB    CR,LF,'Continue with MORE will'
  1169.     DB    ' destroy directory!'
  1170.     DB    CR,LF,LF,'Press ''Y'' to '
  1171.     DB    'continue, else aborts: ',0
  1172. ;
  1173. DONEM:    DB    'Done',CR,LF,0
  1174. READM:    DB    CR,LF,LF,'Read, ',0
  1175. PRESM:    DB    '(Previously-sorted) ',0
  1176. WRITM:    DB    'Write, ',0
  1177. ERORM:    DB    BS,BS,' Error',BEL,CR,LF,0
  1178. SORTM:    DB    'Sort, ',0
  1179. ;
  1180. ;-----------------------------------------------------------------------
  1181. ;
  1182. ; Data area
  1183. ;
  1184. DATA    EQU    $
  1185. ;
  1186. ; Bios parameter block for CP/M 3.0
  1187. ;
  1188. BIOSPB:    DS    1        ; BIOS function
  1189. AREG:    DS    1        ; A  register
  1190. BCREG:    DS    2        ; BC register
  1191. DEREG:    DS    2        ; DE register
  1192. HLREG:    DS    2        ; HL register
  1193. ;
  1194. HSTBUF:    DS    2        ; Cp/m 3.0 disk I/O buffer address
  1195. ;
  1196. ;-----------------------------------------------------------------------
  1197. ;
  1198. ; Disk parameter block for CP/M 2.2 or 3.0
  1199. ;
  1200. DPB:
  1201. SPT:    DS    2
  1202. BSH:    DS    1
  1203. BLM:    DS    1
  1204. EXM:    DS    1
  1205. DSM:    DS    2
  1206. DRM:    DS    2
  1207. AL0:    DS    1
  1208. AL1:    DS    1
  1209. CKS:    DS    2
  1210. SYSTRK:    DS    2
  1211. PSH:    DS    1        ; Physical shift count (CP/M 3.0)
  1212. PSM:    DS    1        ; Physical record mask (CP/M 3.0)
  1213. ;
  1214. ;-----------------------------------------------------------------------
  1215. ;
  1216. ; General data area used by the program
  1217. ;
  1218. MEMTOP:    DS    2        ; Memory top address
  1219. PRGBUF:    DS    2        ; Address of the program buffer
  1220. PRGMAX:    DS    2        ; Free bytes for program buffer
  1221. ;
  1222. DIRCNT:    DS    2
  1223. ICT:    DS    2
  1224. JCT:    DS    2
  1225. NOSWAP:    DS    1
  1226. RECTBL:    DS    2
  1227. RECORD:    DS    2
  1228. WRFLAG:    DS    1
  1229. SRECLN:    DS    2
  1230. SSTADR:    DS    2
  1231. SSRTV1:    DS    2
  1232. SSRTV2:    DS    2
  1233. SSRTV3:    DS    2
  1234. SSRTV4:    DS    2
  1235. SNRECW:    DS    2
  1236. ;
  1237. ;-----------------------------------------------------------------------
  1238. ;
  1239. ; Following used by the program and CP/M 3.0
  1240. ;
  1241. LOGDSK:    DS    1        ; Logical disk number
  1242. LOGTRK:    DS    2        ; Logical track number
  1243. LOGREC:    DS    1        ; Logical record number
  1244. ;
  1245. ;-----------------------------------------------------------------------
  1246. ;
  1247. ; Following used by CP/M 3.0
  1248. ;
  1249. HSTDSK:    DS    1        ; Physical disk number
  1250. HSTTRK:    DS    2        ; Physical track number
  1251. HSTSEC:    DS    1        ; Physical record number
  1252. ;
  1253. ACTREC:    DS    1        ; Skewed physical record
  1254. RECHST:    DS    1        ; Tempopary physical record
  1255. HSTACT:    DS    1        ; Buffer active flag, initially 0
  1256. HSTWRT:    DS    1        ; Buffer changed flag, initially 0
  1257. ;
  1258. UNACNT:    DS    1        ; Unallocated record count
  1259. UNADSK:    DS    1        ; Unallocated disk number
  1260. UNATRK:    DS    2        ; Unallocated track number
  1261. UNAREC:    DS    1        ; Unallocated record number
  1262. RECBUF:    DS    2        ; Logical record address in buffer
  1263. ;
  1264. ERFLAG:    DS    1        ; Error reporting
  1265. RCFLAG:    DS    1        ; Force record read
  1266. READOP:    DS    1        ; 1 if read operation
  1267. WRTYPE:    DS    1        ; Write operation type
  1268. DMAADR:    DS    2        ; Last DMA address
  1269. ;
  1270. ;-----------------------------------------------------------------------
  1271. ;
  1272. ; Stack and buffer area for the program
  1273. ;
  1274.     DS    40        ; Minimum stack (20 levels)
  1275. EVEN    EQU    ($+255)/256*256    ; Start buffer on even page
  1276.                 ; Also increases stack greatly
  1277.     ORG    EVEN
  1278. STACK    EQU    $-2
  1279. DATSIZ    EQU    $-DATA        ; Size of data area
  1280.                 ; Buffers start here
  1281. ;
  1282.     END
  1283.