?login_element?

Subversion Repositories NedoOS

Rev

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