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 / CPM / BDOS / Z80DS231.LBR / Z80DDISK.ZZ0 / Z80DDISK.Z80
Text File  |  2000-06-30  |  45KB  |  1,688 lines

  1.  
  2. ; Z80DOS - Z80 Disk Operating System                Nov 15, 1988
  3. ;
  4. ; Version 2.31    Fast file lookup for random records fix
  5. ; Date:     15 Nov 88
  6. ; Update:    Eugene Nolan
  7. ;
  8. ;-----------------------------------------------------------------------
  9. ;
  10. ; Version 2.3    Fast file lookup, ZRL compatibility
  11. ; Date:     4 Nov 88
  12. ; Update:    Eugene Nolan
  13. ;
  14. ;-----------------------------------------------------------------------
  15. ;
  16. ; Version 2.0a - BETA TEST VERSION - 6 Nov 87 by Carson Wilson
  17. ;
  18. ; Support file: Z80DDISK.Z80
  19. ; Version:    2.0
  20. ; Date:     6 Nov 87
  21. ; Author:    Carson Wilson
  22. ; Description:    DOS Return CP/M Version, Disk Functions
  23. ;
  24. ; Changes:    --------
  25. ;        Changed READR and WRITER to use a common error function,
  26. ;        RWERR, which displays "Data error on D:".
  27. ;
  28. ;        New disk will be overwritten, data from the first file
  29. ;        will probably be lost.
  30. ;
  31. ;        --------
  32. ;        Command 37 (reset individual disk) now resets the disk
  33. ;        changed vector instead of the drive R/O vector.
  34. ;
  35. ;        --------
  36. ;        Removed code which made public files read-only from
  37. ;        other user areas.  The user must now manually set public
  38. ;        files to read-only using the R/O attribute (t1).  This
  39. ;        change was made because some applications must write to
  40. ;        public files.
  41. ;
  42. ;        --------
  43. ;        System files are now R/W unless referenced by wildcards.
  44. ;
  45. ;-----------------------------------------------------------------------
  46. ;
  47. ; Return version number
  48. ;
  49. ;-----------------------------------------------------------------------
  50. ;
  51. CMND12:    LD    A,22H        ; Set version number
  52.     LD    IX,3800H    ; This will put an '8' into D
  53. ;                ; Register upon return, saying
  54. ;                ; Z80DOS operating
  55.     JR    CMD25A        ; And exit
  56. ;
  57. ;-----------------------------------------------------------------------
  58. ;
  59. ;    Disk functions
  60. ;
  61. ;-----------------------------------------------------------------------
  62. ;
  63. ; Reset disk system
  64. ;
  65. CMND13:    LD    HL,0        ; Load zero
  66.     LD    (LOGIN),HL    ; All drives logged out
  67.     LD    (DSKRO),HL    ; All drives read/write
  68.     LD    (DIFF),HL    ; No disks changed <crw>
  69.     LD    HL,RAMLOW+80H    ; Set up DMA address
  70.     LD    (DMA),HL    ; And save it
  71.     CALL    STDMA        ; Do BIOS call
  72.     XOR    A        ; Set default drive = 'A'
  73.     LD    (DEFDRV),A    ; Save it
  74.     LD    A,RESDSK    ; <crw>
  75.     CALL    SELDK        ; Select drive 0=A, 1=B, etc.
  76.     LD    A,(SUBFLG)    ; Get submit flag
  77.     JR    CMD25A        ; Exit
  78. ;
  79. ; Search for file
  80. ;
  81. CMND17:    CALL    SELDRV        ; Select drive from FCB
  82.     LD    A,(IX+0)    ; Get drive number from FCB
  83.     SUB    '?'        ; Test if '?'
  84.     JR    Z,CMD17B    ; If so all entries match
  85.     LD    A,(IX+14)    ; Get system byte
  86.     CP    '?'        ; Test if '?'
  87.     JR    Z,CMD17A    ; Yes, jump
  88.     LD    (IX+14),0    ; Load system byte with zero
  89. ;
  90. CMD17A:    LD    A,15        ; Test first 15 items in FCB
  91. ;
  92. CMD17B:    CALL    SEARCH        ; Do search
  93. ;
  94. CMD17C:    LD    HL,(DIRBUF)    ; Copy directory buffer
  95.     LD    DE,(DMA)    ; To DMA address
  96.     LD    BC,128        ; Directory=128 bytes
  97.     LDIR
  98.     RET            ; Exit
  99. ;
  100. ; Search for next occurrence of file
  101. ;
  102. CMND18:    LD    IX,(DCOPY)    ; Get last FCB used by search
  103.     CALL    SELDRV        ; Select drive from FCB
  104.     CALL    SEARCN        ; Search next file match
  105.     JR    CMD17C        ; And copy directory to DMA address
  106. ;
  107. ; Delete file
  108. ;
  109. CMND19:    CALL    SELDRV        ; Select drive from FCB
  110.     CALL    DELETE        ; Delete file
  111. ;
  112. CMD19A:    LD    A,(SEAREX)    ; Get exit byte 00=file found,0ffh not
  113.     JR    CMD25A        ; And exit
  114. ;
  115. ; Rename file
  116. ;
  117. CMND23:    CALL    SELDRV        ; Select drive from FCB
  118.     CALL    RENAM        ; Rename file
  119.     JR    CMD19A        ; And exit
  120. ;
  121. ; Return login vector
  122. ;
  123. CMND24:    LD    HL,(LOGIN)    ; Get login vector
  124. ;
  125. CMD24A:    LD    (PEXIT),HL    ; Save it
  126.     RET            ; And exit
  127. ;
  128. ; Return current drive
  129. ;
  130. CMND25:    LD    A,(DEFDRV)    ; Get current drive
  131. ;
  132. CMD25A:    JP    EXIT        ; And exit
  133. ;
  134. ; Return allocation vector
  135. ;
  136. CMND27:    LD    HL,(ALV)    ; Get allocation vector
  137.     JR    CMD24A        ; And exit
  138. ;
  139. ; Return disk R/O vector
  140. ;
  141. CMND29:    LD    HL,(DSKRO)    ; Get disk R/O vector
  142.     JR    CMD24A        ; And exit
  143. ;
  144. ; Set file attributes
  145. ;
  146. CMND30:    CALL    SELDRV        ; Select drive from FCB
  147.     CALL    CSTAT        ; Change status
  148.     JR    CMD19A        ; And exit
  149. ;
  150. ; Get Disk Parameter Block Address
  151. ;
  152. CMND31:    LD    HL,(IXP)    ; Get drive table
  153.     JR    CMD24A        ; And exit
  154. ;
  155. ; Set/get user code
  156. ;
  157. CMND32:    LD    A,E        ; Get user code
  158.     INC    A        ; Test if 0ffh
  159.     LD    A,(USER)    ; Get old user code
  160.     JR    Z,CMD25A    ; If 0ffh then exit
  161.     LD    A,E        ; Get new user code
  162.     AND    01FH        ; Mask it
  163.     LD    (USER),A    ; Save it
  164.     RET            ; And exit
  165. ;
  166. ; Compute file size
  167. ;
  168. CMND35:    CALL    SELDRV        ; Select drive from FCB
  169.     CALL    FILSZ        ; Compute file size
  170.     JR    CMD19A        ; And exit
  171. ;
  172. ; Set random record count
  173. ;
  174. CMND36:    LD    HL,32        ; Set pointer to next record
  175.     CALL    CALRRC        ; Calculate random record count
  176. ;
  177. LDRRC:    LD    (IX+33),D    ; And save random record count
  178.     LD    (IX+34),C
  179.     LD    (IX+35),B
  180.     RET            ; And exit
  181. ;
  182. ; Reset individual disk drives from vector in DE
  183. ;
  184. CMND37:    LD    A,E        ; Get mask LSB
  185.     CPL            ; Complement it
  186.     LD    E,A
  187.     LD    A,D        ; Get mask MSB
  188.     CPL            ; Complement it
  189.     LD    D,A
  190.     LD    HL,(LOGIN)    ; Get login vector
  191.     LD    A,E        ; Mask login vector
  192.     AND    L        ; LSB
  193.     LD    L,A
  194.     LD    A,D        ; Mask login vector
  195.     AND    H        ; MSB
  196.     LD    H,A
  197.     LD    (LOGIN),HL    ; Save login vector
  198.     EX    DE,HL        ; Use login vector as mask
  199.     LD    HL,(DIFF)    ; Get disk changed vector <crw>
  200.     LD    A,E        ; Mask drive R/O vector
  201.     AND    L        ; LSB
  202.     LD    L,A
  203.     LD    A,D        ; Mask drive R/O vector
  204.     AND    H        ; LSB
  205.     LD    H,A
  206.     LD    (DIFF),HL    ; Save disk changed vector <crw>
  207.     RET            ; And exit
  208. ;
  209. ; Select disk from FCB
  210. ;
  211. SELDRV:    LD    A,0FFH        ; Set disk select done flag
  212.     LD    (FLDRV),A
  213.     LD    A,(DEFDRV)    ; Get current drive
  214.     LD    (DRIVE),A    ; Save it in memory
  215.     LD    E,A        ; Save it in register e
  216.     LD    A,(IX+0)    ; Get drive from FCB
  217.     LD    (FCB0),A    ; Save it
  218.     LD    D,A
  219.     CP    '?'        ; Test if '?'
  220.     JR    Z,CMND14    ; Yes, then select drive from register e
  221.     AND    01FH        ; Mask drive
  222.     LD    A,E        ; Test if zero
  223.     JR    Z,SELDR0    ; Select drive from register e
  224.     LD    A,D
  225.     DEC    A        ; Decrement drive
  226. ;
  227. SELDR0:    CALL    SELDK        ; Select drive
  228.     LD    A,(IX+0)    ; Get drive from FCB
  229.     AND    0E0H        ; Remove drive bits
  230.     LD    B,A        ; Save register
  231.     LD    A,(USER)    ; Get user number
  232.     OR    B        ; Insert user number in FCB
  233.     LD    (IX+0),A
  234.     RET            ; And exit
  235. ;
  236. ; Select disk
  237. ;
  238. CMND14:    LD    A,E        ; Copy drive number
  239. ;
  240. SELDK:    AND    0FH        ; Mask drive number to 0-15
  241.     LD    B,A        ; Save counter
  242.     LD    DE,(LOGIN)    ; Get login vector
  243.     OR    A        ; Test drive 'a'
  244.     JR    Z,SELDK1    ; Yes then jump
  245. ;
  246. SELDK0:    RR    D        ; Shift login vector
  247.     RR    E        ; Until bit 0 register e
  248.     DJNZ    SELDK0        ; Is current drive
  249. ;
  250. SELDK1:    LD    HL,DEFDRV    ; Get pointer last drive
  251.     BIT    0,E        ; Test if drive logged in
  252.     JR    Z,SELDK2    ; No, login drive
  253.     CP    (HL)        ; Test same drive
  254.     RET    Z        ; Yes then exit
  255. ;
  256. SELDK2:    LD    (HL),A        ; Save new current drive
  257.     PUSH    DE        ; Save drive logged in flag
  258.     LD    C,A
  259.     CALL    SELDSK        ; Do BIOS select
  260.     LD    A,H        ; Test if error
  261.     OR    L
  262.     JR    Z,SELDK3    ; Yes, illegal drive number
  263.     LD    E,(HL)        ; Get LSB translation vector
  264.     INC    HL        ; Increment pointer
  265.     LD    D,(HL)        ; Get MSB translation vector
  266.     INC    HL        ; Increment pointer
  267.     LD    (TRANS),DE    ; Save translation vector
  268.     LD    (TEMP0),HL    ; Save address temp0
  269.     LD    DE,6
  270.     ADD    HL,DE        ; Point to dirbuf pointer <crw>
  271.     LD    DE,DIRBUF    ; Load dirbuf pointer
  272.     LD    BC,8        ; Copy pointers to dirbuf,
  273.     LDIR            ; Csv (wacd), alv from BIOS
  274.     LD    HL,(IXP)    ; Get drive parameter address
  275.     LD    C,15        ; Copy 15 bytes
  276.     LDIR
  277.     POP    DE        ; Get drive logged in flag
  278.     BIT    0,E        ; Test it
  279.     RET    NZ        ; Drive logged in so return
  280.     LD    HL,(LOGIN)    ; Get login vector
  281.     CALL    SDRVB        ; Set drive bit in login vector
  282.     LD    (LOGIN),HL    ; Save login vector
  283.     JR    INITDR        ; And setup drive tables
  284. ;
  285. SELDK3:    LD    HL,(STSEL)    ; Load error message address
  286.     JP    (HL)        ; And display error
  287. ;
  288. ; Init drive
  289. ;  Clear allocation vector bit buffer after drive reset
  290. ;
  291. INITDR:    LD    DE,(MAXLEN)    ; Get length alv buffer-1 (bits)
  292.     LD    A,3        ; Divide by 8
  293. ;
  294. INITD0:    SRL    D        ; To get bytes
  295.     RR    E
  296.     DEC    A
  297.     JR    NZ,INITD0
  298.     INC    DE        ; Increment, so all bits are cleared
  299.     LD    HL,(ALV)    ; Get pointer alv buffer
  300.     PUSH    HL
  301. ;
  302. INITD1:    LD    (HL),0        ; Clear 8 bits
  303.     INC    HL        ; Increment pointer
  304.     DEC    DE        ; Decrement counter
  305.     LD    A,D        ; Test if counter zero
  306.     OR    E
  307.     JR    NZ,INITD1    ; Not then jump
  308.     POP    HL        ; Get alv pointer
  309.     LD    DE,(NDIR0)    ; Get first two bytes alv buffer
  310.     LD    (HL),E        ; Save LSB
  311.     INC    HL        ; Increment pointer
  312.     LD    (HL),D        ; Save MSB
  313.     LD    HL,(TEMP0)    ; Clear number of files
  314.     XOR    A        ; On this drive
  315.     LD    (HL),A        ; Clear LSB
  316.     INC    HL        ; Increment pointer
  317.     LD    (HL),A        ; Clear MSB
  318.     LD    (SUBFLG),A    ; Clear submit flag (reset disk command)
  319.     CALL    SETFCT        ; Set file count
  320. ;
  321. INITD2:    LD    A,0FFH        ; Update directory checksum
  322.     CALL    RDDIR        ; Read FCB's from directory
  323.     CALL    TSTFCT        ; Test last FCB
  324.     RET    Z        ; Yes then exit
  325.     CALL    CALDIR        ; Calculate entry point FCB
  326.     LD    A,(HL)        ; Get first byte FCB
  327.     CP    0E5H        ; Test empty directory entry
  328.     JR    Z,INITD2    ; Yes then get next FCB
  329.     CP    021H        ; Test time stamp
  330.     JR    Z,INITD2    ; Yes then get next FCB
  331.     LD    A,(USER)    ; Get user number
  332.     CP    (HL)        ; Test if user is same
  333.     JR    NZ,INITD3    ; No then jump
  334.     INC    HL        ; Point to file name
  335.     LD    A,(HL)        ; Get first char filename
  336.     SUB    '$'        ; Test if '$'
  337.     JR    NZ,INITD3    ; Not then jump
  338.     DEC    A        ; Load a with 0ffh
  339.     LD    (SUBFLG),A    ; Save it in subflg
  340. ;
  341. INITD3:    LD    C,1        ; Set bit in alv buffer
  342.     CALL    FILLBB        ; Set bits from FCB in alv buffer
  343.     CALL    SETLF        ; Update last file count
  344.     JR    INITD2        ;
  345. ;
  346. ; Set drive bit from (defdrv) in HL
  347. ;    Exit:    DE = HL before setting bit (if any)
  348. ;
  349. SDRVB:    EX    DE,HL        ; Copy hl=>de
  350.     LD    HL,1        ; Get mask drive "a"
  351.     LD    A,(DEFDRV)    ; Get current drive
  352.     OR    A        ; Test if drive "a"
  353.     JR    Z,SDRVB1    ; Yes then done
  354. ;
  355. SDRVB0:    ADD    HL,HL        ; Get next mask
  356.     DEC    A        ; Decrement drive counter
  357.     JR    NZ,SDRVB0    ; And test if done
  358. ;
  359. SDRVB1:    LD    A,D        ; Hl=hl or de
  360.     OR    H
  361.     LD    H,A
  362.     LD    A,E
  363.     OR    L
  364.     LD    L,A
  365.     RET            ; Exit
  366. ;
  367. ; Calculate sector/track directory
  368. ;
  369. STDIR:    LD    HL,(FILCNT)    ; Get FCB counter directory
  370.     SRL    H        ; Divide by 4
  371.     RR    L        ; (4 FCB's / sector)
  372.     SRL    H
  373.     RR    L
  374.     LD    (RECDIR),HL    ; Save value (used by checksum)
  375.     EX    DE,HL        ; Copy it to de
  376.     LD    HL,0        ; Clear hl
  377. ;
  378. ; Calculate sector/track
  379. ;    Entry:    hl,de = sector number (128 byte sector)
  380. ;    Exit:    set track  = hl,de  /  maxsec
  381. ;        set sector = hl,de mod maxsec
  382. ;
  383. CALST:    LD    BC,(MAXSEC)    ; Get sectors/track
  384.     LD    A,17        ; Set up loop counter
  385. ;
  386. CALST0:    OR    A        ; Test hl>=bc
  387.     SBC    HL,BC
  388.     CCF
  389.     JR    C,CALST1    ; Yes then jump
  390.     ADD    HL,BC        ; No then restore hl
  391.     OR    A        ; And clear carry
  392. ;
  393. CALST1:    RL    E        ; Shift result in de
  394.     RL    D
  395.     DEC    A        ; Test last bit done
  396.     JR    Z,CALST2    ; Yes then exit
  397.     RL    L        ; Shift next bit in hl
  398.     RL    H
  399.     JR    CALST0        ; Continue
  400. ;
  401. CALST2:    PUSH    HL        ; Save sector number
  402.     LD    HL,(NFTRK)    ; Get first track
  403.     ADD    HL,DE        ; Add track number
  404.     LD    B,H        ; Copy it to bc
  405.     LD    C,L
  406.     CALL    SETTRK        ; BIOS call set track
  407.     POP    BC        ; Restore sector number
  408.     LD    DE,(TRANS)    ; Get translation table address
  409.     CALL    SECTRN        ; BIOS call sector translation
  410.     LD    B,H        ; Copy result to bc
  411.     LD    C,L
  412.     JP    SETSEC        ; BIOS call set sector
  413. ;
  414. ; Get disk map block number from FCB
  415. ;
  416. ; Exit: HL = address FCB
  417. ;    DE = disk map
  418. ;    BC = offset in disk map
  419. ;
  420. GETDM:    LD    C,(IX+32)    ; Get next record
  421.     LD    A,(NBLOCK)    ; Get number of blocks
  422.     LD    B,A        ; Save it
  423. ;
  424. GETDM0:    SRL    C        ; Shift next record
  425.     DJNZ    GETDM0        ; Number of blocks times
  426. ;
  427. GETDM1:    CPL            ; Complement number of blocks
  428.     ADD    A,9        ; Add 9
  429.     LD    B,A        ; B=8-number of blocks
  430.     LD    A,(NEXTND)    ; Get extend mask
  431.     AND    (IX+12)        ; Mask with extend
  432.     RRCA            ; Rotate one right
  433. ;
  434. GETDM2:    RLCA            ; Rotate one left
  435.     DJNZ    GETDM2        ; 8-number of blocks times
  436. ;
  437. GETDM3:    ADD    A,C        ; Add the two values to get entry FCB
  438. ;
  439. GETDM4:    PUSH    IX        ; Get FCB address
  440.     POP    HL
  441.     LD    C,16        ; Add offset 16 to point to dm
  442.     ADD    HL,BC
  443.     LD    C,A        ; Add entry FCB
  444.     ADD    HL,BC
  445.     LD    A,(MAXLEN+1)    ; Test 8 bits/16 bits FCB entry
  446.     OR    A
  447.     JR    NZ,GETDM5    ; 16 bits => jump
  448.     LD    E,(HL)        ; Get 8 bit value
  449.     LD    D,A        ; Make MSB zero
  450.     RET            ; And exit
  451. ;
  452. GETDM5:    ADD    HL,BC        ; Add twice (16 bit values)
  453.     LD    E,(HL)        ; Get LSB
  454.     INC    HL        ; Increment pointer
  455.     LD    D,(HL)        ; Get MSB
  456.     DEC    HL        ; Decrement pointer
  457.     RET            ; And exit
  458. ;
  459. ; Calculate sector number
  460. ;  entry: de=block number from FCB
  461. ;
  462. CALSEC:    LD    HL,0        ; Clear MSB sector number
  463.     LD    A,(NBLOCK)    ; Get loop counter
  464.     LD    B,A        ; Save it in b
  465. ;
  466. CALSC0:    SLA    E        ; Shift l,d,e
  467.     RL    D
  468.     RL    L
  469.     DJNZ    CALSC0        ; B times
  470. ;
  471. CALSC1:    LD    A,(NMASK)    ; Get sector mask
  472.     AND    (IX+32)        ; And with next record
  473.     OR    E        ; Set up LSB sector number
  474.     LD    E,A
  475.     RET            ; And exit
  476. ;
  477. ; Calculate dirbuf entry point
  478. ;
  479. CALDIR:    LD    HL,(DIRBUF)    ; Get start address dirbuf
  480.     LD    A,(SECPNT)    ; Get sector pointer
  481.     ADD    A,L        ; Add l=l+a
  482.     LD    L,A
  483.     RET    NC        ; No carry exit
  484.     INC    H        ; Increment h
  485.     RET            ; And exit
  486. ;
  487. ; Init file count
  488. ;
  489. SETFCT:    LD    HL,-1        ; Set up file count
  490.     LD    (FILCNT),HL    ; Save it
  491.     RET            ; And exit
  492. ;
  493. ; Test file count
  494. ;
  495. ; Exit: Zero flag set and A = 0 if filcnt = 0ffffh
  496. ;
  497. TSTFCT:    LD    HL,(FILCNT)    ; Test file count=0ffffh
  498.     LD    A,H        ; Get MSB
  499.     AND    L        ; And LSB
  500.     INC    A        ; Test if result=0ffh
  501.     RET            ; And exit
  502. ;
  503. ; Set last file
  504. ;
  505. SETLF:    CALL    TSTLF        ; Test last file
  506.     RET    C        ; No then exit
  507.     INC    DE        ; Increment last file
  508.     LD    (HL),D        ; Save it in temp0
  509.     DEC    HL
  510.     LD    (HL),E
  511.     RET            ; And exit
  512. ;
  513. ; Test last file
  514. ;
  515. TSTLF:    LD    HL,(TEMP0)    ; Get pointer to last file
  516.     LD    DE,(FILCNT)    ; Get file counter
  517.     LD    A,E        ; Subtract filcnt-(temp0)
  518.     SUB    (HL)
  519.     INC    HL
  520.     LD    A,D
  521.     SBC    A,(HL)        ; Carry means (temp0) > filcnt
  522.     RET            ; Exit
  523. ;
  524. ; Get next FCB from drive
  525. ;    Entry:    A = 0 check checksum
  526. ;        A = 0ffh update checksum
  527. ;
  528. RDDIR:    LD    C,A        ; Save checksum flag
  529.     LD    HL,(FILCNT)    ; Get file counter
  530.     INC    HL        ; Increment it
  531.     LD    (FILCNT),HL    ; And save it
  532.     LD    DE,(NFILES)    ; Get maximum number of files
  533.     OR    A        ; Clear carry
  534.     SBC    HL,DE        ; Test if last file
  535.     ADD    HL,DE
  536.     JR    Z,RDDIR0    ; No, jump
  537.     JR    NC,SETFCT    ; Yes, set file count to 0ffffh
  538. ;
  539. RDDIR0:    LD    A,L        ; Get file count LSB
  540.     ADD    A,A        ; *32
  541.     ADD    A,A
  542.     ADD    A,A
  543.     ADD    A,A
  544.     ADD    A,A
  545.     AND    060H        ; Mask it
  546.     LD    (SECPNT),A    ; Save it for later use
  547.     RET    NZ        ; Return if not first FCB sector
  548.     PUSH    BC        ; Save checksum flag
  549.     CALL    STDIR        ; Calculate sector/track directory
  550.     CALL    READDR        ; Read sector directory
  551.     POP    BC        ; Restore checksum flag
  552. ;
  553. ; Update/check checksum directory
  554. ; Entry C=0 check checksum, C=0ffh update checksum
  555. ;
  556. CHKDIR:    LD    HL,(NCHECK)    ; Get number of checked records
  557.     LD    A,H
  558.     OR    L
  559.     RET    Z
  560.     LD    DE,(RECDIR)    ; Get current record
  561.     OR    A        ; Clear carry
  562.     SBC    HL,DE        ; Test current record
  563.     RET    Z        ; Exit if zero
  564.     RET    C        ; Exit if greater then ncheck
  565.     LD    HL,(DIRBUF)    ; Get dirbuf
  566.     LD    B,128        ; Set up counter
  567.     XOR    A        ; Clear checksum
  568. ;
  569. CHKDR0:    ADD    A,(HL)        ; Add checksum
  570.     INC    HL        ; Increment pointer
  571.     DJNZ    CHKDR0        ; 128 times
  572.     LD    HL,(CSV)    ; Get pointer checksum directory
  573.     ADD    HL,DE        ; Add current record
  574.     INC    C        ; Test checksum flag
  575.     JR    Z,CHKDR1    ; 0ffh=> update checksum
  576.     CP    (HL)        ; Test checksum
  577.     RET    Z        ; Exit if ok
  578.     LD    HL,(DIFF)    ; Get disk changed vector
  579.     CALL    SDRVB        ; Include drive bit
  580.     LD    (DIFF),HL    ; Save disk changed bit
  581.     JP    SETFN        ; Set # files to maximum
  582. ;
  583. CHKDR1:    LD    (HL),A        ; Update checksum
  584.     RET            ; And exit
  585. ;
  586. ; Read sector from drive
  587. ;
  588. READR:    CALL    READ        ; BIOS call read sector
  589.     JR    WRITE0        ; Test exit code
  590. ;
  591. ; Write sector on drive
  592. ;
  593. WRITER:    CALL    WRITE        ; BIOS call write sector
  594. ;
  595. WRITE0:    OR    A        ; Test exit code
  596.     RET    Z        ; Exit if ok
  597.     LD    HL,(STRW)    ; Point to data error routine
  598.     LD    (RETFLG),A    ; Allow retry for read/write errors
  599.     JP    (HL)        ; Display "Data error on d:"
  600. ;
  601. ; Read directory from drive
  602. ;
  603. READDR:    CALL    DMADIR        ; Set up DMA directory
  604.     CALL    READR        ; Read record
  605.     JR    STDMA        ; Set up DMA user
  606. ;
  607. ; Write directory on drive
  608. ;
  609. WRITDR:    LD    C,0FFH        ; Update checksum directory
  610.     CALL    CHKDIR
  611.     CALL    DMADIR        ; Set up DMA directory
  612.     LD    C,1        ; Write directory flag
  613.     CALL    WRITER        ; Write record
  614.     JR    STDMA        ; Set up DMA user
  615. ;
  616. ; Set DMA address command
  617. ;
  618. CMND26:    LD    (DMA),DE    ; Save DMA address
  619. ;
  620. STDMA:    LD    BC,(DMA)    ; Get DMA address
  621.     JR    DMADR0        ; And do BIOS call
  622. ;
  623. ; Set DMA address directory
  624. ;
  625. DMADIR:    LD    BC,(DIRBUF)    ; Get DMA address directory
  626. ;
  627. DMADR0:    JP    SETDMA        ; BIOS call set DMA
  628. ;
  629. ; Get bit from allocation vector buffer
  630. ;
  631. ;    Entry:    DE = block number
  632. ;    Exit:    A  = bit in LSB
  633. ;        B  = bitnumber in a
  634. ;        HL = pointer in alv buffer
  635. ;
  636. GETBIT:    LD    A,E        ; Get bit number
  637.     AND    7        ; Mask it
  638.     INC    A        ; Add 1
  639.     LD    B,A        ; Save it
  640.     LD    C,A        ; Twice
  641.     SRL    D        ; Get byte number
  642.     RR    E        ; De=de/8
  643.     SRL    D
  644.     RR    E
  645.     SRL    D
  646.     RR    E
  647.     LD    HL,(ALV)    ; Get start address alv buffer
  648.     ADD    HL,DE        ; Add byte number
  649.     LD    A,(HL)        ; Get 8 bits
  650. ;
  651. GETBT0:    RLCA            ; Get correct bit
  652.     DJNZ    GETBT0
  653.     LD    B,C        ; Restore bit number
  654.     RET            ; And return to caller
  655. ;
  656. ; Set/reset bit in allocation vector buffer
  657. ;    Entry    DE = block number
  658. ;         C = 0 reset bit, c=1 set bit
  659. ;
  660. SETBIT:    PUSH    BC        ; Save set/reset bit
  661.     CALL    GETBIT        ; Get bit
  662.     AND    0FEH        ; Mask it
  663.     POP    DE        ; Get set/reset bit
  664.     OR    E        ; Set/reset bit
  665. ;
  666. SETBT0:    RRCA            ; Rotate bit in correct position
  667.     DJNZ    SETBT0
  668.     LD    (HL),A        ; Save 8 bits
  669.     RET            ; And return to caller
  670. ;
  671. ; Fill bit buffer from FCB in dirbuf
  672. ;    Entry:    C = 0 reset bit
  673. ;        C = 1 set bit
  674. ;
  675. FILLBB:    CALL    CALDIR        ; Get directory entry
  676.     LD    DE,16        ; Get offset dm block
  677.     ADD    HL,DE        ; Add offset
  678.     LD    B,E        ; Get block counter
  679. ;
  680. FILLB0:    LD    E,(HL)        ; Get LSB block number
  681.     INC    HL        ; Increment pointer
  682.     LD    D,0        ; Reset MSB block number
  683.     LD    A,(MAXLEN+1)    ; Test >256 blocks present
  684.     OR    A
  685.     JR    Z,FILLB1    ; No then jump
  686.     DEC    B        ; Decrement block counter
  687.     LD    D,(HL)        ; Get correct MSB
  688.     INC    HL        ; Increment pointer
  689. ;
  690. FILLB1:    LD    A,D        ; Test block number
  691.     OR    E
  692.     JR    Z,FILLB2    ; Zero then get next block
  693.     PUSH    HL        ; Save pointer
  694.     PUSH    BC        ; Save counter and set/reset bit
  695.     LD    HL,(MAXLEN)    ; Get maximum lenght alv buffer
  696.     OR    A        ; Reset carry
  697.     SBC    HL,DE        ; Test de<=maxlen alv buffer
  698.     CALL    NC,SETBIT    ; Yes then insert bit
  699.     POP    BC        ; Get counter and set/reset bit
  700.     POP    HL        ; Get pointer
  701. ;
  702. FILLB2:    DJNZ    FILLB0        ; Repeat for all dm entries
  703.     RET            ; And return to caller
  704. ;
  705. ; Set write protect disk
  706. ;
  707. CMND28:    LD    HL,(DSKRO)    ; Get disk R/O vector
  708.     CALL    SDRVB        ; Include drive bit
  709.     LD    (DSKRO),HL    ; Save disk R/O bit
  710. ;
  711. SETFN:    LD    DE,(NFILES)    ; Get maximum number of files-1
  712.     INC    DE        ; Increment it
  713.     LD    HL,(TEMP0)    ; Get pointer to disk parameter block
  714.     LD    (HL),E        ; And save number of files
  715.     INC    HL
  716.     LD    (HL),D
  717.     RET            ; And return to caller
  718. ;
  719. ; Check file R/O bit
  720. ;
  721. CHKFRO:    CALL    CALDIR        ; Get directory entry
  722.     LD    DE,9        ; Offset to file R/O bit <crw>
  723.     ADD    HL,DE        ; Add offset
  724.     BIT    7,(HL)        ; Test file R/O
  725.     JR    NZ,CHKFR2    ; Yes then error
  726. ;
  727. ; System files are R/O if referenced with wildcards:
  728. ;
  729.     LD    A,(SEARQU)    ; Test if question mark used <crw>
  730.     OR    A        ; Test question mark used
  731.     RET    Z        ; No then don't test system file bit
  732.     INC    HL        ; Increment to system file
  733.     BIT    7,(HL)        ; Test system file
  734.     RET    Z        ; No system file then ok
  735. ;
  736. CHKFR2:    LD    HL,(SFILRO)    ; Get pointer to file R/O message
  737.     JP    (HL)        ; Display message
  738.  
  739. ;
  740. ; Check drive read only
  741. ;
  742. CHKRO:    LD    HL,(DSKRO)    ; Get drive R/O vector
  743.     CALL    SDRVB        ; Set drive bit
  744.     SBC    HL,DE        ; Test extra bit added
  745.     RET    NZ        ; Yes then drive not R/O
  746.     LD    HL,(STRO)    ; Get pointer to drive R/O message
  747.     JP    (HL)        ; Display message
  748. ;
  749. ; Get free block from allocation vector buffer
  750. ;    Entry:    DE = old block number
  751. ;    Exit:    DE = new block number (0 if no free block)
  752. ; HL counts up
  753. ; DE counts down
  754. ;
  755. GETFRE:    LD    H,D        ; Copy old block to hl
  756.     LD    L,E
  757. ;
  758. GETFR0:    LD    A,D        ; Test down counter is zero
  759.     OR    E
  760.     JR    Z,GETFR1    ; Yes then jump
  761.     DEC    DE        ; Decrememt down counter
  762.     PUSH    HL        ; Save up/down counter
  763.     PUSH    DE
  764.     CALL    GETBIT        ; Get bit from alv buffer
  765.     RRA            ; Test if zero
  766.     JR    NC,GETFR3    ; Yes then found empty block
  767.     POP    DE        ; Get up/down counter
  768.     POP    HL
  769. ;
  770. GETFR1:    LD    BC,(MAXLEN)    ; Get maximum alv lenght-1 in bc
  771.     OR    A        ; Clear carry
  772.     SBC    HL,BC        ; Test hl>=lenght alv-1
  773.     ADD    HL,BC        ; Restore hl (flags are not affected)
  774.     JR    NC,GETFR2    ; End buffer then jump
  775.     INC    HL        ; Increment up counter
  776.     PUSH    DE        ; Save down/up counter
  777.     PUSH    HL
  778.     EX    DE,HL        ; Save up counter in de
  779.     CALL    GETBIT        ; Get bit from alv buffer
  780.     RRA            ; Test if zero
  781.     JR    NC,GETFR3    ; Yes then found empty block
  782.     POP    HL        ; Get down/up counter
  783.     POP    DE
  784.     JR    GETFR0        ; And test next block
  785. ;
  786. GETFR2:    LD    A,D        ; Test if last block tested
  787.     OR    E
  788.     JR    NZ,GETFR0    ; No then test next block
  789.     RET            ; Exit (de=0)
  790. ;
  791. GETFR3:    SCF            ; Set block number used
  792.     RLA            ; Save bit
  793.     CALL    SETBT0        ; Put bit in alv buffer
  794.     POP    DE        ; Get correct counter
  795.     POP    HL        ; Restore stack pointer
  796.     RET            ; Exit (de=block number)
  797. ;
  798. ; Entry point to search for a file that is currently open
  799. ;
  800. SEAR0:    LD    A,15        ; Match first 15 bytes
  801. ;
  802. SEAR01:    LD    (SEARNB),A    ; Save number of bytes
  803.     LD    A,(IX+13)    ; Check if =FF, if was, use normal
  804.     INC    A        ; Search routine
  805.     JR    Z,SR1
  806.     CALL    HOME        ; Force BIOS directory read
  807.     LD    L,(IX+13)    ; Get sector of directory file was on
  808.     LD    H,0        ; *4 to satisify internal data base
  809.     SLA    L
  810.     RL    H
  811.     SLA    L
  812.     RL    H
  813.     LD    (FILCNT),HL    ; Place in internal data base
  814.     PUSH    HL
  815.     CALL    STDIR        ; Get sec-trk of directory entry
  816.     CALL    READDR        ; Read it to memory
  817.     POP    HL
  818.     DEC    HL        ; -1, will be +1 in readdr
  819.     LD    (FILCNT),HL
  820.     JR    SEAR1
  821. ;
  822. ; Find file name only
  823. ;
  824. FINDFN:    LD    A,12
  825.     JR    SEARCH
  826. ;
  827. ; Find file
  828. ;
  829. FINDF:    LD    A,15        ; Number of bytes to search for
  830. ;
  831. ; Search for file name
  832. ;    Entry:    A = number of bytes to search for
  833. ;
  834. SEARCH:    LD    (SEARNB),A    ; Save number of bytes
  835. ;
  836. SR1:    CALL    SETFCT        ; Initiate file counter
  837.     CALL    HOME        ; Force BIOS directory read
  838. ;
  839. SEAR1:    LD    A,0FFH        ; Set exit code to 0ffh (not found)
  840.     LD    (SEAREX),A
  841.     LD    (DCOPY),IX    ; Copy FCB pointer to ram (search next)
  842.  
  843. ;                    ; ..after disk change
  844. ; Search next file name
  845. ;
  846. SEARCN:    XOR    A        ; Clear accu, check checksum dir.
  847.     LD    (SEARQU),A    ; Clear question mark detected flag
  848.     LD    (SEARPU),A    ; Clear public file flag
  849.     CALL    RDDIR        ; Get FCB from directory
  850.     CALL    TSTFCT        ; Test if past last entry
  851.     JP    Z,SEARC8    ; Yes then jump
  852.     LD    DE,(DCOPY)    ; Get FCB pointer
  853.     LD    A,(DE)        ; Get first byte
  854.     CP    0E5H        ; Test if searching empty directory
  855.     JR    Z,SEARC1    ; Yes then jump
  856.     PUSH    DE        ; Save FCB pointer
  857.     CALL    TSTLF        ; Test last file on this drive
  858.     POP    DE        ; Restore FCB pointer
  859.     JR    NC,SEARC8    ; Yes then jump
  860. ;
  861. SEARC1:    CALL    CALDIR        ; Get entry in directory
  862.     LD    A,(HL)        ; Get first byte directory entry
  863.     CP    021H        ; Test time stamp
  864.     JR    Z,SEARCN    ; Yes then get next directory entry
  865.     LD    A,(SEARNB)    ; Get number of bytes to search for
  866.     LD    B,A        ; Save it in counter
  867.     XOR    A        ; Clear accu
  868.     LD    C,A        ; Clear counter
  869. ;
  870. SEARC2:    LD    A,B        ; Test if counter is zero
  871.     OR    A
  872.     JR    Z,SEARC9    ; Yes then jump
  873.     LD    A,(DE)        ; Get byte from FCB
  874.     XOR    '?'        ; Test if question mark
  875.     AND    07FH        ; Mask it (remove high bit)
  876.     JR    Z,SEARC6    ; Yes then jump
  877.     LD    A,C        ; Get FCB counter
  878.     OR    A        ; Test whether first byte
  879.     JR    NZ,SEARC3    ; No
  880.     LD    A,(FLAGS)    ; Yes. get flag byte
  881.     BIT    0,A        ; Test public file enable
  882.     JR    Z,SEARC3    ; No
  883.     INC    HL        ; Yes. get pointer to public bit
  884.     INC    HL
  885.     BIT    7,(HL)        ; Test public bit directory
  886.     DEC    HL        ; Restore pointer
  887.     DEC    HL
  888.     JR    Z,SEARC3    ; No public file then jump
  889.     LD    A,(DE)        ; Get first byte FCB
  890.     CP    0E5H        ; Test if searching empty directory
  891.     JR    Z,SEARC3    ; Yes then jump
  892.     XOR    (HL)        ; Test FCB=directory entry
  893.     AND    07FH        ; Mask it
  894.     JR    Z,SEARC5    ; Yes then jump
  895.     AND    0E0H        ; Mask user number
  896.     JR    NZ,SEARC3    ; Not the same then jump
  897.     DEC    A        ; A=0ffh
  898.     LD    (SEARPU),A    ; Set public file found
  899.     JR    SEARC5        ; Jump found
  900. ;
  901. SEARC3:    LD    A,C        ; Get FCB counter
  902.     CP    13        ; Test if at user code
  903.     JR    Z,SEARC5    ; Yes then no test
  904.     CP    12        ; Test if at extend number
  905.     LD    A,(DE)        ; Get byte from FCB
  906.     JR    Z,SEARC7    ; Jump if extent number
  907.     XOR    (HL)        ; Test byte FCB=byte directory entry
  908.     AND    07FH        ; Mask it
  909. ;
  910. SEARC4:    JR    NZ,SEARCN    ; Not the same then get next entry
  911. ;
  912. SEARC5:    INC    DE        ; Increment pointer FCB
  913.     INC    HL        ; Increment pointer directory entry
  914.     INC    C        ; Increment counter
  915.     DEC    B        ; Decrement counter
  916.     JR    SEARC2        ; Test next byte
  917. ;
  918. SEARC6:    DEC    A        ; Set question mark found flag
  919.     LD    (SEARQU),A
  920.     JR    SEARC5        ; Jump found
  921. ;
  922. SEARC7:    PUSH    BC        ; Save counters
  923.     XOR    (HL)        ; Test extends
  924.     LD    B,A        ; Save it
  925.     LD    A,(NEXTND)    ; Get extent mask
  926.     CPL            ; Complement it
  927.     AND    01FH        ; Mask it
  928.     AND    B        ; Mask extents
  929.     POP    BC        ; Restore counters
  930.     JR    SEARC4        ; And test result
  931. ;
  932. SEARC8:    CALL    SETFCT        ; Error set file counter
  933.     LD    A,0FFH        ; And set exit code
  934.     LD    (PEXIT),A
  935.     RET            ; Return to caller
  936. ;
  937. SEARC9:    LD    A,(SEARQU)    ; Get question mark found flag
  938.     LD    B,A        ; Save it
  939.     LD    A,(SEARPU)    ; Get public file flag
  940.     AND    B        ; Test if public file and question mark
  941.     JR    NZ,SEARC4    ; Yes then search for next entry
  942.     CALL    SETLF        ; Update last file count (empty FCB)
  943.     LD    A,(FILCNT)    ; Get file counter
  944.     AND    3        ; Mask it
  945.     LD    (PEXIT),A    ; And set exit code
  946.     XOR    A        ; Clear exit code search
  947.     LD    (SEAREX),A
  948.     RET            ; And return to caller
  949. ;
  950. ; Delete file
  951. ;
  952. DELETE:    CALL    CHKRO        ; Check disk R/O
  953.     CALL    FINDFN
  954. ;
  955. DEL0:    CALL    TSTFCT        ; Test if file found
  956.     RET    Z        ; Not then exit
  957.     CALL    CHKFRO        ; Check file R/O
  958.     CALL    CALDIR        ; Get entry point directory
  959.     LD    (HL),0E5H    ; Remove file
  960.     LD    C,0        ; Remove bits alv buffer
  961.     CALL    FILLBB
  962.     CALL    WRFCB        ; Write directory buffer on disk
  963.     CALL    SEARCN        ; Search next entry
  964.     JR    DEL0        ; And test it
  965. ;
  966. ; Rename file
  967. ;
  968. RENAM:    CALL    CHKRO        ; Check disk R/O
  969.     CALL    FINDFN
  970. ;
  971. RENAM0:    CALL    TSTFCT        ; Test if file found
  972.     RET    Z        ; Not then exit
  973.     CALL    CHKFRO        ; Check file R/O
  974.     PUSH    IX        ; Save FCB entry
  975.     POP    HL        ; Get it in hl
  976.     LD    DE,16        ; Offset to new name
  977.     ADD    HL,DE        ; Add offset
  978.     EX    DE,HL        ; Copy hl=>de
  979.     CALL    CALDIR        ; Get directory entry
  980.     LD    B,11        ; Set up loop counter
  981. ;
  982. RENAM1:    INC    HL        ; Increment directory pointer
  983.     INC    DE        ; Increment FCB pointer
  984.     LD    A,(DE)        ; Get character from FCB
  985.     AND    07FH        ; Mask it
  986.     CP    '?'        ; Test if question mark
  987.     JR    Z,RENAM2    ; Yes then do not change char. on disk
  988.     LD    C,A        ; Save it in c
  989.     LD    A,(HL)        ; Get character from directory
  990.     AND    080H        ; Mask status bit
  991.     OR    C        ; Or with new character
  992.     LD    (HL),A        ; Save in directory
  993. ;
  994. RENAM2:    DJNZ    RENAM1        ; Loop until done
  995.     CALL    WRFCB        ; And write directory on disk
  996.     CALL    SEARCN        ; Search next file
  997.     JR    RENAM0        ; And test it
  998. ;
  999. ; Change status file
  1000. ;
  1001. CSTAT:    CALL    CHKRO        ; Check disk R/O
  1002.     CALL    FINDFN
  1003. ;
  1004. CSTAT0:    CALL    TSTFCT        ; Test if file found
  1005.     RET    Z        ; Not then exit
  1006.     PUSH    IX        ; Save FCB entry
  1007.     POP    DE        ; Get it in hl
  1008.     CALL    CALDIR        ; Get directory entry
  1009.     LD    B,11        ; Set up loop counter
  1010. ;
  1011. CSTAT1:    INC    HL        ; Increment directory pointer
  1012.     INC    DE        ; Increment FCB pointer
  1013.     LD    A,(DE)        ; Get status bit from FCB
  1014.     AND    080H        ; Mask it
  1015.     LD    C,A        ; Save it in c
  1016.     LD    A,(HL)        ; Get character from directory
  1017.     AND    07FH        ; Mask it
  1018.     OR    C        ; Or with new status bit
  1019.     LD    (HL),A        ; Save in directory
  1020.     DJNZ    CSTAT1        ; Loop until done
  1021.     CALL    WRFCB        ; And write directory to disk
  1022.     CALL    SEARCN        ; Search next file
  1023.     JR    CSTAT0        ; And test it
  1024. ;
  1025. ; Compute file size
  1026. ;
  1027. FILSZ:    LD    BC,0        ; Reset file size lenght
  1028.     LD    D,C
  1029.     CALL    LDRRC        ; Save it in FCB+33,34,35
  1030.     CALL    FINDFN
  1031. ;
  1032. FILSZ0:    CALL    TSTFCT        ; Test if file found
  1033.     RET    Z        ; Not then exit
  1034.     CALL    CALDIR        ; Get directory entry
  1035.     EX    DE,HL        ; Copy to de
  1036.     LD    HL,15        ; Offset to next record
  1037.     CALL    CALRRC        ; Calculate random record count
  1038.     LD    A,D        ; Test LSB < (ix+33)
  1039.     SUB    (IX+33)
  1040.     LD    A,C        ; Test isb < (ix+34)
  1041.     SBC    A,(IX+34)
  1042.     LD    A,B        ; Test MSB < (ix+35)
  1043.     SBC    A,(IX+35)
  1044.     CALL    NC,LDRRC    ; Write new maximum
  1045.     CALL    SEARCN        ; Search next file
  1046.     JR    FILSZ0        ; And test it
  1047. ;
  1048. ; Write FCB on disk
  1049. ;
  1050. WRFCB:    CALL    STDIR        ; Calculate sector/track directory
  1051.     JP    WRITDR        ; Write directory on disk
  1052. ;
  1053. ; Calculate sector of file opened in FCB
  1054. ;
  1055. CMD15:    CALL    TSTFCT        ; Look for ffff
  1056.     JR    Z,CMD151    ; Yes, save ff, can't do fast lookup
  1057.     SRL    H        ; HL=(filcnt)/4-1
  1058.     RR    L
  1059.     SRL    H
  1060.     RR    L
  1061.     DEC    L
  1062. CMD151:    LD    (IX+13),L    ; Save in FCB+13 for use in SEAR0
  1063.     RET
  1064. ;
  1065. ; Open file
  1066. ;
  1067. CMND15:    CALL    SELDRV        ; Select drive from FCB
  1068.     LD    (IX+14),0    ; Clear FCB+14
  1069. ;
  1070. OPENF:    CALL    FINDF        ; Find file
  1071.     CALL    TSTFCT        ; Test file found
  1072.     RET    Z        ; No then exit
  1073. ;
  1074. OPENF0:    LD    A,(IX+12)    ; Get extent number from FCB
  1075.     PUSH    AF        ; Save it
  1076.     CALL    CALDIR        ; Get directory entry
  1077.     PUSH    HL        ; Save it <crw>
  1078.     LD    E,8        ; Set access date/time <crw>
  1079.     CALL    STIME        ; Zero flag set if stamps present <crw>
  1080.     POP    HL        ; Get directory entry <crw>
  1081.     PUSH    IX        ; Save FCB entry
  1082.     POP    DE        ; Get in in de
  1083.     LD    BC,32        ; Number of bytes to move
  1084.     LDIR            ; Move directory to FCB
  1085.     CALL    Z,WRFCB        ; Write to disk if stamps present <crw>
  1086.     SET    7,(IX+14)    ; Set FCB/file not modified
  1087.     LD    B,(IX+12)    ; Get extent number
  1088.     LD    C,(IX+15)    ; Get next record number
  1089.     POP    AF        ; Get old extent number
  1090.     LD    (IX+12),A    ; Save it
  1091.     CP    B        ; Compare old and new extent number
  1092.     JR    Z,OPENF1    ; Same then jump
  1093.     LD    C,0        ; Set next record count to 0
  1094.     JR    NC,OPENF1    ; Old extent >= new extent then jump
  1095.     LD    C,80H        ; Set next record count to maximum
  1096. ;
  1097. OPENF1:    LD    (IX+15),C    ; Save next record count
  1098.     CALL    CMD15        ; Fill in FCB+13,fast lookup
  1099.     RET            ; And return to caller
  1100. ;
  1101. ; Close file command
  1102. ;
  1103. CMND16:    CALL    SELDRV        ; Select drive from FCB
  1104. ;
  1105. ; Close file
  1106. ;
  1107. CLOSE:    BIT    7,(IX+14)    ; Test FCB/file modified
  1108.     RET    NZ        ; Not then no close required
  1109.     CALL    CHKRO        ; Test disk R/O
  1110.     CALL    SEAR0        ; Use fast search
  1111.     CALL    TSTFCT        ; Test file present
  1112.     RET    Z        ; No then exit
  1113.     CALL    CHKFRO        ; Check file R/O
  1114.     CALL    CALDIR        ; Get directory entry
  1115.     LD    BC,16        ; Offset to dm block
  1116.     ADD    HL,BC        ; Add offset
  1117.     EX    DE,HL        ; Save hl in de
  1118.     PUSH    IX        ; Save FCB pointer
  1119.     POP    HL        ; Get it in hl
  1120.     ADD    HL,BC        ; Add offset
  1121.     LD    A,(MAXLEN+1)    ; Test number of block >= 256
  1122.     OR    A
  1123.     JR    Z,CLOSE0    ; No then jump
  1124.     DEC    B        ; Set flag
  1125. ;
  1126. CLOSE0:    CALL    COPYDM        ; Copy and test blocks
  1127.     EX    DE,HL        ; Exchange copy direction
  1128.     CALL    COPYDM        ; Copy and test blocks
  1129.     EX    DE,HL        ; Exchange copy direction
  1130.     JR    NZ,CLOSE4    ; Block not the same then error
  1131.     INC    HL        ; Increment pointer FCB
  1132.     INC    DE        ; Increment pointer directory
  1133.     BIT    0,B        ; Test number of block >= 256
  1134.     JR    Z,CLOSE1    ; No then jump
  1135.     INC    HL        ; Increment pointer FCB
  1136.     INC    DE        ; Increment pointer directory
  1137.     DEC    C        ; Decrement counter
  1138. ;
  1139. CLOSE1:    DEC    C        ; Decrement counter
  1140.     JR    NZ,CLOSE0    ; Not ready then jump
  1141.     LD    HL,-20        ; Add -20 to get extent number
  1142.     ADD    HL,DE        ; HL contains pointer to extent number
  1143.     LD    A,(IX+12)    ; Get extent number FCB
  1144.     CP    (HL)        ; Compare with extent number directory
  1145.     JR    C,CLOSE3    ; FCB < directory then jump
  1146.     LD    (HL),A        ; Save extent number in directory
  1147.     INC    HL        ; Get pointer to next record
  1148.     INC    HL
  1149.     INC    HL
  1150.     LD    A,(IX+15)    ; Get next record FCB
  1151. ;
  1152. CLOSE2:    LD    (HL),A        ; Save next record in directory
  1153. ;
  1154. CLOSE3:    LD    E,4        ; Set last update date/time
  1155.     CALL    STIME        ; Update time
  1156.     CALL    CALDIR        ; Get directory entry
  1157.     LD    BC,11        ; Point to archive byte
  1158.     ADD    HL,BC
  1159.     RES    7,(HL)        ; Reset archive bit
  1160.     RES    7,(IX+11)    ; Reset bit in FCB
  1161.     INC    HL
  1162.     INC    HL
  1163.     PUSH    HL
  1164.     CALL    CMD15        ; Fill in FCB+13 for next fast lookup
  1165.     LD    A,L
  1166.     POP    HL
  1167.     LD    (HL),A
  1168.     JP    WRFCB        ; Write FCB on disk
  1169. ;
  1170. CLOSE4:    LD    A,0FFH        ; Flag error
  1171.     LD    (PEXIT),A
  1172.     RET            ; And return to caller
  1173. ;
  1174. ; Copy and test disk map
  1175. ;
  1176. ;    Entry:    HL = pointer to first FCB
  1177. ;        DE = pointer to second FCB
  1178. ;         B = 000h if less then 256 blocks
  1179. ;             0ffh if more or equal to 256 blocks
  1180. ;    Exit:    Z  blocks are the same
  1181. ;        NZ blocks are not the same
  1182. ;
  1183. COPYDM:    LD    A,(HL)        ; Get byte first FCB
  1184.     BIT    0,B        ; Test number of blocks >=256
  1185.     JR    Z,COPYD0    ; No then jump
  1186.     INC    HL        ; Increment pointer
  1187.     OR    (HL)        ; Test byte =0
  1188.     DEC    HL        ; Decrement pointer
  1189. ;
  1190. COPYD0:    OR    A        ; Test block number is zero
  1191.     JR    NZ,COPYD1    ; No then compare blocks
  1192.     LD    A,(DE)        ; Copy block from other FCB in empty location
  1193.     LD    (HL),A
  1194.     BIT    0,B        ; Test number of blocks >=256
  1195.     RET    Z        ; No then exit
  1196.     INC    HL        ; Increment to MSB block numbers
  1197.     INC    DE
  1198.     LD    A,(DE)        ; Copy block from other FCB in empty location
  1199.     LD    (HL),A
  1200.     JR    COPYD2        ; Jump trick to save space
  1201. ;
  1202. COPYD1:    LD    A,(DE)        ; Get block number first FCB
  1203.     SUB    (HL)        ; Test if the same
  1204.     RET    NZ        ; Not then return
  1205.     OR    B        ; Test if >=256 blocks
  1206.     RET    Z        ; No then return
  1207.     INC    HL        ; Increment to MSB block numbers
  1208.     INC    DE
  1209. ;
  1210. COPYD2:    LD    A,(DE)        ; Get block number first FCB
  1211.     SUB    (HL)        ; Test if the same
  1212.     DEC    HL        ; Decrement block FCB pointers
  1213.     DEC    DE
  1214.     RET            ; And exit to caller
  1215. ;
  1216. ; Entry point to use fast lookup to 'MAKE' next FCB entry for open file
  1217. ;
  1218. MAKER:    CALL    MAK0
  1219.     PUSH    AF
  1220.     LD    A,1
  1221.     CALL    SEAR01
  1222.     JR    MAK1
  1223. ;
  1224. ; Common code for MAKE/MAKER
  1225. ;
  1226. MAK0:    CALL    CHKRO        ; Check drive R/O
  1227.     LD    A,(IX+0)    ; Get first byte FCB
  1228.     LD    (IX+0),0E5H    ; Set first byte to empty file
  1229.     RET
  1230. ;
  1231. ; Make file command
  1232. ;
  1233. CMND22:    CALL    SELDRV        ; Select drive from FCB
  1234.     LD    (IX+14),0    ; Clear FCB+14
  1235. ;
  1236. ; Make file
  1237. ;
  1238. MAKE:    CALL    MAK0
  1239.     PUSH    AF        ; Save it
  1240.     LD    A,1        ; Search for 1 byte
  1241.     CALL    SEARCH        ; Search empty file
  1242. ;
  1243. MAK1:    POP    AF        ; Get first byte FCB
  1244.     LD    (IX+0),A    ; Restore it
  1245.     CALL    TSTFCT        ; Test empty file found
  1246.     RET    Z        ; No then return error
  1247.     XOR    A        ; Clear FCB+13
  1248.     PUSH    IX        ; Save FCB pointer
  1249.     POP    HL        ; Get it back in hl
  1250.     LD    DE,15        ; Prepare offset
  1251.     ADD    HL,DE        ; Add it
  1252.     LD    B,17        ; Set loop counter
  1253. ;
  1254. MAKE0:    LD    (HL),A        ; Clear FCB+15 up to FCB+31
  1255.     INC    HL        ; Increment pointer
  1256.     DJNZ    MAKE0        ; And clear all bytes
  1257.     LD    E,2        ; Set creation date
  1258.     CALL    STIME        ; Update time in directory
  1259.     LD    E,4        ; Set last update date/time
  1260.     CALL    STIME        ; Update time in directory
  1261.     LD    E,8        ; Set access date/time <crw>
  1262.     CALL    STIME
  1263.     RES    7,(IX+11)    ; Reset archive bit if present
  1264.     CALL    CALDIR        ; Get directory entry
  1265.     PUSH    HL        ; Save directory pointer
  1266.     PUSH    IX        ; Put FCB pointer on stack
  1267.     CALL    CMD15        ; Fill in FCB+13
  1268.     POP    DE        ; FCB pointer to DE
  1269.     POP    HL        ; Directory entry pointer
  1270.     EX    DE,HL        ; Exchange FCB and directory entry
  1271.     LD    BC,32        ; Number of bytes to move
  1272.     LDIR            ; Move bytes
  1273.     CALL    WRFCB        ; Write FCB on disk
  1274.     SET    7,(IX+14)    ; Set FCB/file not modified
  1275.     RET            ; And return to caller
  1276. ;
  1277. ; Open next extent
  1278. ;
  1279. OPENEX:    BIT    7,(IX+14)    ; Test if FCB/file modified (write)
  1280.     JR    NZ,OPENX2    ; Not then jump
  1281.     CALL    CLOSE        ; Close current FCB
  1282.     LD    A,(PEXIT)    ; Get exit code
  1283.     INC    A        ; Test if error
  1284.     RET    Z        ; Yes then exit
  1285.     CALL    CALNEX        ; Calculate next extent
  1286.     JR    C,OPENX3    ; Error then jump
  1287.     JR    NZ,OPENX5    ; FCB present from close then jump
  1288. ;
  1289. OPENX0:    CALL    SEAR0        ; Use fast lookup to find next extent
  1290. ;
  1291. OPENX1:    CALL    TSTFCT        ; Test if file found
  1292.     JR    NZ,OPENX5    ; Yes then jump
  1293.     LD    A,(RDWR)    ; Test read/write flag
  1294.     OR    A        ; Test if read
  1295.     JR    Z,OPENX3    ; Yes then error
  1296.     CALL    MAKER        ; Make new extent if write
  1297.     CALL    TSTFCT        ; Test if succesfull
  1298.     JR    NZ,OPENX6    ; Yes then exit
  1299.     JR    OPENX3        ; No then error
  1300. ;
  1301. OPENX2:    CALL    CALNEX        ; Calculate next extent
  1302.     JR    NC,OPENX0
  1303. ;
  1304. OPENX3:    SET    7,(IX+14)    ; Set FCB/file not modified
  1305.     LD    A,0FFH        ; Set exit code
  1306. ;
  1307. OPENX4:    LD    (PEXIT),A
  1308.     RET            ; And return to caller
  1309. ;
  1310. OPENX5:    CALL    OPENF0        ; Open file
  1311. ;
  1312. OPENX6:    XOR    A        ; And clear exit code
  1313.     JR    OPENX4        ; Use same routine
  1314. ;
  1315. ; Calculate next extent
  1316. ;
  1317. ;    Exit:    C  overflow detected
  1318. ;        Z  search next extent
  1319. ;        NZ next extent present (close)
  1320. ;
  1321. CALNEX:    LD    B,(IX+12)    ; Get extent number
  1322.     LD    C,(IX+14)    ; Get FCB+14
  1323.     BIT    6,C        ; Test error bit random record
  1324.     SCF            ; Set error flag
  1325.     RET    NZ        ; Non zero then error exit
  1326.     INC    B        ; Increment extent number
  1327.     LD    A,B        ; Get extent number
  1328.     AND    01FH        ; Mask it
  1329.     LD    B,A        ; Save it in b
  1330.     JR    NZ,CALNX0    ; Non zero then jump
  1331.     INC    C        ; Increment FCB+14
  1332.     LD    A,C        ; Get it in a
  1333.     AND    03FH        ; Mask it
  1334.     LD    C,A        ; Save it in c
  1335.     SCF            ; Set error flag
  1336.     RET    Z        ; And return if file overflow
  1337.     XOR    A        ; Clear zero flag (not same extent)
  1338.     JR    CALNX1        ; And save extent number and FCB+14
  1339. ;
  1340. CALNX0:    LD    A,(NEXTND)    ; Get next extent mask
  1341.     AND    B        ; Test if same extent (close)
  1342. ;
  1343. CALNX1:    LD    (IX+12),B    ; Save extent number
  1344.     LD    (IX+14),C    ; Save FCB+14
  1345.     RET            ; And return to caller
  1346. ;
  1347. ; Read random record command
  1348. ;
  1349. CMND33:    CALL    SELDRV        ; Select drive from FCB
  1350. ;
  1351. ; Read random sector
  1352. ;
  1353. RDRAN:    XOR    A        ; Set read/write flag
  1354.     CALL    LDFCB        ; Load random record in FCB
  1355.     JR    Z,READS        ; No error then read sector
  1356.     RET            ; Return error
  1357. ;
  1358. ; Read sequential
  1359. ;
  1360. CMND20:    CALL    SELDRV        ; Select drive from FCB
  1361. ;
  1362. ; Read sector
  1363. ;
  1364. READS:    XOR    A        ; Set read/write flag
  1365.     LD    (RDWR),A    ; Save it
  1366.     LD    A,(IX+32)    ; Get record counter
  1367.     CP    080H        ; Test if last record this extent
  1368.     JR    NC,READS1    ; Yes then open next extent
  1369.     CP    (IX+15)        ; Test if greater then current record
  1370.     JR    C,READS2    ; No then get record
  1371. ;
  1372. READS0:    LD    A,1        ; Set end of file flag
  1373.     LD    (PEXIT),A    ; Save it
  1374.     RET            ; And return to caller
  1375. ;
  1376. READS1:    CALL    OPENEX        ; To open next extent
  1377.     LD    A,(PEXIT)    ; Get exit code
  1378.     OR    A
  1379.     JR    NZ,READS0    ; Yes then end of file
  1380.     LD    (IX+32),0    ; Clear record counter
  1381. ;
  1382. READS2:    CALL    GETDM        ; Get block number from dm in FCB
  1383.     LD    A,D        ; Test block number = 0
  1384.     OR    E
  1385.     JR    Z,READS0    ; Yes then end file
  1386.     CALL    CALSEC        ; Calculate sector number (128 bytes)
  1387.     CALL    CALST        ; Calculate sector/track number
  1388.     CALL    READR        ; Read data
  1389.     LD    A,(FUNCT)    ; Get function number
  1390.     CP    20        ; Test if read sequential
  1391.     RET    NZ        ; No then return
  1392.     INC    (IX+32)        ; Increment next record counter
  1393.     RET            ; And return to caller
  1394. ;
  1395. ; Write random record commands
  1396. ;
  1397. CMND34:    DS    0
  1398. ;
  1399. CMND40:    CALL    SELDRV        ; Select drive from FCB
  1400. ;
  1401. ; Write random sector
  1402. ;
  1403. WRRAN:    LD    A,0FFH        ; Set read/write flag
  1404.     CALL    LDFCB        ; Load FCB from random record
  1405.     JR    Z,WRITES    ; No error then write record
  1406.     RET            ; Return error
  1407. ;
  1408. ; Write sequential
  1409. ;
  1410. CMND21:    CALL    SELDRV        ; Select drive from FCB
  1411. ;
  1412. ; Write sector
  1413. ;
  1414. WRITES:    LD    A,0FFH        ; Set read/write flag
  1415.     LD    (RDWR),A    ; And save it
  1416.     CALL    CHKRO        ; Check disk R/O
  1417.     BIT    7,(IX+9)    ; Test if file R/O
  1418.     JP    NZ,CHKFR2    ; Yes then file R/O message
  1419. ;
  1420. ; Check for changed disk.
  1421. ; If disk changed:
  1422. ;    If file modified, abort.
  1423. ;    Else reset disk and disk changed bit.
  1424. ;
  1425. ;
  1426. ; Test disk changed
  1427. ;
  1428.     LD    HL,(DIFF)    ; Get drive changed vector
  1429.     CALL    SDRVB        ; Set current drive bit
  1430.     SBC    HL,DE        ; Test extra bit added
  1431.     JR    NZ,WRITSA    ; Bit added, so disk not changed
  1432. ;
  1433. ; Test file modified
  1434. ;
  1435.     BIT    7,(IX+14)    ; File modified?
  1436.     JP    Z,CHGERR    ; Yes, abort and warm boot
  1437. ;
  1438. ; Reset disk and disk changed bit.
  1439. ;    HL = 0 from SBC, DE = (diff) from SDRVB above
  1440. ;
  1441.     PUSH    DE        ; Save (diff)
  1442.     CALL    SDRVB        ; Set current bit only in HL
  1443.     POP    DE        ; Get (diff)
  1444.     PUSH    HL        ; Save current drive bit for reset
  1445.     LD    A,D
  1446.     XOR    H
  1447.     LD    D,A        ; Mask current bit in DE
  1448.     LD    A,E
  1449.     XOR    L
  1450.     LD    E,A
  1451.     LD    (DIFF),DE    ; Reset disk changed bit in (diff)
  1452.     POP    DE        ; Get current bit for disk reset
  1453.     CALL    CMND37        ; No, reset drive:
  1454.     LD    A,(DEFDRV)    ; Get drive
  1455.     CALL    SELDK        ; And log it in again
  1456. ;
  1457. WRITSA:    LD    A,(IX+32)    ; Get record count
  1458.     CP    080H        ; Test if end this extent
  1459.     JR    C,WRITS0    ; Yes then open next extent
  1460.     CALL    OPENEX        ; Open next extent
  1461.     LD    A,(PEXIT)    ; Get error code
  1462.     OR    A
  1463.     JP    NZ,WRITS9    ; Error then directory full error
  1464.     LD    (IX+32),0    ; Clear record counter
  1465. ;
  1466. WRITS0:    CALL    GETDM        ; Get block number from FCB
  1467.     LD    A,D        ; Test if block number = 0
  1468.     OR    E
  1469.     JR    NZ,WRITS5    ; No then write sector
  1470.     PUSH    HL        ; Save pointer to block number
  1471.     LD    A,C        ; Test first block number in extent
  1472.     OR    A
  1473.     JR    Z,WRITS1    ; Yes then jump
  1474.     DEC    A        ; Decrement pointer to block number
  1475.     CALL    GETDM4        ; Get previous blocknumber
  1476. ;
  1477. WRITS1:    CALL    GETFRE        ; Get nearest free block
  1478.     POP    HL        ; Get pointer to block number
  1479.     LD    A,D        ; Test if blocknumber = 0
  1480.     OR    E
  1481.     JR    Z,WRITS8    ; Yes then disk full error
  1482.     RES    7,(IX+14)    ; Reset FCB/file modified
  1483.     LD    (HL),E        ; Save blocknumber
  1484.     LD    A,(MAXLEN+1)    ; Get number of blocks
  1485.     OR    A        ; Test if <256
  1486.     JR    Z,WRITS2    ; Yes then jump
  1487.     INC    HL        ; Increment to MSB block number
  1488.     LD    (HL),D        ; Save MSB block number
  1489. ;
  1490. WRITS2:    LD    C,2        ; Set write new block flag
  1491.     LD    A,(NMASK)    ; Get sector mask
  1492.     AND    (IX+32)        ; Mask with record counter
  1493.     JR    Z,WRITSX    ; Zero then ok (at start new record)
  1494.     LD    C,0        ; Else clear new block flag
  1495. ;
  1496. WRITSX:    LD    A,(FUNCT)    ; Get function number
  1497.     SUB    40        ; Test if write rr with zero fill
  1498.     JR    NZ,WRITS6    ; No then jump
  1499.     PUSH    DE        ; Save blocknumber
  1500.     LD    HL,(DIRBUF)    ; Use directory buffer for zero fill
  1501.     LD    B,128        ; 128 bytes to clear
  1502. ;
  1503. WRITS3:    LD    (HL),A        ; Clear directory buffer
  1504.     INC    HL        ; Increment pointer
  1505.     DJNZ    WRITS3        ; Clear all bytes
  1506.     CALL    CALSEC        ; Calculate sector number (128 bytes)
  1507.     LD    A,(NMASK)    ; Get sector mask
  1508.     LD    B,A        ; Copy it
  1509.     INC    B        ; Increment it to get number of writes
  1510.     CPL            ; Complement sector mask
  1511.     AND    E        ; Mask sector number
  1512.     LD    E,A        ; And save it
  1513.     LD    C,2        ; Set write new block flag
  1514. ;
  1515. WRITS4:    PUSH    HL        ; Save registers
  1516.     PUSH    DE
  1517.     PUSH    BC
  1518.     CALL    CALST        ; Calculate sector/track
  1519.     CALL    DMADIR        ; Set DMA directory buffer
  1520.     POP    BC        ; Get write new block flag
  1521.     PUSH    BC        ; Save it again
  1522.     CALL    WRITER        ; Write record on disk
  1523.     POP    BC        ; Restore registers
  1524.     POP    DE
  1525.     POP    HL
  1526.     LD    C,0        ; Clear write new block flag
  1527.     INC    E        ; Increment sector number
  1528.     DJNZ    WRITS4        ; Write all blocks
  1529.     CALL    STDMA        ; Set user DMA address
  1530.     POP    DE        ; Get block number
  1531. ;
  1532. WRITS5:    LD    C,0        ; Clear write new block flag
  1533. ;
  1534. WRITS6:    RES    7,(IX+14)    ; Reset FCB/file modified flag
  1535.     PUSH    BC        ; Save it
  1536.     CALL    CALSEC        ; Calculate sector number (128 bytes)
  1537.     CALL    CALST        ; Calculate sector/track
  1538.     POP    BC        ; Get write new block flag
  1539.     CALL    WRITER        ; Write record on disk
  1540.     LD    A,(IX+32)    ; Get record counter
  1541.     CP    (IX+15)        ; Compare with next record
  1542.     JR    C,WRITS7    ; If less then jump
  1543.     INC    A        ; Increment record count
  1544.     LD    (IX+15),A    ; Save it on next record position
  1545.     RES    7,(IX+14)    ; Reset FCB/file modified flag
  1546. ;
  1547. WRITS7:    LD    A,(FUNCT)    ; Get function number
  1548.     CP    21        ; Test write sequential
  1549.     RET    NZ        ; Not then return
  1550.     INC    (IX+32)        ; Increment record count
  1551.     RET            ; And return to caller
  1552. ;
  1553. WRITS8:    LD    A,2        ; Set disk full error
  1554.     LD    (PEXIT),A
  1555.     RET            ; And return to caller
  1556. ;
  1557. WRITS9:    LD    A,1        ; Set directory full flag
  1558.     LD    (PEXIT),A
  1559.     RET            ; And return to caller
  1560. ;
  1561. ; Load FCB for random read/write
  1562. ;
  1563. ;    Exit:    Z  no error
  1564. ;        NZ error occured
  1565. ;
  1566. LDFCB:    LD    (RDWR),A    ; Save read/write flag
  1567.     LD    A,(IX+33)    ; Get first byte random record
  1568.     LD    D,A        ; Save it in d
  1569.     RES    7,D        ; Reset MSB to get next record
  1570.     RLA            ; Shift MSB in carry
  1571.     LD    A,(IX+34)    ; Load next byte random record
  1572.     RLA            ; Shift carry
  1573.     PUSH    AF        ; Save it
  1574.     AND    01FH        ; Mask next extent
  1575.     LD    C,A        ; Save it in c
  1576.     POP    AF        ; Get byte
  1577.     RLA            ; Shift 4 times
  1578.     RLA
  1579.     RLA
  1580.     RLA
  1581.     AND    0FH        ; Mask it
  1582.     LD    B,A        ; Save FCB+14
  1583.     LD    A,(IX+35)    ; Get next byte random record
  1584.     LD    E,6        ; Set random record to large flag
  1585.     CP    4        ; Test random record to large
  1586.     JR    NC,LDFCB6    ; Yes then error
  1587.     RLCA            ; Shift 4 times
  1588.     RLCA
  1589.     RLCA
  1590.     RLCA
  1591.     ADD    A,B        ; Add byte
  1592.     LD    B,A        ; Save FCB+14 in b
  1593.     LD    (IX+32),D    ; Set next record count
  1594.     LD    D,(IX+14)    ; Get FCB+14
  1595.     BIT    6,D        ; Test error random record
  1596.     JR    NZ,LDFCB1    ; Yes then jump
  1597.     LD    A,C        ; Get new extent number
  1598.     CP    (IX+12)        ; Compare with FCB
  1599.     JR    NZ,LDFCB1    ; Not equal then open next extent
  1600.     LD    A,B        ; Get new FCB+14
  1601.     XOR    (IX+14)        ; Compare with FCB+14
  1602.     AND    03FH        ; Mask it
  1603.     JR    Z,LDFCB4    ; Equal then return
  1604. ;
  1605. LDFCB1:    BIT    7,D        ; Test FCB modified (write)
  1606.     JR    NZ,LDFCB2    ; No then jump
  1607.     PUSH    DE        ; Save registers
  1608.     PUSH    BC
  1609.     CALL    CLOSE        ; Close extent
  1610.     POP    BC        ; Restore registers
  1611.     POP    DE
  1612.     LD    E,3        ; Set close error
  1613.     LD    A,(PEXIT)    ; Get exit code
  1614.     INC    A
  1615.     JR    Z,LDFCB5    ; Error then exit
  1616. ;
  1617. LDFCB2:    LD    (IX+12),C    ; Save new extent number
  1618.     LD    (IX+14),B    ; Save new FCB+14
  1619.     CALL    FINDF        ; Open file old way because may not
  1620. ;                ; Have valid FCB+13 for fast lookup
  1621.     LD    A,(PEXIT)    ; Get error code
  1622.     INC    A
  1623.     JR    NZ,LDFCB3    ; No error then exit
  1624.     LD    A,(RDWR)    ; Get read/write flag
  1625.     LD    E,4        ; Set read empty record
  1626.     INC    A
  1627.     JR    NZ,LDFCB5    ; Read then error
  1628.     CALL    MAKER        ; Make new FCB using fast lookup
  1629.     LD    E,5        ; Set make error
  1630.     LD    A,(PEXIT)    ; Get error code
  1631.     INC    A
  1632.     JR    Z,LDFCB5    ; Error then exit
  1633.     JR    LDFCB4        ; No error exit (zero set)
  1634. ;
  1635. LDFCB3:    CALL    OPENF0        ; Open file
  1636. ;
  1637. LDFCB4:    XOR    A        ; Set zero flag and clear error code
  1638.     LD    (PEXIT),A
  1639.     RET            ; And return to caller
  1640. ;
  1641. LDFCB5:    LD    (IX+14),0C0H    ; Set random record error
  1642. ;
  1643. LDFCB6:    LD    A,E        ; Get error code
  1644.     LD    (PEXIT),A    ; And save it
  1645.     SET    7,(IX+14)    ; Set FCB/file not modified
  1646.     OR    A        ; Clear zero flag
  1647.     RET            ; And return to caller
  1648. ;
  1649. ; Calculate random record
  1650. ;    Entry:    HL = offset in FCB
  1651. ;        DE = FCB pointer
  1652. ;    Exit:    D  = LSB random record
  1653. ;        C  = ISB random record
  1654. ;        B  = MSB random record
  1655. ;
  1656. CALRRC:    ADD    HL,DE        ; Pointer to FCB+15 or FCB+32
  1657.     LD    A,(HL)        ; Get byte
  1658.     LD    HL,12        ; Offset to extent number
  1659.     ADD    HL,DE        ; Get pointer to extent byte
  1660.     LD    D,A        ; Save first byte
  1661.     LD    A,(HL)        ; Get extent byte
  1662.     AND    01FH        ; Mask it
  1663.     RL    D        ; Shift MSB in carry
  1664.     ADC    A,0        ; Add carry
  1665.     RRA            ; Shift 1 time (16 bits)
  1666.     RR    D
  1667.     LD    C,A        ; Save isb
  1668.     INC    HL        ; Increment to FCB+14
  1669.     INC    HL
  1670.     LD    A,(HL)        ; Get FCB+14
  1671.     RRCA            ; Shift 4 times
  1672.     RRCA
  1673.     RRCA
  1674.     RRCA
  1675.     PUSH    AF        ; Save it
  1676.     AND    03H        ; Mask MSB
  1677.     LD    B,A        ; Save it
  1678.     POP    AF        ; Get LSB
  1679.     AND    0F0H        ; Mask it
  1680.     ADD    A,C        ; Add with isb
  1681.     LD    C,A        ; Save isb
  1682.     RET    NC        ; No carry then return
  1683.     INC    B        ; Increment MSB
  1684.     RET            ; And return to caller
  1685. ;
  1686. ; END Z80DDISK.Z80
  1687.  
  1688.