Subversion Repositories NedoOS

Rev

Rev 1613 | Blame | Compare with Previous | Last modification | View Log | Download

  1. TRUE=0xff
  2. FALSE=0x00
  3.  
  4. SECINBLK=255;32;16 ;TR-DOS reserves 16 sectors per block
  5. ;FILENAMESZ=9;10 for multi-block files (block # in +9)
  6.  
  7. _fin
  8.         ;EXPORT _fin
  9.         DW 0
  10. _fout
  11.         ;EXPORT _fout
  12.         DW 0
  13. ;_waseof
  14.         ;EXPORT _waseof
  15.         ;DB 0
  16.  
  17. TRDOSFCB=0
  18.         ;db 0 ;0 = free, 'r' = read, 'w' = write
  19. TRDOSFCB=TRDOSFCB+1
  20. ;;;;;;;;;;;;;;; copy of TR-DOS descriptor ;;;;;;;;;;;;;;
  21. TRDOSFCB.fn=TRDOSFCB
  22.         ;db "12345678c" ;filename
  23. TRDOSFCB=TRDOSFCB+9
  24. TRDOSFCB.block=TRDOSFCB
  25.         ;db 0 ;cur block for write, next block for read
  26.         ;db 0x60 ;(padding for "start")
  27. TRDOSFCB=TRDOSFCB+2
  28. TRDOSFCB.lastlen=TRDOSFCB
  29.         ;dw 0 ;length of block
  30. TRDOSFCB=TRDOSFCB+2
  31. TRDOSFCB.secinblk=TRDOSFCB
  32.         ;db 0 ;sectors remained in block (for read), block size (for write)
  33. TRDOSFCB=TRDOSFCB+1
  34. TRDOSFCB.firstsector=TRDOSFCB
  35.         ;dw 0 ;first sector of block (for write)
  36. TRDOSFCB=TRDOSFCB+2
  37. ;;;;;;;;;;;;;;; end of TR-DOS descriptor ;;;;;;;;;;;;;;
  38. TRDOSFCB.cursector=TRDOSFCB
  39.         ;dw 0 ;cur sector for write, next sector for read
  40. TRDOSFCB=TRDOSFCB+2
  41. TRDOSFCB.remain=TRDOSFCB
  42.         ;db 0xff ;remaining bytes in buf (for read)
  43. TRDOSFCB=TRDOSFCB+1
  44. TRDOSFCB.secwritten=TRDOSFCB
  45.         ;db 0 ;sectors written (for write)
  46. TRDOSFCB=TRDOSFCB+1
  47. TRDOSFCB.descpos=TRDOSFCB
  48.         ;db 0 ;position of descriptor (for write) 0..127
  49. TRDOSFCB=TRDOSFCB+1
  50. TRDOSFCB.waseof=TRDOSFCB
  51.         ;db 0 ;-1 = waseof
  52. TRDOSFCB=TRDOSFCB+1
  53. TRDOSFCB.drive=TRDOSFCB
  54.         ;db 0 ;-1 = waseof
  55. TRDOSFCB.buf=256;$-TRDOSFCB
  56.         ;ds 256 ;buffer for last sector
  57.  
  58.         ;align 256
  59. TRDOSFCB1=trdos_fcbbuf
  60.         ;ds 0x200*trdos_MAXFILES ;max 8 files
  61. DOSBUF=trdos_sectorbuf
  62.         ;ds 0x100
  63. ;TRDOSFCB2.=0x4a00 ;aligned
  64. ;TRDOSFCB3.=0x4c00 ;aligned
  65. ;TRDOSFCB4.=0x4e00 ;aligned
  66. ;TRDOSFCB5.=0x5000 ;aligned
  67. ;DOSBUF=0xff00 ;aligned
  68.  
  69.         if 1==0
  70. ;hl = poi to filename in string
  71. findlastslash.
  72. nfopenfnslash.
  73.         ld d,h
  74.         ld e,l ;de = after last slash
  75. ;find last slash
  76. nfopenfnslash0.
  77.         ld a,[hl]
  78.         inc hl
  79.         or a
  80.         jr z,nfopenfnslashq.
  81.         cp '/'
  82.         jr nz,nfopenfnslash0.
  83.         jr nfopenfnslash.
  84. nfopenfnslashq.
  85. ;de = after last slash
  86.         ret
  87.         endif
  88.  
  89. nfdel
  90. ;de=FCB
  91. ;TODO mask
  92.         inc de ;filename
  93. nfdel_filename
  94.         ld lx,0 ;number of files just deleted
  95. ;TODO extra buffer for tr0sec8 and read number of files
  96.         ld b,8 ;sectors
  97. nfdelsectors0.
  98.         ld hx,0 ;number of files just deleted in this sector
  99.         push bc
  100.         push de ;filename
  101.         push ix
  102.         ld d,0 ;track
  103.         ld a,8
  104.         sub b
  105.         ld e,a ;sector
  106.         call rdsecDOSBUF
  107.         pop ix
  108.         pop de ;filename
  109.         pop bc
  110. ;de=filename
  111. ;b=sectors
  112.         ld hl,DOSBUF
  113. nfdelcp0.
  114.         push bc
  115.         push de ;filename
  116.         push hl ;DOSBUF+
  117.         ld bc,0x900 ;b=bytes to compare, c=errors
  118. nfdelcp00.
  119.         ld a,[de]
  120.         sub [hl]
  121.         or c
  122.         ld c,a ;errors
  123.         inc hl
  124.         inc de
  125.         djnz nfdelcp00.
  126.         pop hl ;DOSBUF+
  127.         pop de ;filename
  128.         pop bc
  129.         jr nz,nfdelcp_notthatfile
  130.         inc hx ;number of files just deleted in this sector
  131.        ;how to check last file? quick fix: if next file is 0 or end of dir ((b==1) && (l==0xf0))
  132.        push de
  133.        push hl
  134.         ld a,l
  135.         add a,13
  136.         ld l,a
  137.         ld a,(hl) ;sectors in deleted file
  138.         ld (nfdel_addfree),a
  139.         inc l
  140.         ld e,(hl)
  141.         inc l
  142.         ld d,(hl) ;trsec of deleted file
  143.         ld (nfdel_firstfree),de
  144.         inc l
  145.         jr nz,nfdelcp_delnolastinsector
  146.         ld a,b
  147.         dec a
  148.         jr z,nfdelcp_delchecklastq
  149. nfdelcp_delnolastinsector
  150.         ld a,(hl)
  151.         or a
  152. nfdelcp_delchecklastq
  153.        pop hl
  154.        pop de
  155.        ld (hl),a;0 if last file (once!!!)
  156.        ld a,128 ;add flag for number of files just deleted (once!!!)
  157.        jr z,nfdelcp_notdel1 ;set flag "last file deleted"
  158.        ld a,1 ;add for number of files just deleted
  159.         ld (hl),1 ;deleted
  160. nfdelcp_notdel1
  161.         add a,lx
  162.         ld lx,a ;number of files just deleted
  163. nfdelcp_notthatfile
  164.         ld a,l
  165.         add a,16
  166.         ld l,a
  167.         jr nz,nfdelcp0. ;next descriptor
  168. ;was sector changed?
  169.         ld a,hx ;number of files just deleted in this sector
  170.         or a
  171.         jr z,nfdelcp_nodeletedinthissector
  172.         push bc
  173.         push de
  174.         push ix
  175.         ld d,0 ;track
  176.         ld a,8
  177.         sub b
  178.         ld e,a ;sector
  179.         call wrsecDOSBUF
  180.         pop ix
  181.         pop de
  182.         pop bc
  183. nfdelcp_nodeletedinthissector
  184.         djnz nfdelsectors0. ;next sector
  185.         xor a
  186.         cp lx
  187.         jr nz,nfdel_correctsystemsector
  188. ;not found
  189.         ld a,0xff ;fail
  190.         ret
  191. nfdel_correctsystemsector
  192. ;lx=files just deleted
  193. ;lx=1..127: deletion with 1
  194. ;lx=128..255: last deletion with 0
  195.         push ix
  196.         ld de,0x0008
  197.         push de
  198.         call rdsecDOSBUF
  199.         pop de
  200.         pop ix
  201. ;lx=1..127: deletion with 1
  202. ;lx=128..255: last deletion with 0
  203.        ld a,lx
  204.        add a,a
  205.        jr nc,nfdel_correctsystemsector_nodelwith0
  206. ;if deletion with 0:
  207.        rrca
  208.        ld lx,a ;files just deleted 0..127
  209.         ld hl,DOSBUF+0xe4 ;total files (including deleted ones)
  210.         dec [hl] ;we can only delete the last file record
  211.        ;ld a,[hl]
  212.        ;ld [files],a ;fail if many drives!
  213. nfdel_firstfree=$+1
  214.         ld hl,0
  215.         ld (DOSBUF+0xe1),hl ;first free sector
  216. nfdel_addfree=$+1
  217.         ld bc,0
  218.         ld hl,(DOSBUF+0xe5) ;free sectors
  219.         add hl,bc
  220.         ld (DOSBUF+0xe5),hl ;free sectors
  221. nfdel_correctsystemsector_nodelwith0
  222.         ld hl,DOSBUF+0xf4 ;del files
  223.         ld a,(hl)
  224.         add a,lx
  225.         ld (hl),a
  226.         ;ld de,0x0008
  227.         call wrsecDOSBUF
  228.         xor a ;success
  229.         ret
  230.        
  231. openwrite
  232.         ld c,'w'
  233. nfopen
  234. ;de=filename
  235. ;c=mode
  236. ;a=drive 0..3
  237.         ;EXPORT nfopen
  238.         push af
  239.        ld (trdoscurdrive),a
  240.          push bc
  241.          push de
  242.          ld a,c
  243.          cp 'w'
  244.          call z,nfdel_filename
  245.          pop de
  246.          pop bc
  247.         xor a
  248.         ld hl,TRDOSFCB1-0x0200
  249.  
  250.         inc h
  251.         inc h
  252.         cp [hl]
  253.         jr nz,$-3
  254. ;TODO check trdos_MAXFILES
  255.  
  256.         ld [hl],c ;mode in TRDOSFCB
  257.        
  258.         pop af
  259.         ld l,TRDOSFCB.drive
  260.         ld (hl),a
  261.         call trdossetdrvfromtrdosfcb ;l=0
  262.        
  263.         inc hl;ld l,TRDOSFCB.fn ;poi to fn in TRDOSFCB
  264.        
  265.         if 1==1
  266. ;de=filename
  267.         ex de,hl
  268.         ld bc,11
  269.         ldir
  270.         ex de,hl
  271.         else
  272.        
  273.         push hl ;poi to fn in TRDOSFCB
  274.         ld d,h
  275.         ld e,l
  276.         inc de
  277.         ld [hl],' '
  278.         ld bc,8
  279.         ldir ;empty filename
  280. nfopen.A.=$+1
  281.         ;EXPORT nfopen.A.
  282.         ld hl,0 ;poi to filename in string
  283.         call findlastslash.
  284. ;de = after last slash
  285.         pop hl ;poi to fn in TRDOSFCB
  286.         ld b,9
  287. nfopenfn0.
  288.         ld a,[de]
  289.         or a
  290.         jr z,nfopenfnq. ;no extension in string
  291.         inc de
  292.         cp '.'
  293.         jr z,nfopenfndot.
  294.         ld [hl],a
  295.         inc hl
  296.         djnz nfopenfn0.
  297. ;9 bytes in filename, no dot (9th byte goes to extension)
  298.         jr nfopenfnq.
  299. nfopenfndot.
  300.         inc hl
  301.         djnz $-1 ;hl points to extension in TRDOSFCB
  302.         dec hl
  303.         ld a,[de] ;extension in string
  304.         ld [hl],a ;extension in TRDOSFCB
  305. nfopenfnq.
  306.         endif
  307.  
  308. nfopen_reopen
  309. ;h-TRDOSFCB/256
  310.         ;xor a
  311.         ;ld l,TRDOSFCB.block
  312.         ;ld [hl],a;0 ;cur block for write, next block for read ;TODO брать из имени (тупо закомментировать)
  313.         ;inc hl
  314.         ;ld [hl],0x60 ;(padding for "start") ;TODO брать из имени (тупо закомментировать)
  315.        
  316.         ld l,0
  317.         ld a,(hl)
  318.         cp 'w'
  319.         jr z,nfopen_nofindfile ;TODO удалить, если есть
  320. ;проверить, что файл существует, иначе вернуть ошибку и освободить FCB
  321.         ld c,9 ;FILENAMESZ
  322.          ld l,TRDOSFCB.fn ;poi to fn
  323.         call findfile
  324.         or a
  325.         jr nz,nfopen_fail
  326. ;hl,de = after filename
  327. ;open for read!
  328.         ld l,TRDOSFCB.block
  329.         ld a,(de)
  330.         inc de
  331.         ld [hl],a;0 ;cur block for write, next block for read
  332.         inc hl
  333.         ld a,(de)
  334.         inc de
  335.         ld [hl],a;0x60 ;(padding for "start")
  336.        ;ld a,FALSE
  337.        ;ld [_waseof],a
  338.        ld l,TRDOSFCB.waseof
  339.        ld [hl],FALSE
  340. nfopen_nofindfile
  341.  
  342.         xor a
  343.         ld l,TRDOSFCB.lastlen
  344.         ld [hl],a;0 ;lastlen LSB ;???
  345.         inc hl
  346.         ld [hl],a;0 ;lastlen HSB ;???
  347.         inc hl
  348.         ld [hl],a;0 ;sectors remained in block (for read), block size (for write)
  349.         ld l,TRDOSFCB.remain
  350.         ld [hl],0xff ;remain (0xff = no data) for read
  351.         inc hl
  352.         ld [hl],a;0 ;sectors written (for write)
  353.         ld l,a;0;TRDOSFCB.mode
  354.         ret ;hl = poi to TRDOSFCB ;a=0 (success)
  355.  
  356. nfopen_fail
  357.         ld l,0
  358.         ld (hl),l;0 ;empty FCB
  359.         ;ld a,0xff
  360.         ret
  361.        
  362. trdossetdrvfromtrdosfcb
  363.        ld l,TRDOSFCB.drive
  364.        ld a,(hl)
  365.        ld (trdoscurdrive),a
  366.        ld l,0
  367.        ret
  368.  
  369. ;closewrite
  370.         ;EXPORT closewrite
  371. fclose
  372. ;hl=poi to TRDOSFCB
  373.         ;EXPORT fclose
  374. ;closewrite.A.=$+1
  375.         ;EXPORT closewrite.A.
  376. ;fclose.A.=$+1
  377.         ;EXPORT fclose.A.
  378.         ;ld hl,0 ;poi to TRDOSFCB
  379.        call trdossetdrvfromtrdosfcb
  380.         ld a,[hl]
  381.         ld [hl],l;0
  382.         cp 'w'
  383.         ret nz ;hl!=0
  384. ;hl = poi to TRDOSFCB
  385.         call flush.
  386.         ;следующая проверка не годится, если будет ручной flush:
  387.         ld l,TRDOSFCB.secwritten
  388.         ld a,[hl]
  389.         or a
  390.         ret z ;no sectors written - descriptor already saved (??? TODO)
  391.  
  392.        push hl ;hl = poi to TRDOSFCB
  393. ;is this the last file?
  394.         ld de,0x0008
  395.         call rdsecDOSBUF
  396.        pop hl
  397.        push hl
  398.         ld a,[DOSBUF+0xe4] ;total files (including deleted ones)
  399.         dec a
  400.         ld l,TRDOSFCB.descpos
  401.         cp [hl]
  402.         jr nz,fclose_nolastfile ;not the last file        
  403. ;cutting down the last file
  404.         ld l,TRDOSFCB.fn+11
  405.         ld c,[hl]
  406.         inc hl
  407.         ld b,[hl] ;length
  408.         inc hl
  409.         dec bc
  410.         inc b
  411.         ld a,[hl]
  412.         sub b
  413.          ld [hl],b ;sectors in file
  414.         inc b
  415.         djnz fclose_nolen0
  416.         push hl
  417.         ld l,TRDOSFCB.fn
  418.         ld [hl],b;0
  419.         ld hl,DOSBUF+0xe4 ;total files (including deleted ones)
  420.         dec [hl] ;we can only delete the last file record
  421.         pop hl
  422. fclose_nolen0
  423.         push bc ;b=sectors in file
  424.         ld e,a
  425.         ld d,0 ;de=sectors freeed
  426.         inc hl;ld l,TRDOSFCB.fn+14 ;trsec
  427.         ld c,[hl]
  428.         inc hl
  429.         ld b,[hl]
  430.         ld hl,(DOSBUF+0xe5) ;free sectors
  431.         add hl,de
  432.         ld (DOSBUF+0xe5),hl ;free sectors
  433.  
  434.         pop af ;a=sectors in file
  435.         ld lx,a
  436. ;bc=trsec
  437. ;lx=number of sectors to add
  438.         call addsectors
  439.         ld (DOSBUF+0xe1),bc ;first free sector
  440.  
  441.         ld de,0x0008
  442.         call wrsecDOSBUF
  443. fclose_nolastfile
  444.        pop hl ;hl = poi to TRDOSFCB
  445.         ;call flushdesc.
  446.         ;ld l,1 ;OK TODO
  447.         ;ret ;hl!=0
  448. ;write descriptor
  449. ;if created or finished
  450. flushdesc.
  451. ;hl = poi to TRDOSFCB
  452.         push hl ;poi to TRDOSFCB
  453.  
  454.         push hl ;poi to TRDOSFCB
  455.         ld l,TRDOSFCB.descpos
  456.         ld l,[hl]
  457.         ld d,0 ;track of descriptor
  458.         ld h,d;0
  459.         add hl,hl
  460.         add hl,hl
  461.         add hl,hl
  462.         add hl,hl
  463.         ld e,h ;sector of descriptor
  464.         ld h,DOSBUF>>8
  465.         push hl ;hl = poi to descriptor
  466.         push de ;track,sector of descriptor
  467.         call rdsecDOSBUF
  468.         pop bc ;track,sector of descriptor
  469.         pop de ;poi to descriptor
  470.         pop hl ;poi to TRDOSFCB
  471.         push bc ;track,sector of descriptor
  472.        ld l,TRDOSFCB.fn+8
  473.        ld a,[hl]
  474.        cp 'B'
  475.        jr nz,flushdesc_nobasic
  476.        ld l,TRDOSFCB.fn+12
  477.        ld b,[hl]
  478.        dec hl
  479.        ld c,[hl] ;length
  480.        dec hl
  481.        ld [hl],b
  482.        dec hl
  483.        ld [hl],c ;start for basic
  484. flushdesc_nobasic
  485.         ld l,TRDOSFCB.fn
  486.         ld bc,16
  487.         ldir
  488.         pop de ;track,sector of descriptor
  489.         call wrsecDOSBUF
  490.  
  491.         pop hl ;poi to TRDOSFCB
  492.         ret
  493.  
  494.         if 1==0
  495. ;FUNC BOOL comparedesc FORWARD(PCHAR filename, PBYTE desc);
  496. comparedesc
  497. comparedesc.A.=$+1 ;filename
  498.         ld hl,0
  499.         call findlastslash.
  500. ;de = after last slash
  501. comparedesc.B.=$+1 ;desc
  502.         ld hl,0
  503. ;compare until '.' or '\0' or 8 loops
  504.         ld b,8
  505. comparedesc0.
  506.         ld a,[de] ;filename
  507.         ;or a
  508.         ;jr z,comparedesctrue. ;filename ended without ext (descriptor not ended)
  509.         inc de
  510.         cp '.'
  511.         jr z,comparedescdot.
  512.         cp [hl] ;descriptor
  513.         jr nz,comparedescfalse.
  514.         inc hl
  515.         djnz comparedesc0.
  516.         ld a,[de] ;filename
  517.         inc de
  518.         cp '.'
  519.         jr z,comparedescdot8. ;filenam8.ext
  520.         ;filenam8 (without ext)
  521.         ld a,[hl]
  522.         cp ' '
  523.         jr nz,comparedescfalse.
  524. comparedesctrue.
  525.         ld a,0xff ;TRUE
  526.         ret
  527. comparedescdot.
  528.         inc hl
  529.         djnz $-1 ;hl = descriptor ext
  530. comparedescdot8.
  531.         ld a,[de] ;filename ext
  532.         cp [hl] ;descriptor ext
  533.         jr z,comparedesctrue.
  534. comparedescfalse.
  535.         xor a ;FALSE
  536.         ret
  537.         endif
  538.  
  539. findfile
  540. ;find new block if exists
  541. ;find Nth block of file with hl pointed filename (10 bytes: name, ext, block N)
  542. ;hl=filename
  543. ;c=FILENAMESZ
  544. ;out: z=found (carry = off, a = 0, hl,de = after filename)
  545.          ;ld l,TRDOSFCB.fn ;poi to fn
  546.         ld b,8 ;sectors
  547. findfile0.
  548.         push bc
  549.         push hl
  550.         ld d,0 ;track
  551.         ld a,8
  552.         sub b
  553.         ld e,a ;sector
  554.         call rdsecDOSBUF
  555.         pop hl
  556.         pop bc
  557. ;hl=filename
  558. ;b=sectors
  559.         ld de,DOSBUF
  560. findfilecp0.
  561.          ;ld l,TRDOSFCB.fn ;poi to fn
  562.         push bc
  563.         ld b,c ;FILENAMESZ
  564.         ld c,0 ;b=bytes to compare, c=errors
  565. findfilecp00.
  566.         ld a,[de]
  567.         sub [hl]
  568.         or c
  569.         ld c,a ;errors
  570.         inc hl
  571.         inc de
  572.         djnz findfilecp00.
  573.         pop bc
  574.         ret z ;found (carry = off, a = 0, hl,de = after filename)
  575. findfile_continue
  576.          ld a,l
  577.          sub c
  578.          ld l,a
  579.          sbc a,l
  580.          add a,h
  581.          ld h,a
  582.          ;ld b,a
  583.          ;sbc hl,bc
  584.         ld a,e
  585.         or 15;add a,16-FILENAMESZ;6
  586.         ld e,a
  587.         inc e
  588.         jr nz,findfilecp0. ;next descriptor
  589.         djnz findfile0. ;next sector
  590. ;not found
  591.         xor a
  592.         dec a ;nz=fail
  593.         ret
  594.  
  595. ;length 0 while reading means either absence of files or zero length file (any sector length)
  596.  
  597. ;readf
  598.         ;EXPORT readf
  599. ;readf.A.=$+1
  600.         ;EXPORT readf.A.
  601.         ;ld hl,0 ;poi to TRDOSFCB
  602.         ;jr fread1. ;a=data ;keeps bc
  603. ;readfin
  604. ;       ;EXPORT readfin
  605. ;       ld hl,[_fin] ;poi to TRDOSFCB
  606. fread1.
  607. ;a=data
  608.  ;;if ok then inc de?
  609. ;keeps bc
  610.         ld l,TRDOSFCB.remain ;0xff = no data, 0xfe = 1 byte, ... 0x00 = 255 bytes
  611.         ld e,[hl]
  612.         ld d,h
  613.         inc d
  614.         inc e
  615.         ld a,[de]
  616.         ld [hl],e ;inc [hl] ;remain
  617.         ret nz
  618. fread1noremain.
  619.         push bc
  620.          ;push de
  621. ;read new buf (if exists)
  622.         ld l,TRDOSFCB.secinblk
  623.         xor a
  624.         cp [hl] ;sectors remained in block (0 means none)
  625.         jr nz,fread1sec. ;a = 0
  626.         ld c,10 ;FILENAMESZ
  627.          ld l,TRDOSFCB.fn ;poi to fn
  628.         call findfile
  629.         jr z,fread1blkq. ;found (carry = off, a = 0, hl,de = after filename)
  630. ;not found
  631. ;EOF - next block doesn't exist
  632. fread1EOF.
  633.          ;pop de
  634.         pop bc
  635.        ;ld a,TRUE
  636.        ;ld [_waseof],a
  637.        ld l,TRDOSFCB.waseof
  638.        ld [hl],TRUE
  639.        ld a,0x0a;'\n' ;EOF returns '\n'
  640. ;set vars as they were (next time EOF again)
  641.         ld l,TRDOSFCB.remain
  642.         dec [hl] ;remain = 0xff
  643.         ret
  644. fread1blkq.
  645. ;de = poi to descriptor + 10
  646. ;hl = poi to fn + 10
  647. ;a = 0
  648.         ;ld l,TRDOSFCB.fn + 10
  649.         ex de,hl
  650. ;hl = poi to descriptor + 10
  651. ;de = poi to filename + 10
  652.         ld bc,16-10 ;padding, len(LSB), len(HSB), secinblk, sec, track
  653.         ldir
  654.         ex de,hl
  655.         ld l,TRDOSFCB.firstsector
  656.         ld e,[hl]
  657.         inc hl
  658.         ld d,[hl]
  659.         ld l,TRDOSFCB.cursector
  660.         ld [hl],e
  661.         inc hl
  662.         ld [hl],d
  663. ;secinblk = (lastlen+255)/256 = (lastlen-1)/256 + 1
  664. ;иначе нельзя будет выделять блоки навырост (как делает TR-DOS)
  665.         ld l,TRDOSFCB.lastlen
  666.         ld e,[hl]
  667.         inc hl
  668.         ld d,[hl]
  669.         dec de
  670.         inc d
  671.         inc hl ;ld l,TRDOSFCB.secinblk
  672.         ld [hl],d
  673.         jr z,fread1EOF. ;(secinblk == 0)
  674.         ld l,TRDOSFCB.block
  675.         inc [hl] ;cur block for write, next block for read
  676. fread1sec.
  677. ;read next sector
  678. ;a = 0
  679.         ld l,TRDOSFCB.cursector
  680.         push hl ;poi to cursector
  681.         ld e,[hl]
  682.         inc hl
  683.         ld d,[hl]
  684.         inc h
  685.         ld l,a;0 ;poi to buf
  686.         call rdsec.
  687.         ex de,hl ;ld de,[0x5cf4] ;de=next sector
  688.         pop hl ;poi to cursector
  689.         ld [hl],e
  690.         inc hl
  691.         ld [hl],d
  692. ;if last sector of block, then remain = -lastlen and shift data in buf to the end
  693. ;else remain = 0 (read + 255 bytes)
  694.         xor a
  695.         ld l,TRDOSFCB.secinblk
  696.         dec [hl] ;sectors remained in block
  697.         jr nz,fread1nlast.
  698. ;last sector in block: shift data to the end of buf
  699.         ld l,TRDOSFCB.lastlen
  700.         ld c,[hl] ;1..256
  701.         ld b,a;0
  702.         dec c ;0..255
  703.         ld l,c ;end of data
  704.         inc h
  705.         inc bc ;1..256
  706.         ld d,h
  707.         ld e,0xff
  708.         lddr
  709.         ;hl = poi to buf - 1
  710.         ;h = poi to TRDOSFCB
  711.         ld a,e ;0xfe (1 byte) ... -1 (256 bytes)
  712.         inc a ;remain = 0xff (read + no data) ... 0 (read + 255 bytes)
  713. fread1nlast.
  714.         ld l,TRDOSFCB.remain
  715.         ld [hl],a
  716.          ;pop de
  717.         pop bc
  718. fread1ok.
  719. ;hl = poi to remain
  720.         ld l,[hl]
  721.         inc h
  722.         ld a,[hl]
  723.          ;inc de
  724.         ret
  725.  
  726. fread
  727. ;hl=poi to data
  728. ;de=poi to TRDOSFCB
  729. ;bc=size
  730. ;out: hl=total processed bytes
  731.         ;EXPORT fread
  732. ;fread.A.=$+1
  733.         ;EXPORT fread.A.
  734.         ;ld hl,0 ;poi to data
  735.          ;ld de,0 ;total processed bytes
  736. ;fread.C.=$+1
  737.         ;EXPORT fread.C.
  738.         ;ld bc,0 ;count
  739. ;fread0.
  740.         ;push bc
  741. ;fread.B.=$+1
  742.         ;EXPORT fread.B.
  743.         ;ld bc,0 ;size
  744.        ex de,hl
  745.        call trdossetdrvfromtrdosfcb
  746.        ex de,hl
  747.         ;ld (fread00size),bc
  748.         ld (fread00addr),hl
  749.         if 1==1
  750. ;read by sectors:
  751.        ld e,TRDOSFCB.waseof
  752.        ld a,[de]
  753.        ;ld a,[_waseof]
  754.        or a ;FALSE
  755.        jp nz,fread00q;freadbysector0q
  756.         ld e,TRDOSFCB.remain ;0xff = no data, 0xfe = 1 byte, ... 0x00 = 255 bytes
  757.         ld a,[de]
  758.         inc a
  759.         jr nz,fread00. ;not at sector margin (TODO read the beginning by bytes)
  760.         ld a,b
  761.         or a
  762.         jr z,fread00. ;length < 256
  763.        dec bc
  764.        inc b ;b=number of loops
  765.  
  766. ;TODO if full block, read it with one dos call
  767. ;de=poi to TRDOSFCB
  768. ;hl=read addr
  769. ;bc="remaining size" (not quite)
  770.  
  771. ;if secinblk-1 < b, read secinblk-1 sectors, b-=(secinblk-1), secinblk = 1
  772.         ld e,TRDOSFCB.secinblk
  773.         ld a,[de] ;sectors remained in block
  774.         dec a
  775.         jr z,fread1nfulblock.
  776.          cp 63
  777.          jr nc,fread1nfulblock.
  778.         sub b
  779.         jr nc,fread1nfulblock. ;secinblk-1 >= b, a = (secinblk-1) - b
  780.         neg ;a = b - (secinblk-1)
  781.         ld b,a
  782.         push bc
  783.         ex de,hl
  784.         ld b,[hl] ;secinblk
  785.         dec b ;secinblk-1
  786.         ld [hl],1 ;secinblk
  787.         ld l,TRDOSFCB.cursector
  788.         push hl ;poi to cursector
  789. ;de=read addr
  790.         ld a,[hl]
  791.         inc hl
  792.         ld h,[hl] ;trsec
  793.         ld l,a
  794.         ex de,hl
  795. ;hl=read addr
  796. ;de=trsec
  797.        push bc
  798.        push hl
  799.         call rdsectors. ;b = secinblk-1 sectors
  800.         ld b,h
  801.         ld c,l ;ld bc,[0x5cf4] ;bc=next sector
  802.        pop de
  803.        pop af ;"b"
  804.        add a,d
  805.        ld d,a
  806. ;de=read addr
  807.         pop hl ;poi to cursector
  808.         ld [hl],c
  809.         inc hl
  810.         ld [hl],b
  811.         ex de,hl
  812. ;de=poi to TRDOSFCB
  813. ;hl=read addr
  814.         pop bc
  815. fread1nfulblock.
  816.  
  817. ;de=poi to TRDOSFCB
  818. ;hl=read addr
  819. ;bc=remaining size
  820. freadbysector0.
  821.         push de
  822.         push hl
  823.         ld h,d
  824.         ld e,0
  825.         inc d ;de=TRDOSFCB+256 (i.e. sector buffer)
  826.         call fread1noremain.
  827.         pop hl
  828.         pop de
  829.        ld e,TRDOSFCB.waseof
  830.        ld a,[de]
  831.        ;ld a,[_waseof]
  832.        or a ;FALSE
  833.        jr nz,fread00q
  834.         push bc
  835.         push de
  836.         ex de,hl ;data is at the end of buf
  837.         ld l,TRDOSFCB.remain ;0xff = 1 byte, 0xfe = 2 bytes, ... 0x00 = 256 bytes (including the returned byte that we've ignored)
  838.         ld l,[hl]
  839.         inc h ;hl=buf with data
  840.         ld b,a;0
  841.         ld a,l ;0xff..0x00
  842.         cpl
  843.         ld c,a ;0..255
  844.         inc bc ;1..256
  845.         ldir
  846.         ex de,hl
  847.         pop de
  848.         pop bc
  849.        inc a
  850.        jr nz,EOFfread00q ;last (short) sector in file
  851.         djnz freadbysector0.
  852. ;bc=remaining size < 256
  853.        ld e,TRDOSFCB.remain ;0xff = no data, 0xfe = 1 byte, ... 0x00 = 255 bytes
  854.        ld a,0xff
  855.        ld [de],a
  856.         jr fread00q
  857. EOFfread00q
  858.        ld e,TRDOSFCB.waseof
  859.        ld a,TRUE
  860.        ld [de],a
  861.         jr fread00q
  862.         endif
  863. ;de=poi to TRDOSFCB
  864. ;hl=read addr
  865. ;bc=remaining size
  866. ;read by bytes:
  867. fread00.
  868.         push de
  869.         push hl
  870. ;fread.D.=$+1
  871.         ;EXPORT fread.D.
  872.         ex de,hl ;ld hl,0 ;hl=poi to TRDOSFCB
  873.         call fread1. ;a=data ;keeps bc
  874.         pop hl
  875.         pop de
  876.         ld [hl],a ;may be EOF!
  877.        ld e,TRDOSFCB.waseof
  878.        ld a,[de]
  879.        ld e,0
  880.        ;ld a,[_waseof]
  881.        or a ;FALSE
  882.        jr nz,fread00q ;jr nz,freadpopret.
  883.         ;cpi
  884.         db 0xed,0xa1
  885.         jp pe,fread00.
  886.         ;pop bc
  887.         ;dec hl
  888.         ;cpi
  889.         ;db 0xed,0xa1
  890.         ;jp pe,fread0.
  891.          ;ex de,hl ;hl = total processed bytes
  892. fread00q
  893. ;bc=size-processedbytes
  894. ;fread00size=$+1
  895. ;        ld hl,0
  896. ;        xor a ;a=0: no error
  897. ;        sbc hl,bc ;hl=processedbytes
  898. ;hl=addr+processedbytes
  899. fread00addr=$+1
  900.         ld bc,0
  901.         xor a ;a=0: no error
  902.         sbc hl,bc ;hl=processedbytes
  903.         ret
  904. ;freadpopret.
  905.         ;pop bc
  906.         ;ret
  907.  
  908.         if 1==0
  909. fwritebyte
  910.         ;EXPORT fwritebyte
  911. fwritebyte.A.=$+1
  912.         ;EXPORT writebyte.A.
  913.         ld hl,0 ;file
  914. fwritebyte.B.=$+1
  915.         ;EXPORT writebyte.B.
  916.         ld a,0
  917.         jp fwrite1.
  918.         endif
  919. ;writefout
  920.         ;EXPORT writefout
  921.         ;ld hl,[_fout]
  922. ;writefout.A.=$+1
  923.         ;EXPORT writefout.A.
  924.         ;ld a,0
  925. ;hl = poi to TRDOSFCB
  926. ;a=data
  927. ;keeps bc
  928. fwrite1.
  929.         ;jr $
  930.         ld l,TRDOSFCB.lastlen
  931.         ld e,[hl]
  932.         ld d,h
  933.         inc d
  934.         ld [de],a
  935.         inc [hl] ;lastlen (LSB)
  936.         ;Z = end of buf
  937.         ret nz
  938.         inc l
  939.         inc [hl] ;lastlen (HSB)
  940. flush.
  941. ;ручной flush пока невозможен!!!
  942. ;can create zero length file
  943. ;hl = poi to TRDOSFCB
  944.         push bc
  945.  
  946. ;if secwritten == 0 then reserve sectors, reserve descriptor
  947.         ld l,TRDOSFCB.secwritten
  948.         ld a,[hl]
  949.         or a
  950.         jr nz,flushnnew.
  951. ;глючит, если последний блок <256 TODO
  952. ;потому что fclose второй раз вызывает flush
  953.         ld l,TRDOSFCB.secinblk
  954.         ld [hl],SECINBLK;16 ;TR-DOS reserves 16 sectors per block
  955. ;update sec8
  956.         push hl ;poi to TRDOSFCB
  957.         ld de,0x0008
  958.         push de
  959.         call rdsecDOSBUF
  960.         pop de ;0x0008
  961.         ld hl,[DOSBUF+0xe5] ;free sectors
  962.         ld bc,-SECINBLK;16
  963.         add hl,bc
  964.          ;bit 7,h
  965.          ;jr nz,$ ;no free sectors
  966.         ld [DOSBUF+0xe5],hl ;free sectors ;don't check for error! because now file size is 255 sectors! (will be cut later)
  967.         ;jr $
  968.         ld hl,DOSBUF+0xe4 ;files
  969.         ld a,[hl] ;descriptor position 0..127
  970.          ;or a
  971.          ;jp m,$ ;128 files, can't add
  972.         inc [hl] ;files
  973.  
  974.         ld l,0xe1 ;free sector
  975.         ld c,[hl]
  976.         inc hl
  977.         ld b,[hl]
  978.         ;inc [hl] ;add 16 sectors = add 1 track
  979.         push bc
  980.         ld lx,SECINBLK
  981.         call addsectors
  982.         ld (hl),b
  983.         dec hl
  984.         ld (hl),c
  985.         pop bc
  986.  
  987.         pop hl ;poi to TRDOSFCB
  988.         ld l,TRDOSFCB.descpos
  989.         ld [hl],a ;descriptor position 0..127
  990.         ld l,TRDOSFCB.firstsector
  991.         ld [hl],c
  992.         inc hl
  993.         ld [hl],b
  994.         ld l,TRDOSFCB.cursector
  995.         ld [hl],c
  996.         inc hl
  997.         ld [hl],b
  998.  
  999.         push hl ;poi to TRDOSFCB
  1000.         ;ld de,0x0008
  1001.         call wrsecDOSBUF ;write sec8
  1002.         pop hl ;poi to TRDOSFCB
  1003. flushnnew.
  1004.  
  1005. ;write buf
  1006.         ld l,TRDOSFCB.cursector
  1007.         push hl ;poi to cursector
  1008.         ld e,[hl]
  1009.         inc hl
  1010.         ld d,[hl]
  1011.         ld l,0
  1012.         inc h ;poi to buf
  1013.         call wrsec.
  1014.         ex de,hl ;ld de,(0x5cf4) ;de=next sector
  1015.         pop hl ;poi to cursector
  1016.         ld [hl],e
  1017.         inc hl
  1018.         ld [hl],d
  1019.  
  1020. ;increase secwritten
  1021. ;get new block if this block filled up
  1022.         ld l,TRDOSFCB.secinblk
  1023.         ld a,[hl]
  1024.         ld l,TRDOSFCB.secwritten
  1025.         inc [hl]
  1026.         sub [hl]
  1027.         jr nz,flushnblk. ;not filled up
  1028. ;block is filled up
  1029. ;zero secwritten
  1030.         ;ld l,TRDOSFCB.secwritten
  1031.         ld [hl],a;0 ;block not created
  1032. ;write descriptor
  1033.         call flushdesc.
  1034. ;increase block number (after flushdesc!!!)
  1035.         ld l,TRDOSFCB.block
  1036.         inc [hl] ;cur block for write, next block for read
  1037. ;теперь дескриптор невалидный, пока не создадим его в начале другого flush
  1038. ;zero lastlen (after flushdesc!!!)
  1039.         ld l,TRDOSFCB.lastlen+1 ;(HSB), LSB is already 0 if not fclose
  1040.         ld [hl],0
  1041. flushnblk.
  1042.  
  1043.         pop bc
  1044.         ret
  1045.  
  1046. addsectors
  1047. ;bc=trsec
  1048. ;lx=number of sectors to add
  1049. ;keeps a
  1050.         inc lx
  1051.         jr flush_addsectors_go
  1052. flush_addsectors0
  1053.         inc c
  1054.         bit 4,c
  1055.         jr z,$+2+3
  1056.         ld c,0
  1057.         inc b
  1058. flush_addsectors_go
  1059.         dec lx
  1060.         jr nz,flush_addsectors0
  1061.         ret
  1062.  
  1063. fwrite
  1064. ;hl=poi to data
  1065. ;de=poi to TRDOSFCB
  1066. ;bc=size
  1067.         ;EXPORT fwrite
  1068. ;fwrite.A.=$+1
  1069.         ;EXPORT fwrite.A.
  1070.         ;ld hl,0 ;poi to data
  1071.          ;ld de,0 ;total processed bytes TODO
  1072. ;fwrite.C.=$+1
  1073.         ;EXPORT fwrite.C.
  1074.         ;ld bc,0 ;count
  1075. ;fwrite0.
  1076.         ;push bc
  1077. ;fwrite.B.=$+1
  1078.         ;EXPORT fwrite.B.
  1079.         ;ld bc,0 ;size
  1080.        ex de,hl
  1081.        call trdossetdrvfromtrdosfcb
  1082.        ex de,hl
  1083.         ;ld (fread00size),bc
  1084.         ld (fread00addr),hl
  1085. fwrite00.
  1086.         ld a,[hl]
  1087.         push de
  1088.         push hl
  1089.          ;push de
  1090. ;fwrite.D.=$+1
  1091.         ex de,hl ;ld hl,0 ;poi to TRDOSFCB
  1092.         call fwrite1. ;a=data ;keeps bc
  1093.          ;pop de
  1094.          ;inc de
  1095.         pop hl
  1096.         pop de
  1097.         ;cpi
  1098.         db 0xed,0xa1
  1099.         jp pe,fwrite00.
  1100.         ;pop bc
  1101.         ;dec hl
  1102.         ;cpi
  1103.         ;db 0xed,0xa1
  1104.         ;jp pe,fwrite0.
  1105.          ;ex de,hl ;hl = total processed bytes
  1106.         jp fread00q ;ret
  1107.  
  1108. ;FUNC UINT readsectors FORWARD(PBYTE buf, UINT trsec, BYTE count);
  1109. readsectors
  1110. readsectors.A.=$+1 ;buf
  1111.         ld hl,0
  1112. readsectors.B.=$+1 ;trsec
  1113.         ld de,0
  1114. readsectors.C.=$+1 ;count
  1115.         ld b,0
  1116.         jr rdsectors.
  1117. rdsecDOSBUF
  1118.         ld hl,DOSBUF
  1119. rdsec.
  1120.         ld b,1
  1121. rdsectors.
  1122.         ld c,0x05
  1123.         ;push hl ;read address
  1124.         ;ld hl,0x8000 ;pgkillable
  1125.         ;push bc
  1126.         ;push hl
  1127.         jp iodos. ;hl=next sector
  1128.         ;pop hl
  1129.         ;pop bc
  1130.         ;ld c,0
  1131.         ;pop de ;read address
  1132.         ;ldir
  1133.         ;ld hl,(0x5cf4);(sysvars+0x00f4) ;next sector
  1134.         ;ret
  1135.  
  1136. ;FUNC UINT writesectors FORWARD(PBYTE buf, UINT trsec, BYTE count);
  1137. writesectors
  1138. writesectors.A.=$+1 ;buf
  1139.         ld hl,0
  1140. writesectors.B.=$+1 ;trsec
  1141.         ld de,0
  1142. writesectors.C.=$+1 ;count
  1143.         ld b,0
  1144.         jr wrsectors.
  1145. wrsecDOSBUF
  1146.         ld hl,DOSBUF
  1147. wrsec.
  1148.         ld b,1
  1149. wrsectors.
  1150.         ;push bc
  1151.         ;push de ;track,sector
  1152.         ;ld c,0
  1153.         ;ld de,0x8000 ;pgkillable
  1154.         ;push de
  1155.         ;ldir
  1156.         ;pop hl
  1157.         ;pop de ;track,sector
  1158.         ;pop bc
  1159.         ld c,0x06
  1160. iodos.
  1161. trdoscurdrive=$+1
  1162.         ld a,0xff
  1163.         call iodos_setdrive
  1164.         ;ld iy,23610
  1165.         call dos3d13. ;returns a=error (from 0x5d0f)
  1166.         ld hl,(0x5cf4);(sysvars+0x00f4) ;next sector
  1167.         ret
  1168.  
  1169. iodos_setdrive_okq
  1170.         xor a
  1171.         ret
  1172. iodos_setdrive
  1173. trdosolddrive=$+1
  1174.                 cp 0xff
  1175.                 jr z,iodos_setdrive_okq
  1176.                 ld (trdoscurdrive),a
  1177.                 push bc
  1178.                 push de
  1179.                 push hl
  1180.                 ld a,(trdoscurdrive)
  1181.                 ld c,1
  1182.                 call dos3d13nopg.
  1183.                 ;call iodos_chd_cherr
  1184.                 ld c,0x18
  1185.                 call dos3d13nopg.
  1186.                 call iodos_chd_cherr
  1187.                 ;ld bc,0x0105
  1188.                 ;ld hl,trdos_sectorbuf
  1189.                 ;ld de,0x0008
  1190.                 ;call dos3d13nopg.
  1191.                 ;call iodos_chd_cherr
  1192.                 ld a,(trdoscurdrive)
  1193.                 ld (trdosolddrive),a
  1194.                 xor a
  1195.                 jr iodos_chd_noerr
  1196. iodos_chd_cherr
  1197.                 or a
  1198.                 ret z
  1199.                 ld a,0xff
  1200.                 ld (trdosolddrive),a
  1201.         dec a ;Alone Coder: чтобы были не равны в следующий заход, тогда опять будем пытаться включить драйв
  1202.         ld (trdoscurdrive),a
  1203.                 ld a,0xff
  1204.                 pop hl
  1205. iodos_chd_noerr
  1206.         pop hl
  1207.         pop de
  1208.         pop bc
  1209.                 ret