?login_element?

Subversion Repositories NedoOS

Rev

Rev 776 | Rev 1539 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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