Subversion Repositories NedoOS

Rev

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

  1. #include "../_sdk/io.h"
  2. #include "../_sdk/str.h"
  3.  
  4. VAR UINT _lentword;
  5. VAR CHAR _c1small;
  6. VAR CHAR _c2small;
  7.  
  8. FUNC BYTE aaa(BYTE b, BYTE c)
  9. {
  10. VAR UINT zxc;
  11. VAR UINT typeaddr; //фы  cast
  12. IF (+TRUE) {
  13.   IF (+FALSE) {
  14.     _lentword=1;
  15.     RETURN 0x00;
  16.   };
  17. };
  18. RETURN 0x00;
  19. }
  20.  
  21. VAR BYTE bb = aaa(0x02);
  22.  
  23. STRUCT FCB{
  24.   CHAR mode; //0 = free, 'r' = read, 'w' = write
  25. //copy of TR-DOS descriptor
  26.   CHAR fn;
  27.   CHAR fn1;
  28.   CHAR fn2;
  29.   CHAR fn3;
  30.   CHAR fn4;
  31.   CHAR fn5;
  32.   CHAR fn6;
  33.   CHAR fn7;
  34.   CHAR ext;
  35.   BYTE block; //cur block for write, next block for read (start LSB)
  36.   BYTE blockpad; // (start HSB)
  37.   BYTE lastlenLSB; BYTE lastlenHSB; //length of block in bytes //TODO т√Ёртэштрэшх!!!
  38.   BYTE secinblk; //sectors remained in block (for read), block size (for write)
  39.   BYTE firstsectorLSB; BYTE firstsectorHSB; //first sector of block (for write) //TODO т√Ёртэштрэшх!!!
  40. //end of TR-DOS descriptor
  41.   BYTE cursectorLSB; BYTE cursectorHSB; //cur sector for write, next sector for read //TODO т√Ёртэштрэшх!!!
  42.   BYTE remain; //remaining bytes in buf (for read)
  43.   BYTE secwritten; //sectors written (for write)
  44.   BYTE descpos; //position of descriptor (for write) 0..127
  45.   //BYTE buf; //256 bytes padded
  46. };
  47.  
  48. /**
  49. _fin
  50.         EXPORT _fin
  51.         DW 0
  52. _fout
  53.         EXPORT _fout
  54.         DW 0
  55. _waseof
  56.         EXPORT _waseof
  57.         DB 0
  58.  
  59. FCB1=0x4800 ;aligned ;len=0x0200
  60. DOSBUF=0xff00 ;aligned
  61. */
  62. EXPORT VAR PBYTE _fin;
  63. EXPORT VAR PBYTE _fout;
  64. EXPORT VAR BOOL _waseof;
  65. CONST PBYTE FCB1; // = 0x4800; //aligned ;len=0x0200
  66. //#define FCB1 (PBYTE)(0x4800) /**aligned, len = 0x0200 every FCB*/
  67. CONST PBYTE DOSBUF; // = 0xff00; //aligned
  68. //#define DOSBUF (PBYTE)(0xff00) /**aligned*/
  69.  
  70. VAR PBYTE pdesc;
  71.  
  72. #define DOSBUFfreesectorsLSB (PBYTE)(DOSBUF+0x00e5)
  73. #define DOSBUFfreesectorsHSB (PBYTE)(DOSBUF+0x00e6)
  74. #define DOSBUFfiles (PBYTE)(DOSBUF+0x00e4)
  75. #define DOSBUFfreesectorLSB (PBYTE)(DOSBUF+0x00e1)
  76. #define DOSBUFfreesectorHSB (PBYTE)(DOSBUF+0x00e2)
  77.  
  78. FUNC BOOL findfile(FCB* pfcb, BYTE namesz)
  79. {
  80. //find new block if exists
  81. //find Nth block of file with hl pointed filename (10 bytes: name, ext, block N)
  82. VAR PBYTE pfn;
  83. VAR BYTE sector;
  84. VAR BYTE i;
  85. VAR BYTE b;
  86. VAR BOOL res = +TRUE; //found
  87.     sector = 0x00;
  88.     REPEAT {
  89.       readsectors(DOSBUF, (UINT)sector, 0x01);
  90.       pdesc = DOSBUF;
  91. #define DOSBUFEND (UINT)(DOSBUF+0x0100)
  92.       REPEAT {
  93.         pfn = (PBYTE)&(pfcb->fn);
  94.         i = 0x00;
  95.         REPEAT {
  96.           b = *(PBYTE)pfn;
  97.           INC pfn;
  98.           IF (pdesc[i] != b) goto wrong;
  99.           INC i;
  100.         }UNTIL (i == namesz/**0x0a*/); //bytes to compare
  101.         goto found;
  102.         wrong:
  103.         pdesc = &pdesc[16];
  104.       }UNTIL ((UINT)pdesc == DOSBUFEND); //next descriptor
  105.       INC sector;
  106.     }UNTIL (sector == 0x08); //next sector
  107.   res = +FALSE; //not found
  108. found:
  109. RETURN res;
  110. }
  111.  
  112. /**
  113. findlastslash
  114. findlastslash.A.=$+1
  115.         ld hl,0
  116. ;hl = poi to filename in string
  117. nfopenfnslash.
  118.         ld d,h
  119.         ld e,l ;de = after last slash
  120. ;find last slash
  121. nfopenfnslash0.
  122.         ld a,[hl]
  123.         inc hl
  124.         or a
  125.         jr z,nfopenfnslashq.
  126.         cp '/'
  127.         jr nz,nfopenfnslash0.
  128.         jr nfopenfnslash.
  129. nfopenfnslashq.
  130.         ex de,hl
  131. ;hl = after last slash
  132.         ret
  133. */
  134. EXPORT FUNC PCHAR findlastslash(PCHAR s)
  135. {
  136. VAR PCHAR slast;
  137. VAR CHAR c;
  138.   loopslash:
  139.     slast = s;
  140.   loop:
  141.     c = *(PCHAR)s;
  142.     INC s;
  143.     IF (c == '\0') goto quit;
  144.     IF (c == '/') goto loopslash;
  145.     goto loop;
  146.   quit:
  147. RETURN slast;
  148. }
  149.  
  150. /**
  151. nfopen
  152. ;todo яЁютхЁ Є№ эрышўшх Їрщыр яЁш юЄъЁ√Єшш эр ўЄхэшх
  153.         EXPORT nfopen
  154.         xor a
  155.         ld hl,FCB1-0x0200
  156.  
  157.         inc h
  158.         inc h
  159.         cp [hl]
  160.         jr nz,$-3
  161.  
  162. ;nfopenFCB
  163. nfopen.B.=$+1
  164.         EXPORT nfopen.B.
  165.         ld a,[0] ;poi to mode ("wb"/"rb")
  166.         ld [hl],a ;mode in FCB
  167.         inc hl ;poi to fn in FCB
  168.         push hl ;poi to fn in FCB
  169.         ld d,h
  170.         ld e,l
  171.         inc de
  172.         ld [hl],' '
  173.         ld bc,8
  174.         ldir ;empty filename
  175. nfopen.A.=$+1
  176.         EXPORT nfopen.A.
  177.         ld hl,0 ;poi to filename in string
  178.         ld [findlastslash.A.],hl
  179.         call findlastslash
  180.         ex de,hl
  181. ;de = after last slash
  182.         pop hl ;poi to fn in FCB
  183.         ld b,9
  184. nfopenfn0.
  185.         ld a,[de]
  186.         or a
  187.         jr z,nfopenfnq. ;no extension in string
  188.         inc de
  189.         cp '.'
  190.         jr z,nfopenfndot.
  191.         ld [hl],a
  192.         inc hl
  193.         djnz nfopenfn0.
  194. ;9 bytes in filename, no dot (9th byte goes to extension)
  195.         jr nfopenfnq.
  196. nfopenfndot.
  197.         inc hl
  198.         djnz $-1 ;hl points to extension in FCB
  199.         dec hl
  200.         ld a,[de] ;extension in string
  201.         ld [hl],a ;extension in FCB
  202. nfopenfnq.
  203.         xor a
  204.         ld l,FCB.block
  205.         ld [hl],a;0 ;cur block for write, next block for read
  206.         inc hl
  207.         ld [hl],0x60 ;(padding for "start")
  208.         inc hl
  209.         ld [hl],a;0 ;lastlen LSB ;???
  210.         inc hl
  211.         ld [hl],a;0 ;lastlen HSB ;???
  212.         inc hl
  213.         ld [hl],a;0 ;sectors remained in block (for read), block size (for write)
  214.         ld l,FCB.remain
  215.         ld [hl],0xff ;remain (0xff = no data) for read
  216.         inc hl
  217.         ld [hl],a;0 ;sectors written (for write)
  218.         ld l,a;0;FCB.mode
  219.         ret ;hl = poi to FCB
  220. */
  221. EXPORT FUNC PBYTE nfopen(PCHAR filename, PCHAR pmode)
  222. {
  223. VAR FCB* pfcb = (FCB*)((UINT)FCB1 - 0x0200);
  224. VAR BYTE i = 0x09;
  225. VAR CHAR c;
  226. //VAR PBYTE pdesc;
  227.   REPEAT {
  228.     pfcb = (FCB*)((UINT)pfcb + 0x0200);
  229.   }UNTIL (*(PBYTE)pfcb == 0x00); //first free FCB
  230.   //pfcb->mode = *(PCHAR)pmode; //see in the end if success
  231.   pdesc = (PBYTE)&(pfcb->fn); //poi to fn in FCB
  232.   memcopy((PBYTE)"         ", 9, pdesc); //from, len, to
  233.   filename = findlastslash(filename); //after last slash
  234.   REPEAT {
  235.     c = *(PCHAR)filename;
  236.     IF (c == '\0') goto nfopenfnq; //no extension in string
  237.     INC filename;
  238.     IF (c == '.') goto nfopenfndot;
  239.     POKE *(PCHAR)(pdesc) = c;
  240.     INC pdesc;
  241.     DEC i;
  242.   }UNTIL (i == 0x00);
  243. //9 bytes in filename, no dot (9th byte goes to extension)
  244.   goto nfopenfnq;
  245. nfopenfndot:
  246.   pfcb->ext = *(PCHAR)filename;
  247. nfopenfnq:
  248.   pfcb->block = 0x00; //cur block (for write!!!)
  249.   pfcb->blockpad = 0x60; //padding for "start"
  250.  
  251. /**
  252.         ld l,a;0
  253.         ld a,(hl)
  254.         cp 'w'
  255.         jr z,nfopen_nofindfile. ;TODO єфрышЄ№, хёыш хёЄ№
  256. ;яЁютхЁшЄ№, ўЄю Їрщы ёє∙хёЄтєхЄ, шэрўх тхЁэєЄ№ ю°шсъє ш юётюсюфшЄ№ FCB
  257.         ld c,9 ;FILENAMESZ
  258.         call findfile
  259.         or a
  260.         jr nz,nfopen_fail.
  261. ;hl,de = after filename
  262. ;open for read!
  263.         ld l,FCB.block
  264.         ld a,(de)
  265.         inc de
  266.         ld [hl],a;0 ;cur block for write, next block for read
  267.         inc hl
  268.         ld a,(de)
  269.         inc de
  270.         ld [hl],a;0x60 ;(padding for "start")
  271.        ;ld a,FALSE
  272.        ;ld [_waseof],a
  273. nfopen_nofindfile.
  274. */
  275.   IF (*(PCHAR)pmode != 'w') {
  276.     IF (!findfile(pfcb, 0x09)) {
  277.       pfcb = (FCB*)0;
  278.       goto nfopenfail;
  279.     };
  280.     memcopy(pdesc, 11, (PBYTE)&(pfcb->fn)); //from, len, to
  281.   };
  282.  
  283.   pfcb->lastlenLSB = 0x00;
  284.   pfcb->lastlenHSB = 0x00;
  285.   pfcb->secinblk = 0x00; //sectors remained in block (for read), block size (for write)
  286.   pfcb->remain = 0xff; //remain (0xff = no data) for read
  287.   pfcb->secwritten = 0x00; //sectors written (for write)
  288.   pfcb->mode = *(PCHAR)pmode;
  289. nfopenfail:
  290. RETURN (PBYTE)pfcb;
  291. }
  292.  
  293. /**
  294. topenwr.
  295.         db "wb"
  296.         db 0
  297.  
  298. openwrite
  299.         EXPORT openwrite
  300.         ld hl,topenwr.
  301.         ld [nfopen.B.],hl
  302. openwrite.A.=$+1
  303.         EXPORT openwrite.A.
  304.         ld hl,0 ;filename
  305.         ld [nfopen.A.],hl
  306.         jp nfopen
  307.  
  308. */
  309. EXPORT FUNC PBYTE openwrite(PCHAR s)
  310. {
  311. RETURN nfopen(s, "wb");
  312. }
  313.  
  314. /**
  315. flushdesc
  316. flushdesc.A.=$+1
  317.         ld hl,0
  318.         push hl ;poi to FCB
  319.         ld l,FCB.descpos
  320.         ld l,[hl]
  321.         ld d,0 ;track of descriptor
  322.         ld h,d;0
  323.         add hl,hl
  324.         add hl,hl
  325.         add hl,hl
  326.         add hl,hl
  327.         ld e,h ;sector of descriptor
  328.         ld h,DOSBUF.>>8
  329.         push hl ;hl = poi to descriptor
  330.         push de ;track,sector of descriptor
  331.         call rdsecDOSBUF.
  332.         pop bc ;track,sector of descriptor
  333.         pop de ;poi to descriptor
  334.         pop hl ;poi to FCB
  335.         ld l,FCB.fn
  336.         push bc ;track,sector of descriptor
  337.         ld bc,16
  338.         ldir
  339.         pop de ;track,sector of descriptor
  340.         ld hl,DOSBUF.
  341.         call wrsec.
  342.         ret
  343. */
  344. //write descriptor
  345. //if created or finished
  346. PROC flushdesc(FCB* pfcb)
  347. {
  348. VAR UINT trsec = (UINT)((pfcb->descpos)>>0x04);
  349. //VAR PBYTE pdesc;
  350.   pdesc = (PBYTE)((UINT)DOSBUF + (UINT)((pfcb->descpos)<<0x04));
  351.   readsectors(DOSBUF, trsec, 0x01);
  352. //  memcopy(/**from*/(PBYTE)&(pfcb->fn)/**(PBYTE)((UINT)pfcb+1)*/, 16, /**to*/pdesc); //ёюфхЁцшьюх ёЄЁєъЄєЁ√ чртшёшЄ юЄ яюЁ фър срщЄют т ёыютх ш ЁрчьхЁр UINT!!!
  353.   memcopy((PBYTE)&(pfcb->fn), 11, pdesc); //from,len,to
  354.   pdesc = &pdesc[11];
  355.   POKE *(PBYTE)(pdesc) = pfcb->lastlenLSB;
  356.   INC pdesc;
  357.   POKE *(PBYTE)(pdesc) = pfcb->lastlenHSB;
  358.   INC pdesc;
  359.   POKE *(PBYTE)(pdesc) = pfcb->secinblk;
  360.   INC pdesc;
  361.   POKE *(PBYTE)(pdesc) = pfcb->firstsectorLSB;
  362.   INC pdesc;
  363.   POKE *(PBYTE)(pdesc) = pfcb->firstsectorHSB;
  364.   writesectors(DOSBUF, trsec, 0x01);
  365. }
  366.  
  367. /**
  368. flushwritebuf
  369. flushwritebuf.A.=$+1
  370.         ld hl,0
  371. ;write buf
  372.         ld l,FCB.cursector
  373.         push hl ;poi to cursector
  374.         ld e,[hl]
  375.         inc hl
  376.         ld d,[hl]
  377.         ld l,0
  378.         inc h ;poi to buf
  379.         call wrsec.
  380.         ex de,hl ;ld de,(0x5cf4) ;de=next sector
  381.         pop hl ;poi to cursector
  382.         ld [hl],e
  383.         inc hl
  384.         ld [hl],d
  385. ;increase secwritten
  386. ;get new block if this block filled up
  387.         ld l,FCB.secinblk
  388.         ld a,[hl]
  389.         ld l,FCB.secwritten
  390.         inc [hl]
  391.         sub [hl]
  392.         jr nz,flushnblk. ;not filled up
  393. ;block is filled up
  394. ;zero secwritten
  395.         ;ld l,FCB.secwritten
  396.         ld [hl],a;0 ;block not created
  397. ;write descriptor
  398.         ld l,0
  399.         ld (flushdesc.A.),hl
  400.         push hl
  401.         call flushdesc
  402.         pop hl
  403. ;increase block number (after flushdesc!!!)
  404.         ld l,FCB.block
  405.         inc [hl] ;cur block for write, next block for read
  406. ;ЄхяхЁ№ фхёъЁшяЄюЁ эхтрышфэ√щ, яюър эх ёючфрфшь хую т эрўрых фЁєуюую flush
  407. ;zero lastlen (after flushdesc!!!)
  408.         ld l,FCB.lastlen+1 ;(HSB), LSB is already 0 if not fclose
  409.         ld [hl],0
  410. flushnblk.
  411.         ret
  412. */
  413. PROC flushwritebuf(FCB* pfcb)
  414. {
  415. VAR UINT cursector;
  416. //1Ёрч
  417.   cursector = writesectors((PBYTE)((UINT)pfcb+0x100), (UINT)(pfcb->cursectorLSB) + ((UINT)(pfcb->cursectorHSB)<<8), 0x01);
  418.   pfcb->cursectorLSB = (BYTE)cursector;
  419.   pfcb->cursectorHSB = (BYTE)(cursector>>8);
  420.   INC *(&(pfcb->secwritten)); //pfcb->secwritten = pfcb->secwritten + 0x01;
  421.   IF (pfcb->secwritten == pfcb->secinblk) { //block is filled up
  422. //эх яюярыш
  423.     pfcb->secwritten = 0x00;
  424.     flushdesc(pfcb);
  425.     INC *(&(pfcb->block)); //pfcb->block = pfcb->block + 0x01; //cur block for write, next block for read
  426.     //ЄхяхЁ№ фхёъЁшяЄюЁ эхтрышфэ√щ, яюър эх ёючфрфшь хую т эрўрых фЁєуюую flush
  427.     pfcb->lastlenLSB = 0x00;
  428.     pfcb->lastlenHSB = 0x00;
  429.   };
  430. }
  431.  
  432. /**
  433. flush_
  434. flush_.A.=$+1
  435.         ld hl,0 ;hl = poi to FCB
  436. ;if secwritten == 0 then reserve sectors, reserve descriptor
  437.         ld l,FCB.secwritten
  438.         ld a,[hl]
  439.         or a
  440.         jr nz,flushnnew.
  441. ;уы■ўшЄ, хёыш яюёыхфэшщ сыюъ <256
  442. ;яюЄюьє ўЄю fclose тЄюЁющ Ёрч т√ч√трхЄ flush
  443.         ld l,FCB.secinblk
  444.         ld [hl],16 ;TR-DOS reserves 16 sectors per block
  445. ;update sec8
  446.         push hl ;poi to FCB
  447.         ld de,0x0008
  448.         push de
  449.         ld hl,DOSBUF
  450.         call rdsec.
  451.         pop de ;0x0008
  452.         ld hl,[DOSBUF+0xe5] ;free sectors
  453.         ld bc,-16
  454.         add hl,bc
  455.          ;bit 7,h
  456.          ;jr nz,$ ;no free sectors
  457.         ld [DOSBUF+0xe5],hl ;free sectors
  458.  
  459.         ld hl,DOSBUF+0xe4 ;files
  460.         ld a,[hl] ;descriptor position 0..127
  461.          ;or a
  462.          ;jp m,$ ;128 files, can't add
  463.         inc [hl] ;files
  464.  
  465.         ld l,0xe1 ;free sector
  466.         ld c,[hl]
  467.         inc hl
  468.         ld b,[hl]
  469.         inc [hl] ;add 16 sectors = add 1 track
  470.  
  471.         pop hl ;poi to FCB
  472.         ld l,FCB.descpos
  473.         ld [hl],a ;descriptor position 0..127
  474.         ld l,FCB.firstsector
  475.         ld [hl],c
  476.         inc hl
  477.         ld [hl],b
  478.         ld l,FCB.cursector
  479.         ld [hl],c
  480.         inc hl
  481.         ld [hl],b
  482.  
  483.         push hl ;poi to FCB
  484.         ld hl,DOSBUF
  485.         ;ld de,0x0008
  486.         call wrsec. ;write sec8
  487.         pop hl ;poi to FCB
  488. flushnnew.
  489.         ld l,0
  490.         ld (flushwritebuf.A.),hl
  491.         jp flushwritebuf
  492. */
  493. //Ёєўэющ flush яюър эхтючьюцхэ!!!
  494. //can create zero length file
  495. PROC flush_(FCB* pfcb)
  496. {
  497. VAR BYTE firstsectorLSB;
  498. VAR BYTE firstsectorHSB;
  499. VAR UINT freesectors;
  500.   IF (pfcb->secwritten == 0x00) { //reserve sectors, reserve descriptor
  501.     //уы■ўшЄ, хёыш яюёыхфэшщ сыюъ <256
  502.     //яюЄюьє ўЄю fclose тЄюЁющ Ёрч т√ч√трхЄ flush
  503.     pfcb->secinblk = 0x10; //TR-DOS reserves 16 sectors per block
  504.     //update sec8
  505.     readsectors(DOSBUF, 0x0008, 0x01);
  506.     //POKE *(PUINT)(/**(UINT)DOSBUF+0x00e5*/DOSBUFfreesectors) = *(PUINT)(/**(UINT)DOSBUF+0x00e5*/DOSBUFfreesectors) - 16; //free sectors //todo check < 0
  507.     freesectors = ((UINT)*(PBYTE)DOSBUFfreesectorsHSB << 8) + (UINT)*(PBYTE)DOSBUFfreesectorsLSB - 16;
  508. //    freesectors = (UINT)*(PBYTE)DOSBUFfreesectorsLSB + ((UINT)*(PBYTE)DOSbuffreesectorsHSB << 8) - 16; //todo эрщЄш уы■ъ т рёёхьсыхЁх!!! яюўхьє эх эрїюфшЄ ьхЄъє DOSbuffreesectorsHSB???
  509.     POKE *(PBYTE)(DOSBUFfreesectorsLSB) = (BYTE)freesectors;
  510.     POKE *(PBYTE)(DOSBUFfreesectorsHSB) = (BYTE)(freesectors>>8);
  511.     pfcb->descpos = *(PBYTE)(/**(UINT)DOSBUF+0x00e4*/DOSBUFfiles); //descriptor position 0..127
  512.     POKE *(PBYTE)(/**(UINT)DOSBUF+0x00e4*/DOSBUFfiles) = pfcb->descpos + 0x01; //files //todo check >=128
  513.     //*(PUINT)(/**(UINT)DOSBUF+0x00e1*/DOSBUFfreesector); //free sector
  514.     firstsectorLSB = *(PBYTE)DOSBUFfreesectorLSB;
  515.     firstsectorHSB = *(PBYTE)DOSBUFfreesectorHSB;
  516.     pfcb->firstsectorLSB = firstsectorLSB;
  517.     pfcb->firstsectorHSB = firstsectorHSB;
  518.     pfcb->cursectorLSB = firstsectorLSB;
  519.     pfcb->cursectorHSB = firstsectorHSB;
  520.     //POKE *(PUINT)(/**(UINT)DOSBUF+0x00e1*/DOSBUFfreesector) = firstsector + 0x0100; //add 16 sectors = add 1 track
  521.     POKE *(PBYTE)(DOSBUFfreesectorHSB) = firstsectorHSB + 0x01;
  522. //1Ёрч
  523. //goto l1;l1:
  524.     writesectors(DOSBUF, 0x0008, 0x01);
  525. //goto l2;l2:
  526.   };
  527.   flushwritebuf(pfcb);
  528. }
  529.  
  530. /**
  531. comparedesc
  532. comparedesc.A.=$+1 ;filename
  533.         ld hl,0
  534.         ld [findlastslash.A.],hl
  535.         call findlastslash
  536.         ex de,hl
  537. ;de = after last slash
  538. comparedesc.B.=$+1 ;desc
  539.         ld hl,0
  540. ;compare until '.' or '\0' or 8 loops
  541.         ld b,8
  542. comparedesc0.
  543.         ld a,[de] ;filename
  544.         inc de ;todo test '\0', descbuf all spaces
  545.         cp '.'
  546.         jr z,comparedescdot.
  547.         cp [hl] ;descriptor
  548.         jr nz,comparedescfalse.
  549.         inc hl
  550.         djnz comparedesc0.
  551.         ld a,[de] ;filename
  552.         inc de
  553.         cp '.'
  554.         jr z,comparedescdot8. ;filenam8.ext
  555.         ;filenam8 (without ext)
  556.         ld a,[hl]
  557.         cp ' '
  558.         jr nz,comparedescfalse.
  559. comparedesctrue.
  560.         ld a,0xff ;TRUE
  561.         ret
  562. comparedescdot.
  563.         inc hl
  564.         djnz $-1 ;hl = descriptor ext
  565. comparedescdot8.
  566.         ld a,[de] ;filename ext
  567.         cp [hl] ;descriptor ext
  568.         jr z,comparedesctrue.
  569. comparedescfalse.
  570.         xor a ;FALSE
  571.         ret
  572. */
  573. /**
  574. FUNC BOOL comparedesc(PCHAR filename, PBYTE desc)
  575. {
  576. VAR CHAR c;
  577. VAR BOOL res;
  578. VAR BYTE i = 0x08;
  579.   filename = findlastslash(filename);
  580.   loop:
  581.     c = *(PCHAR)filename;
  582.     INC filename;
  583.     IF (c == '.') { //todo test '\0', descbuf all spaces
  584.       dot:
  585.       //desc = (PBYTE)((UINT)desc + (UINT)i);
  586.       res = (*(PCHAR)((UINT)desc + (UINT)i) == *(PCHAR)filename);
  587.       goto quit;
  588.     };
  589.     IF (c != *(PCHAR)desc) {
  590.       res = +FALSE;
  591.       goto quit;
  592.     };
  593.     INC desc;
  594.     DEC i;
  595.     IF (i == 0x00) {
  596.       c = *(PCHAR)filename;
  597.       INC filename;
  598.       //IF (c == '.')
  599.               goto dot;
  600.       //res = (*(PCHAR)desc == ' '); //filenam8 (without ext) //TODO
  601.       //goto quit;
  602.     };
  603.     goto loop;
  604.   quit:
  605. RETURN res;
  606. }
  607. */
  608.  
  609. /**
  610. fread_readnextsector
  611. fread_readnextsector.A.=$+1
  612.         ld hl,0
  613.         ld l,FCB.cursector
  614.         push hl ;poi to cursector
  615.         ld e,[hl]
  616.         inc hl
  617.         ld d,[hl]
  618.         inc h
  619.         ld l,0;a;0 ;poi to buf
  620.         call rdsec.
  621.         ex de,hl ;ld de,[0x5cf4] ;de=next sector
  622.         pop hl ;poi to cursector
  623.         ld [hl],e
  624.         inc hl
  625.         ld [hl],d
  626.         ret
  627. */
  628. /**
  629. PROC fread_readnextsector(FCB* pfcb)
  630. {
  631.   pfcb->cursector = readsectors((PBYTE)((UINT)pfcb+0x100), pfcb->cursector, 0x01);
  632. }
  633. */
  634.  
  635. /**
  636. fread1sec
  637. fread1sec.A.=$+1
  638.         ld hl,0
  639.         ld (fread_readnextsector.A.),hl
  640.         push hl
  641.         call fread_readnextsector
  642.         pop hl
  643. ;if last sector of block, then remain = -lastlen and shift data in buf to the end
  644. ;else remain = 0 (read + 255 bytes)
  645.         xor a
  646.         ld l,FCB.secinblk
  647.         dec [hl] ;sectors remained in block
  648.         jr nz,fread1nlast.
  649. ;last sector in block: shift data to the end of buf
  650.         ld l,FCB.lastlen
  651.         ld c,[hl] ;1..256
  652.         ld b,a;0
  653.         dec c ;0..255
  654.         ld l,c ;end of data
  655.         inc h
  656.         inc bc ;1..256
  657.         ld d,h
  658.         ld e,0xff
  659.         lddr
  660.         ;hl = poi to buf - 1
  661.         ;h = poi to FCB
  662.         ld a,e ;0xfe (1 byte) ... -1 (256 bytes)
  663.         inc a ;remain = 0xff (read + no data) ... 0 (read + 255 bytes)
  664. fread1nlast.
  665.         ld l,FCB.remain
  666.         ld [hl],a
  667.         ret
  668. */
  669. PROC fread1sec(FCB* pfcb)
  670. {
  671. VAR BYTE eod;
  672. VAR UINT cursector;
  673. //1Ёрч
  674.   //fread_readnextsector(pfcb);
  675.   cursector = readsectors((PBYTE)((UINT)pfcb+0x100), (UINT)(pfcb->cursectorLSB) + ((UINT)(pfcb->cursectorHSB)<<8), 0x01);
  676.   pfcb->cursectorLSB = (BYTE)cursector;
  677.   pfcb->cursectorHSB = (BYTE)(cursector>>8);
  678.   //if last sector of block, then remain = -lastlen and shift data in buf to the end
  679.   //else remain = 0 (read + 255 bytes)
  680.   pfcb->remain = 0x00;
  681.   DEC *(&(pfcb->secinblk)); //sectors remained in block
  682.   IF (pfcb->secinblk == 0x00) {
  683.     //last sector in block: shift data to the end of buf
  684.     eod = pfcb->lastlenLSB - 0x01; //1..256 => 0..255
  685.     memcopyback(
  686.       (PBYTE)((UINT)pfcb + 0x0100 + (UINT)eod), //end of data
  687.       (UINT)eod + 1, //1..256
  688.       (PBYTE)((UINT)pfcb + 0x01ff) //end of buf
  689.     );
  690.     pfcb->remain = ~eod; //0xff (read + no data) ... 0 (read + 255 bytes)
  691.   };
  692. }
  693.  
  694. /**
  695. fread1blkq
  696. fread1blkq.A.=$+1 ;FCB
  697.         ld hl,0
  698. fread1blkq.B.=$+1 ;desc
  699.         ld de,0
  700. ;de = poi to descriptor ;+ 10
  701. ;hl = FCB
  702.         ld l,FCB.fn ;+ 10
  703.         ex de,hl
  704. ;hl = poi to descriptor ;+ 10
  705. ;de = poi to filename ;+ 10
  706.         ld bc,16;6 ;padding, len(LSB), len(HSB), secinblk, sec, track
  707.         ldir
  708.         ex de,hl
  709.         ld l,FCB.firstsector
  710.         ld e,[hl]
  711.         inc hl
  712.         ld d,[hl]
  713.         ld l,FCB.cursector
  714.         ld [hl],e
  715.         inc hl
  716.         ld [hl],d
  717. ;secinblk = (lastlen+255)/256 = (lastlen-1)/256 + 1
  718. ;шэрўх эхы№ч  сєфхЄ т√фхы Є№ сыюъш эрт√ЁюёЄ (ъръ фхырхЄ TR-DOS)
  719.         ld l,FCB.lastlen
  720.         ld e,[hl]
  721.         inc hl
  722.         ld d,[hl]
  723.         dec de
  724.         inc d
  725.         inc hl ;ld l,FCB.secinblk
  726.         ld [hl],d
  727.         jr z,fread1qEOF. ;(secinblk == 0)
  728.         ld l,FCB.block
  729.         inc [hl] ;cur block for write, next block for read
  730.         ld a,0xff ;TRUE ;no EOF
  731.         ret
  732. fread1qEOF.
  733.         xor a
  734.         ret
  735. */
  736. FUNC BOOL fread1blkq(FCB* pfcb, PBYTE pdesc1)
  737. {
  738. VAR BOOL res = +FALSE; //EOF
  739.   //memcopy(pdesc1, 16, (PBYTE)&(pfcb->fn)); //from, len, to //ёюфхЁцшьюх ёЄЁєъЄєЁ√ чртшёшЄ юЄ яюЁ фър срщЄют т ёыютх ш ЁрчьхЁр UINT!!!
  740.   memcopy(pdesc1, 11, (PBYTE)&(pfcb->fn)); //from, len, to
  741.   pdesc1 = &pdesc1[11];
  742.   pfcb->lastlenLSB = *(PBYTE)(pdesc1);
  743.   pfcb->lastlenHSB = *(PBYTE)((UINT)pdesc1+1);
  744.   pdesc1 = &pdesc1[2];
  745.   pfcb->secinblk = *(PBYTE)(pdesc1);
  746.   INC pdesc1;
  747.   pfcb->firstsectorLSB = *(PBYTE)(pdesc1);
  748.   pfcb->firstsectorHSB = *(PBYTE)((UINT)pdesc1+1);
  749.   pfcb->cursectorLSB = pfcb->firstsectorLSB;
  750.   pfcb->cursectorHSB = pfcb->firstsectorHSB;
  751.   //secinblk = (lastlen+255)/256 = (lastlen-1)/256 + 1
  752.   //шэрўх эхы№ч  сєфхЄ т√фхы Є№ сыюъш эрт√ЁюёЄ (ъръ фхырхЄ TR-DOS)
  753.   pfcb->secinblk = (BYTE)(((UINT)(pfcb->lastlenLSB) + ((UINT)(pfcb->lastlenHSB)<<8) + 0x00ff) >> 8);
  754.   IF (pfcb->secinblk != 0x00) {
  755.     INC *(&(pfcb->block)); //cur block for write, next block for read
  756.     res = +TRUE; //no EOF
  757.   };
  758. RETURN res;
  759. }
  760.  
  761. /**
  762. readnewbuf
  763. ;read new buf (if exists)
  764. readnewbuf.A.=$+1
  765.         ld hl,0
  766.         ld l,FCB.secinblk
  767.         xor a
  768.         cp [hl] ;sectors remained in block (0 means none)
  769.         jr nz,fread1sec. ;a = 0
  770. ;find new block if exists
  771. ;find Nth block of file with hl pointed filename (10 bytes: name, ext, block N)
  772.         ld b,8 ;sectors
  773. findfile0.
  774.         push bc
  775.         push hl
  776.         ld d,0 ;track
  777.         ld a,8
  778.         sub b
  779.         ld e,a ;sector
  780.         ld hl,DOSBUF
  781.         ld b,1
  782.         call rdsectors.
  783.         pop hl
  784.         pop bc
  785. ;hl=filename
  786. ;b=sectors
  787.         ld de,DOSBUF
  788. findfilecp0.
  789.         ld l,0
  790.         ld (fread1blkq.A.),hl ;FCB
  791.         ld (fread1blkq.B.),de ;desc
  792.         ld l,FCB.fn ;poi to fn
  793.         push bc
  794.         ld bc,0x0a00 ;b=bytes to compare, c=errors
  795. findfilecp00.
  796.         ld a,[de]
  797.         sub [hl]
  798.         or c
  799.         ld c,a ;errors
  800.         inc hl
  801.         inc de
  802.         djnz findfilecp00.
  803.         pop bc
  804.         jr z,fread1blkq. ;ret z ;found (carry = off, a = 0)
  805.         ld a,e
  806.         add a,6
  807.         ld e,a
  808.         jr nz,findfilecp0. ;next descriptor
  809.         djnz findfile0. ;next sector
  810. ;not found
  811.         xor a ;EOF
  812.         ret
  813. fread1blkq.
  814. ;de = poi to descriptor ;+ 10
  815. ;hl = poi to fn ;+ 10
  816.         push hl
  817.         call fread1blkq
  818.         pop hl
  819.         or a ;EOF
  820.         ret z;jr z,fread1EOF.
  821. fread1sec.
  822.         ld l,0
  823.         ld (fread1sec.A.),hl
  824.         call fread1sec
  825.         ld a,0xff ;not EOF
  826.         ret
  827. */
  828. FUNC BOOL readnewbuf(FCB* pfcb)
  829. {
  830. VAR BOOL res = +FALSE; //EOF
  831.   IF (pfcb->secinblk == 0x00) { //sectors remained in block (0 means none)
  832.     IF (!findfile(pfcb, 0x0a)) goto quit; //EOF
  833.     IF (!fread1blkq(pfcb, pdesc)) goto quit; //EOF
  834.   };
  835.   fread1sec(pfcb);
  836.   res = +TRUE; //not EOF
  837. quit:
  838. RETURN res;
  839. }
  840.  
  841. /**
  842. fputs
  843.         EXPORT fputs
  844. ;todo optimize
  845. fputs.A.=$+1
  846.         EXPORT fputs.A.
  847.         ld bc,0 ;poi to string
  848.         jp fputsgo.
  849. fputs0.
  850. fputs.B.=$+1
  851.         EXPORT fputs.B.
  852.         ld hl,0 ;poi to FCB
  853.         call fwrite1. ;a=data
  854.         inc bc
  855. fputsgo.
  856.         ld a,[bc]
  857.         or a
  858.         jp nz,fputs0.
  859.         ret ;end of string ;(TODO hl = non-negative value)
  860. */
  861. EXPORT FUNC INT fputs(PCHAR s, PBYTE file)
  862. {
  863. VAR CHAR c;
  864. loop:
  865.   c = *(PCHAR)s;
  866.   IF (c == '\0') goto quit;
  867.   fwrite((PBYTE)&c, 1, 1, file);
  868.   INC s;
  869.   goto loop;
  870. quit:
  871. RETURN +1; //OK
  872. }
  873.  
  874. /**
  875. closewrite
  876.         EXPORT closewrite
  877. fclose
  878.         EXPORT fclose
  879. closewrite.A.=$+1
  880.         EXPORT closewrite.A.
  881. fclose.A.=$+1
  882.         EXPORT fclose.A.
  883.         ld hl,0 ;poi to FCB
  884.         ld a,[hl]
  885.         ld [hl],l;0
  886.         cp 'w'
  887.         ret nz ;hl!=0
  888. ;hl = poi to FCB
  889.         push hl
  890.         ld (flush_.A.),hl
  891.         call flush_
  892.         pop hl
  893.         ;ёыхфє■∙р  яЁютхЁър эх уюфшЄё , хёыш сєфхЄ Ёєўэющ flush:
  894.         ld l,FCB.secwritten
  895.         ld a,[hl]
  896.         or a
  897.         ret z ;no sectors written - descriptor already saved
  898.         ld l,0
  899.         ld (flushdesc.A.),hl
  900.         call flushdesc
  901.         ;ld l,1 ;OK TODO
  902.         ret ;hl!=0
  903. */
  904. EXPORT FUNC INT fclose(PBYTE file)
  905. {
  906. VAR FCB* pfcb = (FCB*)file;
  907. VAR CHAR mode = pfcb->mode;
  908.   pfcb->mode = '\0';
  909.   IF (mode == 'w') {
  910.     flush_(pfcb);
  911.     IF (pfcb->secwritten != 0x00) {
  912.       flushdesc(pfcb);
  913.     };
  914.   };
  915. RETURN +1; //OK
  916. }
  917. /**
  918. EXPORT PROC closewrite(PBYTE file)
  919. {
  920.   fclose(file);
  921. }
  922. */
  923. CONST PBYTE mas[2]={closewrite,fclose}
  924. VAR PBYTE ad
  925. VAR BYTE i
  926. call (mas[i]);
  927. call (ad);
  928.  
  929. VAR UINT u;
  930. u = ~(u+4);
  931. i = i-0x05;
  932.