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 / BEEHIVE / OS / Z80D24SR.ARC / Z80DDISK.Z80 < prev    next >
Text File  |  1991-02-10  |  47KB  |  1,660 lines

  1. ;
  2. ; Z80DOS - Z80 Disk Operating System
  3. ;
  4. ; Version 2.4    Maskable disk reset's using variable fixdrv
  5. ;        Now can assemble with Z80MR if Z80MR equate
  6. ;        set to -1.
  7. ;        Gene Nolan 4/9/89
  8. ;
  9. ;
  10. ;------------------------------------------------------
  11. ;
  12. ; Version 2.31    Fast file lookup for random records fix
  13. ; Date        15 Nov 88
  14. ; Update    Eugene Nolan
  15. ;
  16. ; Version 2.3    Fast file lookup
  17. ; Date:        4 Nov 88
  18. ; Update:    Eugene Nolan
  19. ;
  20. ;-------------------------------------------------------------
  21. ; Version 2.0a - BETA TEST VERSION - 6 Nov 87 by Carson Wilson
  22. ;
  23. ; Support file:    Z80DDISK.Z80
  24. ; Version:    2.0
  25. ; Date:        6 Nov 87
  26. ; Author:    Carson Wilson
  27. ; Description:    DOS Return CP/M Version, Disk Functions
  28. ;
  29. ; Changes:    --------
  30. ;        Changed Readr and Writer to use a common error function,
  31. ;        RWErr, which displays "Data error on d:".      
  32. ;
  33. ;        new disk will be overwritten, data from the first file will 
  34. ;        probably be lost.
  35. ;
  36. ;        --------
  37. ;        Command 37 (reset individual disk) now resets the disk changed
  38. ;        vector instead of the drive R/O vector.
  39. ;
  40. ;        --------
  41. ;        Removed code which made public files read-only from 
  42. ;        other user areas.  The user must now manually set public 
  43. ;        files to read-only using the R/O attribute (t1).  This 
  44. ;        change was made because some applications must write to 
  45. ;        public files.
  46. ;
  47. ;        --------
  48. ;        System files are now R/W unless referenced by wildcards.
  49. ;
  50.  
  51.  
  52. ; -----------------------
  53. ;
  54. ; Return version number
  55. ;
  56. ; -----------------------
  57.  
  58. cmnd12:    ld    a,22h            ; Set version number
  59.     ld    ix,3800h        ; this will put an '8' into D
  60.                     ; register upon return, saying
  61.                     ; Z80DOS operating
  62.     jp    cmd25a            ; And exit
  63.  
  64.  
  65. ; -----------------------------
  66. ;
  67. ;    Disk functions
  68. ;
  69. ; -----------------------------
  70. ;
  71. ; Reset disk system
  72. ;
  73. cmnd13:
  74. ;    ld    hl,0            ; Load zero
  75.     ld    hl,(login)        ; Get login vector
  76.     ld    de,(fixdrvs)        ; get drive mask
  77.     ld    a,h
  78.     and    d
  79.     ld    h,a
  80.     ld    a,l
  81.     and    e
  82.     ld    l,a            ; HL now has selective drives
  83.                     ; logged out
  84.     ld    (login),hl
  85.     ld    hl,0
  86.     ld    (dskro),hl        ; All drives read/write
  87.     ld    (diff),hl        ; No disks changed <crw>
  88.     ld    hl,RamLow+80h        ; Set up DMA address
  89.     ld    (DMA),hl        ; And save it
  90.     call    stDMA            ; Do BIOS call
  91.     ld    a,ResDsk+1        ; When selective logout enabled
  92.                     ; the call to seldk below requires
  93.                     ; defdrv and the drive to select in
  94.                     ; the A reg to be different
  95.     ld    (defdrv),a        ; Save it
  96.     ld    a,ResDsk        ; <crw>
  97.     call    seldk            ; Select drive 0=A, 1=B, etc.
  98.     ld    a,(subflg)        ; Get submit flag
  99.     jr    cmd25a            ; Exit
  100. ;
  101. ; Search for file
  102. ;
  103. cmnd17:    call    seldrv            ; Select drive from FCB
  104.     ld    a,(ix+0)        ; Get drive number from FCB
  105.     sub    '?'            ; Test if '?'
  106.     jr    Z,cmd17b        ; If so all entries match
  107.     ld    a,(ix+14)        ; Get system byte
  108.     cp    '?'            ; Test if '?'
  109.     jr    Z,cmd17a        ; Yes, jump
  110.     ld    (ix+14),0        ; Load system byte with zero
  111. cmd17a:    ld    a,15            ; Test first 15 items in FCB
  112. cmd17b:    call    search            ; Do search
  113. cmd17c:    ld    hl,(dirbuf)        ; Copy directory buffer
  114.     ld    de,(DMA)        ; To DMA address
  115.     ld    bc,128            ; Directory=128 bytes
  116.     ldir
  117.     ret                ; Exit
  118. ;
  119. ; Search for next occurrence of file
  120. ;
  121. cmnd18:    ld    ix,(dcopy)        ; Get last FCB used by search
  122.     call    seldrv            ; Select drive from FCB
  123.     call    searcn            ; Search next file match
  124.     jr    cmd17c            ; And copy directory to DMA address
  125. ;
  126. ; Delete file
  127. ;
  128. cmnd19:    call    seldrv            ; Select drive from FCB
  129.     call    delete            ; Delete file
  130. cmd19a:    ld    a,(searex)        ; Get exit byte 00=file found,0ffh not
  131.     jr    cmd25a            ; And exit
  132. ;
  133. ; Rename file
  134. ;
  135. cmnd23:    call    seldrv            ; Select drive from FCB
  136.     call    renam            ; Rename file
  137.     jr    cmd19a            ; And exit
  138. ;
  139. ; Return login vector
  140. ;
  141. cmnd24:    ld    hl,(login)        ; Get login vector
  142. cmd24a:    ld    (pexit),hl        ; Save it
  143.     ret                ; And exit
  144. ;
  145. ; Return current drive
  146. ;
  147. cmnd25:    ld    a,(defdrv)        ; Get current drive
  148. cmd25a:    jp    exit            ; And exit
  149. ;
  150. ; Return allocation vector
  151. ;
  152. cmnd27:    ld    hl,(alv)        ; Get allocation vector
  153.     jr    cmd24a            ; And exit
  154. ;
  155. ; Return disk R/O vector
  156. ;
  157. cmnd29:    ld    hl,(dskro)        ; Get disk R/O vector
  158.     jr    cmd24a            ; And exit
  159. ;
  160. ; Set file attributes
  161. ;
  162. cmnd30:    call    seldrv            ; Select drive from FCB
  163.     call    cstat            ; Change status
  164.     jr    cmd19a            ; And exit
  165. ;
  166. ; Get Disk Parameter Block Address
  167. ;
  168. cmnd31:    ld    hl,(ixp)        ; get drive table
  169.     jr    cmd24a            ; And exit
  170. ;
  171. ; Set/get user code
  172. ;
  173.  
  174. cmnd32:    ld    a,e            ; Get user code
  175.     inc    a            ; Test if 0ffh
  176.     ld    a,(user)        ; Get old user code
  177.     jr    Z,cmd25a        ; If 0ffh then exit
  178.     ld    a,e            ; Get new user code
  179.     and    01fh            ; Mask it
  180.     ld    (user),a        ; Save it
  181.     ret                ; And exit
  182. ;
  183. ; Compute file size
  184. ;
  185. cmnd35:    call    seldrv            ; Select drive from FCB
  186.     call    filsz            ; Compute file size
  187.     jr    cmd19a            ; And exit
  188. ;
  189. ; Set random record count
  190. ;
  191. cmnd36:    ld    hl,32            ; Set pointer to next record
  192.     call    calrrc            ; Calculate random record count
  193. ldrrc:    ld    (ix+33),d        ; And save random record count
  194.     ld    (ix+34),c
  195.     ld    (ix+35),b
  196.     ret                ; And exit
  197. ;
  198. ; Reset individual disk drives from vector in DE
  199. ;
  200. cmnd37:    ld    a,e            ; Get mask LSB
  201.     cpl                ; Complement it
  202.     ld    e,a
  203.     ld    a,d            ; Get mask MSB
  204.     cpl                ; Complement it
  205.     ld    d,a
  206.     ld    hl,(login)        ; Get login vector
  207.     ld    a,e            ; Mask login vector
  208.     and    l            ; LSB
  209.     ld    l,a
  210.     ld    a,d            ; Mask login vector
  211.     and    h            ; MSB
  212.     ld    h,a
  213.     ld    (login),hl        ; Save login vector
  214.     ex    de,hl            ; Use login vector as mask
  215.     ld    hl,(diff)        ; Get disk changed vector <crw> 
  216.     ld    a,e            ; Mask drive R/O vector
  217.     and    l            ; LSB
  218.     ld    l,a
  219.     ld    a,d            ; Mask drive R/O vector
  220.     and    h            ; LSB
  221.     ld    h,a
  222.     ld    (diff),hl        ; Save disk changed vector <crw>
  223.     ret                ; And exit
  224. ;
  225. ; Select disk from FCB
  226. ;
  227. seldrv:    ld    a,0ffh            ; Set disk select done flag
  228.     ld    (fldrv),a
  229.     ld    a,(defdrv)        ; Get current drive
  230.     ld    (drive),a        ; Save it in memory
  231.     ld    e,a            ; Save it in register e
  232.     ld    a,(ix+0)        ; Get drive from FCB
  233.     ld    (fcb0),a        ; Save it
  234.     ld    d,a
  235.     cp    '?'            ; Test if '?'
  236.     jr    Z,cmnd14        ; Yes, then select drive from register e
  237.     and    01fh            ; Mask drive
  238.     ld    a,e            ; Test if zero
  239.     jr    Z,seldr0        ; Select drive from register e
  240.     ld    a,d
  241.     dec    a            ; Decrement drive
  242. seldr0:    call    seldk            ; Select drive
  243.     ld    a,(ix+0)        ; Get drive from FCB
  244.     and    0e0h            ; Remove drive bits
  245.     ld    b,a            ; Save register
  246.     ld    a,(user)        ; Get user number
  247.     or    b            ; Insert user number in FCB
  248.     ld    (ix+0),a
  249.     ret                ; And exit
  250. ;
  251. ; Select disk
  252. ;
  253. cmnd14:    ld    a,e            ; Copy drive number
  254. ;
  255. seldk:    and    0fh            ; Mask drive number to 0-15
  256.     ld    b,a            ; Save counter
  257.     ld    de,(login)        ; Get login vector
  258.     or    a            ; Test drive 'a'
  259.     jr    Z,seldk1        ; Yes then jump
  260. seldk0:    rr    d            ; Shift login vector
  261.     rr    e            ; Until bit 0 register e
  262.     djnz    seldk0            ; Is current drive
  263. seldk1:    ld    hl,defdrv        ; Get pointer last drive
  264.     bit    0,e            ; Test if drive logged in
  265.     jr    Z,seldk2        ; No, login drive
  266.     cp    (hl)            ; Test same drive
  267.     ret    Z            ; Yes then exit
  268. seldk2: ld    (hl),a            ; Save new current drive
  269.     push    de            ; Save drive logged in flag
  270.     ld    c,a
  271.     call    SelDsk            ; Do BIOS select
  272.     ld    a,h            ; Test if error
  273.     or    l
  274.     jr    Z,seldk3        ; Yes, illegal drive number
  275.     ld    e,(hl)            ; Get LSB translation vector
  276.     inc    hl            ; Increment pointer
  277.     ld    d,(hl)            ; Get MSB translation vector
  278.     inc    hl            ; Increment pointer
  279.     ld    (trans),de        ; Save translation vector
  280.     ld    (temp0),hl        ; Save address temp0
  281.     ld    de,6
  282.     add    hl,de            ; Point to dirbuf pointer <crw>
  283.     ld    de,dirbuf        ; Load dirbuf pointer
  284.     ld    bc,8            ; Copy pointers to dirbuf,
  285.     ldir                ; ..csv (wacd), alv from BIOS
  286.     ld    hl,(ixp)        ; Get drive parameter address
  287.     ld    c,15            ; Copy 15 bytes
  288.     ldir
  289.     pop    de            ; Get drive logged in flag
  290.     bit    0,e            ; Test it
  291.     ret    NZ            ; Drive logged in so return
  292.     ld    hl,(login)        ; Get login vector
  293.     call    sdrvb            ; Set drive bit in login vector
  294.     ld    (login),hl        ; Save login vector
  295.     jr    initdr            ; And setup drive tables
  296. seldk3:
  297.     ld    hl,(StSel)        ; Load error message address
  298.     jp    (hl)            ; And display error
  299. ;
  300. ; Init drive
  301. ;  Clear allocation vector bit buffer after drive reset
  302. ;
  303. initdr:    ld    de,(maxlen)        ; Get length alv buffer-1 (bits)
  304.     ld    a,3            ; Divide by 8
  305. initd0:    srl    d            ; To get bytes
  306.     rr    e
  307.     dec    a
  308.     jr    NZ,initd0
  309.     inc    de            ; Increment, so all bits are cleared
  310.     ld    hl,(alv)        ; Get pointer alv buffer
  311.     push    hl
  312. initd1:    ld    (hl),0            ; Clear 8 bits
  313.     inc    hl            ; Increment pointer
  314.     dec    de            ; Decrement counter
  315.     ld    a,d            ; Test if counter zero
  316.     or    e
  317.     jr    NZ,initd1        ; Not then jump
  318.     pop    hl            ; Get alv pointer
  319.     ld    de,(ndir0)        ; Get first two bytes alv buffer
  320.     ld    (hl),e            ; Save LSB
  321.     inc    hl            ; Increment pointer
  322.     ld    (hl),d            ; Save MSB
  323.     ld    hl,(temp0)        ; Clear number of files
  324.     xor    a            ; On this drive
  325.     ld    (hl),a            ; Clear LSB
  326.     inc    hl            ; Increment pointer
  327.     ld    (hl),a            ; Clear MSB
  328.     ld    (subflg),a        ; Clear submit flag (reset disk command)
  329.     call    setfct            ; Set file count
  330. initd2:    ld    a,0ffh            ; Update directory checksum
  331.     call    rddir            ; Read FCB's from directory
  332.     call    tstfct            ; Test last FCB
  333.     ret    Z            ; Yes then exit
  334.     call    caldir            ; Calculate entry point FCB
  335.     ld    a,(hl)            ; Get first byte FCB
  336.     cp    0e5h            ; Test empty directory entry
  337.     jr    Z,initd2        ; Yes then get next FCB
  338.     cp    021h            ; Test time stamp
  339.     jr    Z,initd2        ; Yes then get next FCB
  340.     ld    a,(user)        ; Get user number
  341.     cp    (hl)            ; Test if user is same
  342.     jr    NZ,initd3        ; No then jump
  343.     inc    hl            ; Point to file name
  344.     ld    a,(hl)            ; Get first char filename
  345.     dec    hl
  346.     sub    '$'            ; Test if '$'
  347.     jr    NZ,initd3        ; Not then jump
  348.     dec    a            ; Load a with 0ffh
  349.     ld    (subflg),a        ; Save it in subflg
  350. initd3:    ld    c,1            ; Set bit in alv buffer
  351.     call    fillbb            ; Set bits from FCB in alv buffer
  352.     call    setlf            ; Update last file count
  353.     jr    initd2            ;
  354. ;
  355. ; Set drive bit from (defdrv) in HL
  356. ;    Exit:    DE = HL before setting bit (if any)
  357. ;
  358. sdrvb:    ex    de,hl            ; Copy hl=>de
  359.     ld    hl,1            ; Get mask drive "a"
  360.     ld    a,(defdrv)        ; Get current drive
  361.     or    a            ; Test if drive "a"
  362.     jr    Z,sdrvb1        ; Yes then done
  363. sdrvb0:    add    hl,hl            ; Get next mask
  364.     dec    a            ; Decrement drive counter
  365.     jr    NZ,sdrvb0        ; And test if done
  366. sdrvb1:    ld    a,d            ; Hl=hl or de
  367.     or    h
  368.     ld    h,a
  369.     ld    a,e
  370.     or    l
  371.     ld    l,a
  372.     ret                ; Exit
  373.  
  374. ;
  375. ; Calculate sector/track directory
  376. ;
  377. stdir:
  378.     ld    hl,(filcnt)        ; Get FCB counter directory
  379.     srl    h            ; Divide by 4
  380.     rr    l            ; (4 FCB's / sector)
  381.     srl    h
  382.     rr    l
  383.     ld    (recdir),hl        ; Save value (used by checksum)
  384.     ex    de,hl            ; Copy it to de
  385.     ld    hl,0            ; Clear hl
  386. ;
  387. ; Calculate sector/track
  388. ;    Entry:    hl,de = sector number (128 byte sector)
  389. ;    Exit:    set track  = hl,de  /  maxsec
  390. ;        set sector = hl,de mod maxsec
  391. ;
  392. calst:    ld    bc,(maxsec)        ; Get sectors/track
  393.     ld    a,17            ; Set up loop counter
  394. calst0:    or    a            ; Test hl>=bc
  395.     sbc    hl,bc
  396.     ccf
  397.     jr    C,calst1        ; Yes then jump
  398.     add    hl,bc            ; No then restore hl
  399.     or    a            ; And clear carry
  400. calst1:    rl    e            ; Shift result in de
  401.     rl    d
  402.     dec    a            ; Test last bit done
  403.     jr    Z,calst2        ; Yes then exit
  404.     rl    l            ; Shift next bit in hl
  405.     rl    h
  406.     jr    calst0            ; Continue
  407. calst2:    push    hl            ; Save sector number
  408.     ld    hl,(nftrk)        ; Get first track
  409.     add    hl,de            ; Add track number
  410.     ld    b,h            ; Copy it to bc
  411.     ld    c,l
  412.     call    SetTrk            ; BIOS call set track
  413.     pop    bc            ; Restore sector number
  414.     ld    de,(trans)        ; Get translation table address
  415.     call    SecTrn            ; BIOS call sector translation
  416.     ld    b,h            ; Copy result to bc
  417.     ld    c,l
  418.     jp    SetSec            ; BIOS call set sector
  419. ;
  420. ; Get disk map block number from FCB
  421. ;
  422. ; Exit: HL = address FCB
  423. ;    DE = disk map
  424. ;    BC = offset in disk map
  425. ;
  426. getdm:    ld    c,(ix+32)        ; Get next record
  427.     ld    a,(nblock)        ; Get number of blocks
  428.     ld    b,a            ; Save it
  429. getdm0:    srl    c            ; Shift next record
  430.     djnz    getdm0            ; Number of blocks times
  431. getdm1:    cpl                ; Complement number of blocks
  432.     add    a,9            ; Add 9
  433.     ld    b,a            ; B=8-number of blocks
  434.     ld    a,(nextnd)        ; Get extend mask
  435.     and    (ix+12)            ; Mask with extend
  436.     rrca                ; Rotate one right
  437. getdm2:    rlca                ; Rotate one left
  438.     djnz    getdm2            ; 8-number of blocks times
  439. getdm3:    add    a,c            ; Add the two values to get entry FCB
  440. getdm4:    push    ix            ; Get FCB address
  441.     pop    hl
  442.     ld    c,16            ; Add offset 16 to point to dm
  443.     add    hl,bc
  444.     ld    c,a            ; Add entry FCB
  445.     add    hl,bc
  446.     ld    a,(maxlen+1)        ; Test 8 bits/16 bits FCB entry
  447.     or    a
  448.     jr    NZ,getdm5        ; 16 bits => jump
  449.     ld    e,(hl)            ; Get 8 bit value
  450.     ld    d,a            ; Make MSB zero
  451.     ret                ; And exit
  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. calsc0:    sla    e            ; Shift l,d,e
  466.     rl    d
  467.     rl    l
  468.     djnz    calsc0            ; B times
  469. calsc1:    ld    a,(nmask)        ; Get sector mask
  470.     and    (ix+32)            ; And with next record
  471.     or    e            ; Set up LSB sector number
  472.     ld    e,a
  473.     ret                ; And exit
  474. ;
  475. ; Calculate dirbuf entry point
  476. ;
  477. caldir:    ld    hl,(dirbuf)        ; Get start address dirbuf
  478.     ld    a,(secpnt)        ; Get sector pointer
  479.     add    a,l            ; Add l=l+a
  480.     ld    l,a
  481.     ret    NC            ; No carry exit
  482.     inc    h            ; Increment h
  483.     ret                ; And exit
  484. ;
  485. ; Init file count
  486. ;
  487. setfct:    ld    hl,-1            ; Set up file count
  488.     ld    (filcnt),hl        ; Save it
  489.     ret                ; And exit
  490. ;
  491. ; Test file count
  492. ;
  493. ; Exit:    Zero flag set and A = 0 if filcnt = 0ffffh
  494. ;
  495. tstfct:    ld    hl,(filcnt)        ; Test file count=0ffffh
  496.      ld    a,h            ; Get MSB
  497.     and    l            ; And LSB
  498.     inc    a            ; Test if result=0ffh
  499.     ret                ; And exit
  500. ;
  501. ; Set last file
  502. ;
  503. setlf:    call    tstlf            ; Test last file
  504.     ret    C            ; No then exit
  505.     inc    de            ; Increment last file
  506.     ld    (hl),d            ; Save it in temp0
  507.     dec    hl
  508.     ld    (hl),e
  509.     ret                ; And exit
  510. ;
  511. ; Test last file
  512. ;
  513. tstlf:    ld    hl,(temp0)        ; Get pointer to last file
  514.     ld    de,(filcnt)        ; Get file counter
  515.     ld    a,e            ; Subtract filcnt-(temp0)
  516.     sub    (hl)
  517.     inc    hl
  518.     ld    a,d
  519.     sbc    a,(hl)            ; Carry means (temp0) > filcnt
  520.     ret                ; Exit
  521. ;
  522. ; Get next FCB from drive
  523. ;    Entry:    A = 0 check checksum
  524. ;        A = 0ffh update checksum
  525. ;
  526. rddir:    ld    c,a            ; Save checksum flag
  527.     ld    hl,(filcnt)        ; Get file counter
  528.     inc    hl            ; Increment it
  529.     ld    (filcnt),hl        ; And save it
  530.     ld    de,(nfiles)        ; Get maximum number of files
  531.     or    a            ; Clear carry
  532.     sbc    hl,de            ; Test if last file
  533.     add    hl,de
  534.     jr    Z,rddir0        ; No, jump
  535.     jr    NC,setfct        ; Yes, set file count to 0ffffh
  536. rddir0:    ld    a,l            ; Get file count LSB
  537.     add    a,a            ; *32
  538.     add    a,a
  539.     add    a,a
  540.     add    a,a
  541.     add    a,a
  542.     and    060h            ; Mask it
  543.     ld    (secpnt),a        ; Save it for later use
  544.     ret    NZ            ; Return if not first FCB sector
  545.     push    bc            ; Save checksum flag
  546.     call    stdir            ; Calculate sector/track directory
  547.     call    readdr            ; Read sector directory
  548.     pop    bc            ; Restore checksum flag
  549. ;
  550. ; Update/check checksum directory
  551. ; Entry C=0 check checksum, C=0ffh update checksum
  552. ;
  553. chkdir:    ld    hl,(ncheck)        ; Get number of checked records
  554.     ld    a,h
  555.     or    l
  556.     ret    Z
  557.     ld    de,(recdir)        ; Get current record
  558.     or    a            ; Clear carry
  559.     sbc    hl,de            ; Test current record
  560.     ret    Z            ; Exit if zero
  561.     ret    C            ; Exit if greater then ncheck
  562.     ld    hl,(dirbuf)        ; Get dirbuf
  563.     ld    b,128            ; Set up counter
  564.     xor    a            ; Clear checksum
  565. chkdr0:    add    a,(hl)            ; Add checksum
  566.     inc    hl            ; Increment pointer
  567.     djnz    chkdr0            ; 128 times
  568.     ld    hl,(csv)        ; Get pointer checksum directory
  569.     add    hl,de            ; Add current record
  570.     inc    c            ; Test checksum flag
  571.     jr    Z,chkdr1        ; 0ffh=> update checksum
  572.     cp    (hl)            ; Test checksum
  573.     ret    Z            ; Exit if ok
  574.     ld    hl,(diff)        ; Get disk changed vector
  575.     call    sdrvb            ; Include drive bit
  576.     ld    (diff),hl        ; Save disk changed bit
  577.     jp    setfn            ; Set # files to maximum
  578. chkdr1:    ld    (hl),a            ; Update checksum
  579.     ret                ; And exit
  580. ;
  581. ; Read sector from drive
  582. ;
  583. readr:    call    read            ; BIOS call read sector
  584.     jr    write0            ; Test exit code
  585. ;
  586. ; Write sector on drive
  587. ;
  588. writer:    call    write            ; BIOS call write sector
  589. write0:    or    a            ; Test exit code
  590.     ret    Z            ; Exit if ok
  591.     ld    hl,(StRW)        ; Point to data error routine
  592.     ld    (retflg),a        ; Allow retry for read/write errors
  593.     jp    (hl)            ; Display "Data error on d:"
  594. ;
  595. ; Read directory from drive
  596. ;
  597. readdr:    call    DMAdir            ; Set up DMA directory
  598.     call    readr            ; Read record
  599.     jr    stDMA            ; Set up DMA user
  600. ;
  601. ; Write directory on drive
  602. ;
  603. writdr:    ld    c,0ffh            ; Update checksum directory
  604.     call    chkdir
  605.     call    DMAdir            ; Set up DMA directory
  606.     ld    c,1            ; Write directory flag
  607.     call    writer            ; Write record
  608.     jr    stDMA            ; Set up DMA user
  609. ;
  610. ; Set DMA address command
  611. ;
  612. cmnd26:    ld    (DMA),de        ; Save DMA address
  613. ;
  614. stDMA:    ld    bc,(DMA)        ; Get DMA address
  615.     jr    DMAdr0            ; And do BIOS call
  616. ;
  617. ; Set DMA address directory
  618. ;
  619. DMAdir:    ld    bc,(dirbuf)        ; Get DMA address directory
  620. DMAdr0:    jp    setDMA            ; BIOS call set DMA
  621.  
  622. ;
  623. ; Get bit from allocation vector buffer
  624. ;
  625. ;    Entry:    DE = block number
  626. ;    Exit:    A  = bit in LSB
  627. ;        B  = bitnumber in a
  628. ;        HL = pointer in alv buffer
  629. ;
  630. getbit:    ld    a,e            ; Get bit number
  631.     and    7            ; Mask it
  632.     inc    a            ; Add 1
  633.     ld    b,a            ; Save it
  634.     ld    c,a            ; Twice
  635.     srl    d            ; Get byte number
  636.     rr    e            ; De=de/8
  637.     srl    d
  638.     rr    e
  639.     srl    d
  640.     rr    e
  641.     ld    hl,(alv)        ; Get start address alv buffer
  642.     add    hl,de            ; Add byte number
  643.     ld    a,(hl)            ; Get 8 bits
  644. getbt0:    rlca                ; Get correct bit
  645.     djnz    getbt0
  646.     ld    b,c            ; Restore bit number
  647.     ret                ; And return to caller
  648. ;
  649. ; Set/reset bit in allocation vector buffer
  650. ;    Entry    DE = block number
  651. ;         C = 0 reset bit, c=1 set bit
  652. ;
  653. setbit:    push    bc            ; Save set/reset bit
  654.     call    getbit            ; Get bit
  655.     and    0feh            ; Mask it
  656.     pop    de            ; Get set/reset bit
  657.     or    e            ; Set/reset bit
  658. setbt0:    rrca                ; Rotate bit in correct position
  659.     djnz    setbt0
  660.     ld    (hl),a            ; Save 8 bits
  661.     ret                ; And return to caller
  662. ;
  663. ; Fill bit buffer from FCB in dirbuf
  664. ;    Entry:    C = 0 reset bit
  665. ;        C = 1 set bit
  666. ;
  667. fillbb:;    call    caldir            ; Get directory entry
  668.     ld    de,16            ; Get offset dm block
  669.     add    hl,de            ; Add offset
  670.     ld    b,e            ; Get block counter
  671. fillb0:    ld    e,(hl)            ; Get LSB block number
  672.     inc    hl            ; Increment pointer
  673.     ld    d,0            ; Reset MSB block number
  674.     ld    a,(maxlen+1)        ; Test >256 blocks present
  675.     or    a
  676.     jr    Z,fillb1        ; No then jump
  677.     dec    b            ; Decrement block counter
  678.     ld    d,(hl)            ; Get correct MSB
  679.     inc    hl            ; Increment pointer
  680. fillb1:    ld    a,d            ; Test block number
  681.     or    e
  682.     jr    Z,fillb2        ; Zero then get next block
  683.     push    hl            ; Save pointer
  684.     push    bc            ; Save counter and set/reset bit
  685.     ld    hl,(maxlen)        ; Get maximum lenght alv buffer
  686.     or    a            ; Reset carry
  687.     sbc    hl,de            ; Test de<=maxlen alv buffer
  688.     call    nc,setbit        ; Yes then insert bit
  689.     pop    bc            ; Get counter and set/reset bit
  690.     pop    hl            ; Get pointer
  691. fillb2:    djnz    fillb0            ; Repeat for all dm entries
  692.     ret                ; And return to caller
  693. ;
  694. ; Set write protect disk
  695. ;
  696. cmnd28:
  697.     ld    hl,(dskro)        ; Get disk R/O vector
  698.     call    sdrvb            ; Include drive bit
  699.     ld    (dskro),hl        ; Save disk R/O bit
  700. setfn:    ld    de,(nfiles)        ; Get maximum number of files-1
  701.     inc    de            ; Increment it
  702.     ld    hl,(temp0)        ; Get pointer to disk parameter block
  703.     ld    (hl),e            ; And save number of files
  704.     inc    hl
  705.     ld    (hl),d
  706.     ret                ; And return to caller
  707. ;
  708. ; Check file R/O bit
  709. ;
  710. chkfro:    call    caldir            ; Get directory entry
  711.     ld    de,9            ; Offset to file R/O bit <crw>
  712.     add    hl,de            ; Add offset
  713.     bit    7,(hl)            ; Test file R/O
  714.     jr    NZ,chkfr2        ; Yes then error
  715. ;
  716. ; System files are R/O if referenced with wildcards:
  717. ;
  718.     ld    a,(searqu)        ; Test if question mark used <crw>
  719.     or    a            ; Test question mark used
  720.     ret    Z            ; No then don't test system file bit
  721.     inc    hl            ; Increment to system file
  722.     bit    7,(hl)            ; Test system file
  723.     ret    Z            ; No system file then ok
  724. chkfr2:
  725.     ld    hl,(sfilro)        ; Get pointer to file R/O message
  726.     jp    (hl)            ; Display message
  727.  
  728. ;
  729. ; Check drive read only
  730. ;
  731. chkro:    ld    hl,(dskro)        ; Get drive R/O vector
  732.     call    sdrvb            ; Set drive bit
  733.     sbc    hl,de            ; Test extra bit added
  734.     ret    NZ            ; Yes then drive not R/O
  735.     ld    hl,(stro)        ; Get pointer to drive R/O message
  736.     jp    (hl)            ; Display message
  737.  
  738. ;
  739. ; Get free block from allocation vector buffer
  740. ;    Entry:    DE = old block number
  741. ;    Exit:    DE = new block number (0 if no free block)
  742. ; HL counts up
  743. ; DE counts down
  744. ;
  745. getfre:    ld    h,d            ; Copy old block to hl
  746.     ld    l,e
  747. getfr0:    ld    a,d            ; Test down counter is zero
  748.     or    e
  749.     jr    Z,getfr1        ; Yes then jump
  750.     dec    de            ; Decrememt down counter
  751.     push    hl            ; Save up/down counter
  752.     push    de
  753.     call    getbit            ; Get bit from alv buffer
  754.     rra                ; Test if zero
  755.     jr    NC,getfr3        ; Yes then found empty block
  756.     pop    de            ; Get up/down counter
  757.     pop    hl
  758. getfr1:    ld    bc,(maxlen)        ; Get maximum alv lenght-1 in bc
  759.     or    a            ; Clear carry
  760.     sbc    hl,bc            ; Test hl>=lenght alv-1
  761.     add    hl,bc            ; Restore hl (flags are not affected)
  762.     jr    NC,getfr2        ; End buffer then jump
  763.     inc    hl            ; Increment up counter
  764.     push    de            ; Save down/up counter
  765.     push    hl
  766.     ex    de,hl            ; Save up counter in de
  767.     call    getbit            ; Get bit from alv buffer
  768.     rra                ; Test if zero
  769.     jr    NC,getfr3        ; Yes then found empty block
  770.     pop    hl            ; Get down/up counter
  771.     pop    de
  772.     jr    getfr0            ; And test next block
  773. getfr2:    ld    a,d            ; Test if last block tested
  774.     or    e
  775.     jr    NZ,getfr0        ; No then test next block
  776.     ret                ; Exit (de=0)
  777. getfr3:    scf                ; Set block number used
  778.     rla                ; Save bit
  779.     call    setbt0            ; Put bit in alv buffer
  780.     pop    de            ; Get correct counter
  781.     pop    hl            ; Restore stack pointer
  782.     ret                ; Exit (de=block number)
  783.  
  784. ;
  785. ; Entry point to search for a file that is currently open
  786. ;
  787.  
  788. sear0:    ld    a,15            ; Match first 15 bytes
  789. sear01:    ld    (searnb),a        ; Save number of bytes
  790.     ld    a,(ix+13)        ; Check if =FF, if was, use normal
  791.     inc    a            ; search routine
  792.     jr    Z,sr1
  793.     call    home            ; Force BIOS directory read
  794.     ld    l,(ix+13)        ; Get sector of directory file was on
  795.     ld    h,0            ; *4 to satisify internal data base
  796.     sla    l
  797.     rl    h
  798.     sla    l
  799.     rl    h
  800.     ld    (filcnt),hl        ; Place in internal data base
  801.     push    hl
  802.     call    stdir            ; Get sec-trk of directory entry
  803.     call    readdr            ; Read it to memory
  804.     pop    hl
  805.     dec    hl            ; -1, will be +1 in readdr
  806.     ld    (filcnt),hl
  807.     jr    sear1
  808.  
  809. ;
  810. ; Find file name only
  811. ;
  812. findfn:    ld    a,12
  813.     jr    search
  814. ;
  815. ; Find file
  816. ;
  817. findf:    ld    a,15            ; Number of bytes to search for
  818.  
  819. ;
  820. ; Search for file name
  821. ;    Entry:    A = number of bytes to search for
  822. ;
  823.  
  824. search:
  825.     ld    (searnb),a        ; Save number of bytes
  826. sr1:    call    setfct            ; Initiate file counter
  827.     call    home            ; Force BIOS directory read
  828. sear1:    ld    a,0ffh            ; Set exit code to 0ffh (not found)
  829.     ld    (searex),a
  830.     ld    (dcopy),ix        ; Copy FCB pointer to ram (search next)
  831.  
  832. ;                    ; ..after disk change
  833. ; Search next file name
  834. ;
  835. SearcN:    xor    a            ; Clear accu, check checksum dir.
  836.     ld    (searqu),a        ; Clear question mark detected flag
  837.     ld    (searpu),a        ; Clear public file flag
  838.     call    rddir            ; Get FCB from directory
  839.     call    tstfct            ; Test if past last entry
  840.     jp    Z,searc8        ; Yes then jump
  841.     ld    de,(dcopy)        ; Get FCB pointer
  842.     ld    a,(de)            ; Get first byte
  843.     cp    0e5h            ; Test if searching empty directory
  844.     jr    Z,searc1        ; Yes then jump
  845.     push    de            ; Save FCB pointer
  846.     call    tstlf            ; Test last file on this drive
  847.     pop    de            ; Restore FCB pointer
  848.     jr    NC,searc8        ; Yes then jump
  849. searc1:    call    caldir            ; Get entry in directory
  850.     ld    a,(hl)            ; Get first byte directory entry
  851.     cp    021h            ; Test time stamp
  852.     jr    Z,searcn        ; Yes then get next directory entry
  853.     ld    a,(searnb)        ; Get number of bytes to search for
  854.     ld    b,a            ; Save it in counter
  855.     xor    a            ; Clear accu
  856.     ld    c,a            ; Clear counter
  857. searc2:    ld    a,b            ; Test if counter is zero
  858.     or    a
  859.     jr    Z,searc9        ; Yes then jump
  860.     ld    a,(de)            ; Get byte from FCB
  861.     xor    '?'            ; Test if question mark
  862.     and    07fh            ; Mask it (remove high bit)
  863.     jr    Z,searc6        ; Yes then jump
  864.     ld    a,c            ; Get FCB counter
  865.     or    a            ; Test whether first byte
  866.     jr    NZ,searc3        ; No
  867.     ld    a,(flags)        ; Yes. get flag byte
  868.     bit    0,a            ; Test public file enable
  869.     jr    Z,searc3        ; No
  870.     inc    hl            ; Yes. get pointer to public bit
  871.     inc    hl
  872.     bit    7,(hl)            ; Test public bit directory
  873.     dec    hl            ; Restore pointer
  874.     dec    hl
  875.     jr    Z,searc3        ; No public file then jump
  876.     ld    a,(de)            ; Get first byte FCB
  877.     cp    0e5h            ; Test if searching empty directory
  878.     jr    Z,searc3        ; Yes then jump
  879.     xor    (hl)            ; Test FCB=directory entry
  880.     and    07fh            ; Mask it
  881.     jr    Z,searc5        ; Yes then jump
  882.     and    0e0h            ; Mask user number
  883.     jr    NZ,searc3        ; Not the same then jump
  884.     dec    a            ; A=0ffh
  885.     ld    (searpu),a        ; Set public file found
  886.     jr    searc5            ; Jump found
  887. searc3:    ld    a,c            ; Get FCB counter
  888.     cp    13            ; Test if at user code
  889.     jr    Z,searc5        ; Yes then no test
  890.     cp    12            ; Test if at extend number
  891.     ld    a,(de)            ; Get byte from FCB
  892.     jr    Z,searc7        ; Jump if extent number
  893.     xor    (hl)            ; Test byte FCB=byte directory entry
  894.     and    07fh            ; Mask it
  895. searc4:    jr    NZ,searcn        ; Not the same then get next entry
  896. searc5:    inc    de            ; Increment pointer FCB
  897.     inc    hl            ; Increment pointer directory entry
  898.     inc    c            ; Increment counter
  899.     dec    b            ; Decrement counter
  900.     jr    searc2            ; Test next byte
  901. searc6:    dec    a            ; Set question mark found flag
  902.     ld    (searqu),a
  903.     jr    searc5            ; Jump found
  904. searc7:    push    bc            ; Save counters
  905.     xor    (hl)            ; Test extends
  906.     ld    b,a            ; Save it
  907.     ld    a,(nextnd)        ; Get extent mask
  908.     cpl                ; Complement it
  909.     and    01fh            ; Mask it
  910.     and    b            ; Mask extents
  911.     pop    bc            ; Restore counters
  912.     jr    searc4            ; And test result
  913. searc8:    call    setfct            ; Error set file counter
  914.     ld    a,0ffh            ; And set exit code
  915.     ld    (pexit),a
  916.     ret                ; Return to caller
  917. searc9:    ld    a,(searqu)        ; Get question mark found flag
  918.     ld    b,a            ; Save it
  919.     ld    a,(searpu)        ; Get public file flag
  920.     and    b            ; Test if public file and question mark
  921.     jr    NZ,searc4        ; Yes then search for next entry
  922.     call    setlf            ; Update last file count (empty FCB)
  923.     ld    a,(filcnt)        ; Get file counter
  924.     and    3            ; Mask it
  925.     ld    (pexit),a        ; And set exit code
  926.     xor    a            ; Clear exit code search
  927.     ld    (searex),a
  928.     ret                ; And return to caller
  929. ;
  930. ; Delete file
  931. ;
  932. delete:    call    chkro            ; Check disk R/O
  933.     call    findfn
  934. del0:    call    tstfct            ; Test if file found
  935.     ret    Z            ; Not then exit
  936.     call    chkfro            ; Check file R/O
  937.     call    caldir            ; Get entry point directory
  938.     ld    (hl),0e5h        ; Remove file
  939.     ld    c,0            ; Remove bits alv buffer
  940.     call    fillbb
  941.     call    wrFCB            ; Write directory buffer on disk
  942.     call    searcn            ; Search next entry
  943.     jr    del0            ; And test it
  944. ;
  945. ; Rename file
  946. ;
  947. renam:    call    chkro            ; Check disk R/O
  948.     call    findfn
  949. renam0:    call    tstfct            ; Test if file found
  950.     ret    Z            ; Not then exit
  951.     call    chkfro            ; Check file R/O
  952.     push    ix            ; Save FCB entry
  953.     pop    hl            ; Get it in hl
  954.     ld    de,16            ; Offset to new name
  955.     add    hl,de            ; Add offset
  956.     ex    de,hl            ; Copy hl=>de
  957.     call    caldir            ; Get directory entry
  958.     ld    b,11            ; Set up loop counter
  959. renam1:    inc    hl            ; Increment directory pointer
  960.     inc    de            ; Increment FCB pointer
  961.     ld    a,(de)            ; Get character from FCB
  962.     and    07fh            ; Mask it
  963.     cp    '?'            ; Test if question mark
  964.     jr    Z,renam2        ; Yes then do not change char. on disk
  965.     ld    c,a            ; Save it in c
  966.     ld    a,(hl)            ; Get character from directory
  967.     and    080h            ; Mask status bit
  968.     or    c            ; Or with new character
  969.     ld    (hl),a            ; Save in directory
  970. renam2:    djnz    renam1            ; Loop until done
  971.     call    wrFCB            ; And write directory on disk
  972.     call    searcn            ; Search next file
  973.     jr    renam0            ; And test it
  974. ;
  975. ; Change status file
  976. ;
  977. cstat:    call    chkro            ; Check disk R/O
  978.     call    findfn
  979. cstat0:    call    tstfct            ; Test if file found
  980.     ret    Z            ; Not then exit
  981.     push    ix            ; Save FCB entry
  982.     pop    de            ; Get it in hl
  983.     call    caldir            ; Get directory entry
  984.     ld    b,11            ; Set up loop counter
  985. cstat1:    inc    hl            ; Increment directory pointer
  986.     inc    de            ; Increment FCB pointer
  987.     ld    a,(de)            ; Get status bit from FCB
  988.     and    080h            ; Mask it
  989.     ld    c,a            ; Save it in c
  990.     ld    a,(hl)            ; Get character from directory
  991.     and    07fh            ; Mask it
  992.     or    c            ; Or with new status bit
  993.     ld    (hl),a            ; Save in directory
  994.     djnz    cstat1            ; Loop until done
  995.     call    wrFCB            ; And write directory to disk
  996.     call    searcn            ; Search next file
  997.     jr    cstat0            ; And test it
  998. ;
  999. ; Compute file size
  1000. ;
  1001. filsz:    ld    bc,0            ; Reset file size lenght
  1002.     ld    d,c
  1003.     call    ldrrc            ; Save it in FCB+33,34,35
  1004.     call    findfn
  1005. filsz0:    call    tstfct            ; Test if file found
  1006.     ret    Z            ; Not then exit
  1007.     call    caldir            ; Get directory entry
  1008.     ex    de,hl            ; Copy to de
  1009.     ld    hl,15            ; Offset to next record
  1010.     call    calrrc            ; Calculate random record count
  1011.     ld    a,d            ; Test LSB < (ix+33)
  1012.     sub    (ix+33)
  1013.     ld    a,c            ; Test isb < (ix+34)
  1014.     sbc    a,(ix+34)
  1015.     ld    a,b            ; Test MSB < (ix+35)
  1016.     sbc    a,(ix+35)
  1017.     call    nc,ldrrc        ; Write new maximum
  1018.     call    searcn            ; Search next file
  1019.     jr    filsz0            ; And test it
  1020. ;
  1021. ; Write FCB on disk
  1022. ;
  1023. wrFCB:    call    stdir            ; Calculate sector/track directory
  1024.     jp    writdr            ; Write directory on disk
  1025.  
  1026. ;
  1027. ; Calculate sector of file opened in FCB
  1028. ;
  1029. cmd15:    call    tstfct            ; Look for ffff
  1030.     jr    Z,cmd151        ; yes, save ff, can't do fast lookup
  1031.     srl    h            ; HL=(filcnt)/4-1
  1032.     rr    l
  1033.     srl    h
  1034.     rr    l
  1035.     dec    l
  1036. cmd151:    ld    (ix+13),l        ; Save in FCB+13 for use in SEAR0
  1037.     ret
  1038. ;
  1039. ; Open file
  1040. ;
  1041. cmnd15:    call    seldrv            ; Select drive from FCB
  1042.     ld    (ix+14),0        ; Clear FCB+14
  1043.  
  1044. openf:    call    findf            ; Find file
  1045.     call    tstfct            ; Test file found
  1046.     ret    Z            ; No then exit
  1047. openf0:    
  1048.     ld    a,(ix+12)        ; Get extent number from FCB
  1049.     push    af            ; Save it
  1050.     call    caldir            ; Get directory entry
  1051.     push    hl            ; Save it <crw>
  1052.     ld    e,8            ; Set access date/time <crw>
  1053.     call    stime            ; Zero flag set if stamps present <crw>
  1054.     pop    hl            ; Get directory entry <crw>
  1055.     push    ix            ; Save FCB entry
  1056.     pop    de            ; Get in in de
  1057.     ld    bc,32            ; Number of bytes to move
  1058.     ldir                ; Move directory to FCB
  1059.     call    Z,wrFCB            ; Write to disk if stamps present <crw>
  1060.     set    7,(ix+14)        ; Set FCB/file not modified
  1061.     ld    b,(ix+12)        ; Get extent number
  1062.     ld    c,(ix+15)        ; Get next record number
  1063.     pop    af            ; Get old extent number
  1064.     ld    (ix+12),a        ; Save it
  1065.     cp    b            ; Compare old and new extent number
  1066.     jr    Z,openf1        ; Same then jump
  1067.     ld    c,0            ; Set next record count to 0
  1068.     jr    NC,openf1        ; Old extent >= new extent then jump
  1069.     ld    c,80h            ; Set next record count to maximum
  1070. openf1:    ld    (ix+15),c        ; Save next record count
  1071.     call    cmd15            ; Fill in FCB+13,fast lookup
  1072.     ret                ; And return to caller
  1073.  
  1074. ;
  1075. ; Close file command
  1076. ;
  1077. cmnd16:    call    seldrv            ; select drive from FCB
  1078. ;
  1079. ; Close file
  1080. ;
  1081. close:    bit    7,(ix+14)        ; test FCB/file modified
  1082.     ret    NZ            ; not then no close required
  1083.     call    chkro            ; test disk R/O
  1084. ;    ld    a,15            ; number of bytes to search for
  1085. ;    call    search            ; search file
  1086. ;    call    findf
  1087.     call    sear0            ; Use fast search
  1088.     call    tstfct            ; test file present
  1089.     ret    Z            ; no then exit
  1090.     call    chkfro            ; check file R/O
  1091.     call    caldir            ; get directory entry
  1092.     ld    bc,16            ; offset to dm block
  1093.     add    hl,bc            ; add offset
  1094.     ex    de,hl            ; save hl in de
  1095.     push    ix            ; save FCB pointer
  1096.     pop    hl            ; get it in hl
  1097.     add    hl,bc            ; add offset
  1098.     ld    a,(maxlen+1)        ; test number of block >= 256
  1099.     or    a
  1100.     jr    Z,close0        ; no then jump
  1101.     dec    b            ; set flag
  1102. close0:    call    copydm            ; copy and test blocks
  1103.     ex    de,hl            ; exchange copy direction
  1104.     call    copydm            ; copy and test blocks
  1105.     ex    de,hl            ; exchange copy direction
  1106.     jr    NZ,close4        ; block not the same then error
  1107.     inc    hl            ; increment pointer FCB
  1108.     inc    de            ; increment pointer directory
  1109.     bit    0,b            ; test number of block >= 256
  1110.     jr    Z,close1        ; no then jump
  1111.     inc    hl            ; increment pointer FCB
  1112.     inc    de            ; increment pointer directory
  1113.     dec    c            ; decrement counter
  1114. close1:    dec    c            ; decrement counter
  1115.     jr    NZ,close0        ; not ready then jump
  1116.     ld    hl,-20            ; add -20 to get extent number
  1117.     add    hl,de            ; hL contains pointer to extent number
  1118.     ld    a,(ix+12)        ; get extent number FCB
  1119.     cp    (hl)            ; compare with extent number directory
  1120.     jr    C,close3        ; fCB < directory then jump
  1121.     ld    (hl),a            ; save extent number in directory
  1122.     inc    hl            ; get pointer to next record
  1123.     inc    hl
  1124.     inc    hl
  1125.     ld    a,(ix+15)        ; get next record FCB
  1126. close2:    ld    (hl),a            ; save next record in directory
  1127. close3:    ld    e,4            ; Set last update date/time
  1128.     call    stime            ; Update time
  1129.     call    caldir            ; Get directory entry
  1130.     ld    bc,11            ; Point to archive byte
  1131.     add    hl,bc
  1132.     res    7,(hl)            ; reset archive bit
  1133.     res    7,(ix+11)        ; reset bit in FCB
  1134.     inc    hl
  1135.     inc    hl
  1136.     push    hl
  1137.     call    cmd15            ; Fill in FCB+13 for next fast lookup
  1138.     ld    a,l
  1139.     pop    hl
  1140.     ld    (hl),a
  1141.     jp    wrFCB            ; write FCB on disk
  1142. ;
  1143. close4:    ld    a,0ffh            ; flag error
  1144.     ld    (pexit),a
  1145.     ret                ; and return to caller
  1146. ;
  1147. ; Copy and test disk map
  1148. ;
  1149. ;    Entry:    HL = pointer to first FCB
  1150. ;        DE = pointer to second FCB
  1151. ;         B = 000h if less then 256 blocks
  1152. ;             0ffh if more or equal to 256 blocks
  1153. ;    Exit:    Z  blocks are the same
  1154. ;        NZ blocks are not the same
  1155. ;
  1156. copydm:    ld    a,(hl)            ; get byte first FCB
  1157.     bit    0,b            ; test number of blocks >=256
  1158.     jr    Z,copyd0        ; No then jump
  1159.     inc    hl            ; Increment pointer
  1160.     or    (hl)            ; Test byte =0
  1161.     dec    hl            ; Decrement pointer
  1162. copyd0:    or    a            ; Test block number is zero
  1163.     jr    NZ,copyd1        ; No then compare blocks
  1164.     ld    a,(de)            ; Copy block from other FCB in empty location
  1165.     ld    (hl),a
  1166.     bit    0,b            ; Test number of blocks >=256
  1167.     ret    Z            ; No then exit
  1168.     inc    hl            ; Increment to MSB block numbers
  1169.     inc    de
  1170.     ld    a,(de)            ; Copy block from other FCB in empty location
  1171.     ld    (hl),a
  1172.     jr    copyd2            ; Jump trick to save space
  1173. copyd1:    ld    a,(de)            ; Get block number first FCB
  1174.     sub    (hl)            ; Test if the same
  1175.     ret    NZ            ; Not then return
  1176.     or    b            ; Test if >=256 blocks
  1177.     ret    Z            ; No then return
  1178.     inc    hl            ; Increment to MSB block numbers
  1179.     inc    de
  1180. copyd2:    ld    a,(de)            ; Get block number first FCB
  1181.     sub    (hl)            ; Test if the same
  1182.     dec    hl            ; Decrement block FCB pointers
  1183.     dec    de
  1184.     ret                ; And exit to caller
  1185.  
  1186.  
  1187. ;
  1188. ; Entry point to use fast lookup to 'MAKE' next FCB entry for open file
  1189. ;
  1190.  
  1191. maker:    call    mak0
  1192.     push    af
  1193.     ld    a,1
  1194.     call    sear01
  1195.     jr    mak1
  1196.  
  1197. ;
  1198. ; Common code for MAKE/MAKER
  1199. ;
  1200. mak0:    call    chkro            ; Check drive R/O
  1201.     ld    a,(ix+0)        ; Get first byte FCB
  1202.     ld    (ix+0),0e5h        ; Set first byte to empty file
  1203.     ret
  1204.  
  1205.  
  1206. ;
  1207. ; Make file command
  1208. ;
  1209.  
  1210. cmnd22:
  1211.     call    seldrv            ; Select drive from FCB
  1212.     ld    (ix+14),0        ; Clear FCB+14
  1213. ;
  1214. ; Make file
  1215. ;
  1216. make:
  1217.     call    mak0
  1218.     push    af            ; Save it
  1219.     ld    a,1            ; Search for 1 byte
  1220.     call    search            ; Search empty file
  1221. mak1:    pop    af            ; Get first byte FCB
  1222.     ld    (ix+0),a        ; Restore it
  1223.     call    tstfct            ; Test empty file found
  1224.     ret    Z            ; No then return error
  1225.     xor    a            ; Clear FCB+13
  1226. ;    ld    (ix+13),a        
  1227.     push    ix            ; Save FCB pointer
  1228.     pop    hl            ; Get it back in hl
  1229.     ld    de,15            ; Prepare offset
  1230.     add    hl,de            ; Add it
  1231.     ld    b,17            ; Set loop counter
  1232. make0:    ld    (hl),a            ; Clear FCB+15 up to FCB+31
  1233.     inc    hl            ; Increment pointer
  1234.     djnz    make0            ; And clear all bytes
  1235.     ld    e,2            ; Set creation date
  1236.     call    stime            ; Update time in directory
  1237.     ld    e,4            ; Set last update date/time
  1238.     call    stime            ; Update time in directory
  1239.     ld    e,8            ; Set access date/time <crw>
  1240.     call    stime
  1241.     res    7,(ix+11)        ; Reset archive bit if present
  1242. ;    call    cmd15            ; Fill in FCB for fast lookup
  1243. ;    call    caldir            ; Get directory entry
  1244. ;    push    ix            ; Save FCB entry
  1245. ;    pop    de            ; Get it in de
  1246.     call    caldir            ; get directory entry
  1247.     push    hl            ; save directory pointer
  1248.     push    ix            ; put fcb pointer on stack
  1249.     call    cmd15            ; fill in FCB+13
  1250.     pop    de            ; fcb pointer to DE
  1251.     pop    hl            ; directory entry pointer
  1252.  
  1253.     ex    de,hl            ; Exchange FCB and directory entry
  1254.     ld    bc,32            ; Number of bytes to move
  1255.     ldir                ; Move bytes
  1256.     call    wrFCB            ; Write FCB on disk
  1257.     set    7,(ix+14)        ; Set FCB/file not modified
  1258.     ret                ; And return to caller
  1259. ;
  1260. ; Open next extent
  1261. ;
  1262. openex:    bit    7,(ix+14)        ; Test if FCB/file modified (write)
  1263.     jr    NZ,openx2        ; Not then jump
  1264.     call    close            ; Close current FCB
  1265.     ld    a,(pexit)        ; Get exit code
  1266.     inc    a            ; Test if error
  1267.     ret    Z            ; Yes then exit
  1268.     call    calnex            ; Calculate next extent
  1269.     jr    C,openx3        ; Error then jump
  1270.     jr    NZ,openx5        ; fCB present from close then jump
  1271. openx0:    
  1272.     call    sear0            ; Use fast lookup to find next extent
  1273. openx1:    call    tstfct            ; Test if file found
  1274.     jr    NZ,openx5        ; Yes then jump
  1275.     ld    a,(rdwr)        ; Test read/write flag
  1276.     or    a            ; Test if read
  1277.     jr    Z,openx3        ; Yes then error
  1278.     call    maker            ; Make new extent if write
  1279.     call    tstfct            ; Test if succesfull
  1280.     jr    NZ,openx6        ; Yes then exit
  1281.     jr    openx3            ; No then error
  1282. openx2:    call    calnex            ; Calculate next extent
  1283.     jr    NC,openx0
  1284. openx3:    set    7,(ix+14)        ; Set FCB/file not modified
  1285.     ld    a,0ffh            ; Set exit code
  1286. openx4:    ld    (pexit),a
  1287.     ret                ; And return to caller
  1288. openx5:    call    openf0            ; Open file
  1289. openx6:    xor    a            ; And clear exit code
  1290.     jr    openx4            ; Use same routine
  1291. ;
  1292. ; Calculate next extent
  1293. ;
  1294. ;    Exit:    C  overflow detected
  1295. ;        Z  search next extent
  1296. ;        NZ next extent present (close)
  1297. ;
  1298. calnex:    ld    b,(ix+12)        ; Get extent number
  1299.     ld    c,(ix+14)        ; Get FCB+14
  1300.     bit    6,c            ; Test error bit random record
  1301.     scf                ; Set error flag
  1302.     ret    NZ            ; Non zero then error exit
  1303.     inc    b            ; Increment extent number
  1304.     ld    a,b            ; Get extent number
  1305.     and    01fh            ; Mask it
  1306.     ld    b,a            ; Save it in b
  1307.     jr    NZ,calnx0        ; Non zero then jump
  1308.     inc    c            ; Increment FCB+14
  1309.     ld    a,c            ; Get it in a
  1310.     and    03fh            ; Mask it
  1311.     ld    c,a            ; Save it in c
  1312.     scf                ; Set error flag
  1313.     ret    Z            ; And return if file overflow
  1314.     xor    a            ; Clear zero flag (not same extent)
  1315.     jr    calnx1            ; And save extent number and FCB+14
  1316. calnx0:    ld    a,(nextnd)        ; Get next extent mask
  1317.     and    b            ; Test if same extent (close)
  1318. calnx1:    ld    (ix+12),b        ; Save extent number
  1319.     ld    (ix+14),c        ; Save FCB+14
  1320.     ret                ; And return to caller
  1321. ;
  1322. ; Read random record command
  1323. ;
  1324. cmnd33:    call    seldrv            ; Select drive from FCB
  1325. ;
  1326. ; Read random sector
  1327. ;
  1328. rdran:    xor    a            ; Set read/write flag
  1329.     call    ldFCB            ; Load random record in FCB
  1330.     jr    Z,reads            ; No error then read sector
  1331.     ret                ; Return error
  1332. ;
  1333. ; Read sequential
  1334. ;
  1335. cmnd20:    call    seldrv            ; Select drive from FCB
  1336. ;    ld    c,30h
  1337. ;    call    conout
  1338.  
  1339. ;
  1340. ; Read sector
  1341. ;
  1342. reads:    xor    a            ; Set read/write flag
  1343.     ld    (rdwr),a        ; Save it
  1344.     ld    a,(ix+32)        ; Get record counter
  1345.     cp    080h            ; Test if last record this extent
  1346.     jr    NC,reads1        ; Yes then open next extent
  1347.     cp    (ix+15)            ; Test if greater then current record
  1348.     jr    C,reads2        ; No then get record
  1349. reads0:    ld    a,1            ; Set end of file flag
  1350.     ld    (pexit),a        ; Save it
  1351.     ret                ; And return to caller
  1352. reads1:
  1353.     call    openex            ; ..To open next extent
  1354.     ld    a,(pexit)        ; Get exit code
  1355.     or    a
  1356.     jr    NZ,reads0        ; Yes then end of file
  1357.     ld    (ix+32),0        ; Clear record counter
  1358. reads2:    call    getdm            ; Get block number from dm in FCB
  1359.     ld    a,d            ; Test block number = 0
  1360.     or    e
  1361.     jr    Z,reads0        ; Yes then end file
  1362.     call    calsec            ; Calculate sector number (128 bytes)
  1363.     call    calst            ; Calculate sector/track number
  1364.     call    readr            ; Read data
  1365.     ld    a,(funct)        ; Get function number
  1366.     cp    20            ; Test if read sequential
  1367.     ret    NZ            ; No then return
  1368.     inc    (ix+32)            ; Increment next record counter
  1369.     ret                ; And return to caller
  1370. ;
  1371. ; Write random record commands
  1372. ;
  1373. cmnd34:
  1374. cmnd40:
  1375.     call    seldrv            ; Select drive from FCB
  1376. ;
  1377. ; Write random sector
  1378. ;
  1379. wrran:    ld    a,0ffh            ; Set read/write flag
  1380.     call    ldFCB            ; Load FCB from random record
  1381.     jr    Z,writes        ; No error then write record
  1382.     ret                ; Return error
  1383. ;
  1384. ; Write sequential
  1385. ;
  1386. cmnd21:
  1387.     call    seldrv            ; Select drive from FCB
  1388. ;
  1389. ; Write sector
  1390. ;
  1391. writes:
  1392.     ld    a,0ffh            ; Set read/write flag
  1393.     ld    (rdwr),a        ; And save it
  1394.     call    chkro            ; Check disk R/O
  1395.     bit    7,(ix+9)        ; Test if file R/O
  1396.     jp    NZ,chkfr2        ; Yes then file R/O message
  1397.  
  1398. ; Check for changed disk.
  1399. ; If disk changed:
  1400. ;     If file modified, abort.
  1401. ;     Else reset disk and disk changed bit.
  1402. ;
  1403.  
  1404. ; Test disk changed
  1405. ;
  1406.     ld    hl,(diff)        ; Get drive changed vector
  1407.     call    sdrvb            ; Set current drive bit
  1408.     sbc    hl,de            ; Test extra bit added
  1409.     jr    NZ,writsa        ; Bit added, so disk not changed
  1410.  
  1411. ; Test file modified
  1412. ;
  1413.     bit    7,(ix+14)        ; File modified?
  1414.     jp    Z,chgerr        ; Yes, abort and warm boot
  1415.  
  1416. ; Reset disk and disk changed bit.
  1417. ;    HL = 0 from SBC, DE = (diff) from SDRVB above
  1418. ;
  1419.     push    de            ; Save (diff)
  1420.     call    sdrvb            ; Set current bit only in HL
  1421.     pop    de            ; Get (diff)
  1422.     push    hl            ; Save current drive bit for reset
  1423.     ld    a,d
  1424.     xor    h
  1425.     ld    d,a            ; Mask current bit in DE
  1426.     ld    a,e
  1427.     xor    l
  1428.     ld    e,a
  1429.     ld    (diff),de        ; Reset disk changed bit in (diff)
  1430.     pop    de            ; Get current bit for disk reset
  1431.     call    cmnd37            ; No, reset drive:
  1432.     ld    a,(defdrv)        ; Get drive
  1433.     call    seldk            ; ..and log it in again
  1434. writsa:
  1435.     ld    a,(ix+32)        ; Get record count
  1436.     cp    080h            ; Test if end this extent
  1437.     jr    C,writs0        ; Yes then open next extent
  1438.     call    openex            ; Open next extent
  1439.     ld    a,(pexit)        ; Get error code
  1440.     or    a
  1441.     jp    NZ,writs9        ; Error then directory full error
  1442.     ld    (ix+32),0        ; Clear record counter
  1443. writs0:    call    getdm            ; Get block number from FCB
  1444.     ld    a,d            ; Test if block number = 0
  1445.     or    e
  1446.     jr    NZ,writs5        ; No then write sector
  1447.     push    hl            ; Save pointer to block number
  1448.     ld    a,c            ; Test first block number in extent
  1449.     or    a
  1450.     jr    Z,writs1        ; Yes then jump
  1451.     dec    a            ; Decrement pointer to block number
  1452.     call    getdm4            ; Get previous blocknumber
  1453. writs1:    call    getfre            ; Get nearest free block
  1454.     pop    hl            ; Get pointer to block number
  1455.     ld    a,d            ; Test if blocknumber = 0
  1456.     or    e
  1457.     jr    Z,writs8        ; Yes then disk full error
  1458.     res    7,(ix+14)        ; Reset FCB/file modified
  1459.     ld    (hl),e            ; Save blocknumber
  1460.     ld    a,(maxlen+1)        ; Get number of blocks
  1461.     or    a            ; Test if <256
  1462.     jr    Z,writs2        ; Yes then jump
  1463.     inc    hl            ; Increment to MSB block number
  1464.     ld    (hl),d            ; Save MSB block number
  1465. writs2:    ld    c,2            ; Set write new block flag
  1466.     ld    a,(nmask)        ; Get sector mask
  1467.     and    (ix+32)            ; Mask with record counter
  1468.     jr    Z,writsx        ; Zero then ok (at start new record)
  1469.     ld    c,0            ; Else clear new block flag
  1470. writsx:    ld    a,(funct)        ; Get function number
  1471.     sub    40            ; Test if write rr with zero fill
  1472.     jr    NZ,writs6        ; No then jump
  1473.     push    de            ; Save blocknumber
  1474.     ld    hl,(dirbuf)        ; Use directory buffer for zero fill
  1475.     ld    b,128            ; 128 bytes to clear
  1476. writs3:    ld    (hl),a            ; Clear directory buffer
  1477.     inc    hl            ; Increment pointer
  1478.     djnz    writs3            ; Clear all bytes
  1479.     call    calsec            ; Calculate sector number (128 bytes)
  1480.     ld    a,(nmask)        ; Get sector mask
  1481.     ld    b,a            ; Copy it
  1482.     inc    b            ; Increment it to get number of writes
  1483.     cpl                ; Complement sector mask
  1484.     and    e            ; Mask sector number
  1485.     ld    e,a            ; And save it
  1486.     ld    c,2            ; Set write new block flag
  1487. writs4:    push    hl            ; Save registers
  1488.     push    de
  1489.     push    bc
  1490.     call    calst            ; Calculate sector/track
  1491.     call    DMAdir            ; Set DMA directory buffer
  1492.     pop    bc            ; Get write new block flag
  1493.     push    bc            ; Save it again
  1494.     call    writer            ; Write record on disk
  1495.     pop    bc            ; Restore registers
  1496.     pop    de
  1497.     pop    hl
  1498.     ld    c,0            ; Clear write new block flag
  1499.     inc    e            ; Increment sector number
  1500.     djnz    writs4            ; Write all blocks
  1501.     call    stDMA            ; Set user DMA address
  1502.     pop    de            ; Get block number
  1503. writs5:    ld    c,0            ; Clear write new block flag
  1504. writs6:    res    7,(ix+14)        ; Reset FCB/file modified flag
  1505.     push    bc            ; Save it
  1506.     call    calsec            ; Calculate sector number (128 bytes)
  1507.     call    calst            ; Calculate sector/track
  1508.     pop    bc            ; Get write new block flag
  1509.     call    writer            ; Write record on disk
  1510.     ld    a,(ix+32)        ; Get record counter
  1511.     cp    (ix+15)            ; Compare with next record
  1512.     jr    C,writs7        ; If less then jump
  1513.     inc    a            ; Increment record count
  1514.     ld    (ix+15),a        ; Save it on next record position
  1515.     res    7,(ix+14)        ; Reset FCB/file modified flag
  1516. writs7:    ld    a,(funct)        ; Get function number
  1517.     cp    21            ; Test write sequential
  1518.     ret    NZ            ; Not then return
  1519.     inc    (ix+32)            ; Increment record count
  1520.     ret                ; And return to caller
  1521. writs8:    ld    a,2            ; Set disk full error
  1522.     ld    (pexit),a
  1523.     ret                ; And return to caller
  1524. writs9:    ld    a,1            ; Set directory full flag
  1525.     ld    (pexit),a
  1526.     ret                ; And return to caller
  1527. ;
  1528. ; Load FCB for random read/write
  1529. ;
  1530. ;    Exit:    Z  no error
  1531. ;        NZ error occured
  1532. ;
  1533. ldFCB:    ld    (rdwr),a        ; Save read/write flag
  1534.     ld    a,(ix+33)        ; Get first byte random record
  1535.     ld    d,a            ; Save it in d
  1536.     res    7,d            ; Reset MSB to get next record
  1537.     rla                ; Shift MSB in carry
  1538.     ld    a,(ix+34)        ; Load next byte random record
  1539.     rla                ; Shift carry
  1540.     push    af            ; Save it
  1541.     and    01fh            ; Mask next extent
  1542.     ld    c,a            ; Save it in c
  1543.     pop    af            ; Get byte
  1544.     rla                ; Shift 4 times
  1545.     rla
  1546.     rla
  1547.     rla
  1548.     and    0fh            ; Mask it
  1549.     ld    b,a            ; Save FCB+14
  1550.     ld    a,(ix+35)        ; Get next byte random record
  1551.     ld    e,6            ; Set random record to large flag
  1552.     cp    4            ; Test random record to large
  1553.     jr    NC,ldFCB8        ; Yes then error
  1554.     rlca                ; Shift 4 times
  1555.     rlca
  1556.     rlca
  1557.     rlca
  1558.     add    a,b            ; Add byte
  1559.     ld    b,a            ; Save FCB+14 in b
  1560.     ld    (ix+32),d        ; Set next record count
  1561.     ld    d,(ix+14)        ; Get FCB+14
  1562.     bit    6,d            ; Test error random record
  1563.     jr    NZ,ldFCB0        ; Yes then jump
  1564.     ld    a,c            ; Get new extent number
  1565.     cp    (ix+12)            ; Compare with FCB
  1566.     jr    NZ,ldFCB0        ; Not equal then open next extent
  1567.     ld    a,b            ; Get new FCB+14
  1568.     xor    (ix+14)            ; Compare with FCB+14
  1569.     and    03fh            ; Mask it
  1570.     jr    Z,ldFCB6        ; Equal then return
  1571. ldFCB0:    bit    7,d            ; Test FCB modified (write)
  1572.     jr    NZ,ldFCB1        ; No then jump
  1573.     push    de            ; Save registers
  1574.     push    bc
  1575.     call    close            ; Close extent
  1576.     pop    bc            ; Restore registers
  1577.     pop    de
  1578.     ld    e,3            ; Set close error
  1579.     ld    a,(pexit)        ; Get exit code
  1580.     inc    a
  1581.     jr    Z,ldFCB7        ; Error then exit
  1582. ldFCB1:    ld    (ix+12),c        ; Save new extent number
  1583.     ld    (ix+14),b        ; Save new FCB+14
  1584. ;    bit    7,d            ; Test FCB modified (previous FCB)
  1585. ;    jr    NZ,ldFCB3        ; No then jump
  1586. ;ldFCB2:
  1587. ;    call    sear0            ; File was opened for writing, so
  1588.                     ; the close filled in FCB+13 for fast
  1589.                     ; lookup, so do it
  1590. ;    jr    ldFCB4            ; Jump
  1591.  
  1592. ldFCB3:
  1593.     call    findf            ; Open file old way because may not
  1594.                     ; have valid FCB+13 for fast lookup
  1595.  
  1596. ldFCB4:    ld    a,(pexit)        ; Get error code
  1597.     inc    a
  1598.     jr    NZ,ldFCB5        ; No error then exit
  1599.     ld    a,(rdwr)        ; Get read/write flag
  1600.     ld    e,4            ; Set read empty record
  1601.     inc    a
  1602.     jr    NZ,ldFCB7        ; Read then error
  1603.     call    maker            ; Make new FCB using fast lookup
  1604.     ld    e,5            ; Set make error
  1605.     ld    a,(pexit)        ; Get error code
  1606.     inc    a
  1607.     jr    Z,ldFCB7        ; Error then exit
  1608.     jr    ldFCB6            ; No error exit (zero set)
  1609. ldFCB5:    call    openf0            ; Open file
  1610. ldFCB6:
  1611.     xor    a            ; Set zero flag and clear error code
  1612.     ld    (pexit),a
  1613.     ret                ; And return to caller
  1614. ldFCB7:    ld    (ix+14),0c0h        ; Set random record error
  1615. ldFCB8:    ld    a,e            ; Get error code
  1616.     ld    (pexit),a        ; And save it
  1617.     set    7,(ix+14)        ; Set FCB/file not modified
  1618.     or    a            ; Clear zero flag
  1619.     ret                ; And return to caller
  1620. ;
  1621. ; Calculate random record
  1622. ;    Entry:    HL = offset in FCB
  1623. ;        DE = FCB pointer
  1624. ;    Exit:    D  = LSB random record
  1625. ;        C  = ISB random record
  1626. ;        B  = MSB random record
  1627. ;
  1628. calrrc:    add    hl,de            ; Pointer to FCB+15 or FCB+32
  1629.     ld    a,(hl)            ; Get byte
  1630.     ld    hl,12            ; Offset to extent number
  1631.     add    hl,de            ; Get pointer to extent byte
  1632.     ld    d,a            ; Save first byte
  1633.     ld    a,(hl)            ; Get extent byte
  1634.     and    01fh            ; Mask it
  1635.     rl    d            ; Shift MSB in carry
  1636.     adc    a,0            ; Add carry
  1637.     rra                ; Shift 1 time (16 bits)
  1638.     rr    d
  1639.     ld    c,a            ; Save isb
  1640.     inc    hl            ; Increment to FCB+14
  1641.     inc    hl
  1642.     ld    a,(hl)            ; Get FCB+14
  1643.     rrca                ; Shift 4 times
  1644.     rrca
  1645.     rrca
  1646.     rrca
  1647.     push    af            ; Save it
  1648.     and    03h            ; Mask MSB
  1649.     ld    b,a            ; Save it
  1650.     pop    af            ; Get LSB
  1651.     and    0f0h            ; Mask it
  1652.     add    a,c            ; Add with isb
  1653.     ld    c,a            ; Save isb
  1654.     ret    NC            ; No carry then return
  1655.     inc    b            ; Increment MSB
  1656.     ret                ; And return to caller
  1657.  
  1658. ; END Z80DDISK.Z80
  1659.  
  1660.