Rev 53 | Blame | Compare with Previous | Last modification | View Log | Download
_finEXPORT _finDW 0_foutEXPORT _foutDW 0_waseofEXPORT _waseofDB 0FCB=0;db 0 ;0 = free, 'r' = read, 'w' = writeFCB=FCB+1;;;;;;;;;;;;;;; copy of TR-DOS descriptor ;;;;;;;;;;;;;;FCB.fn=FCB;db "12345678c" ;filenameFCB=FCB+9FCB.block=FCB;db 0 ;cur block for write, next block for read;db 0x60 ;(padding for "start")FCB=FCB+2FCB.lastlen=FCB;dw 0 ;length of blockFCB=FCB+2FCB.secinblk=FCB;db 0 ;sectors remained in block (for read), block size (for write)FCB=FCB+1FCB.firstsector=FCB;dw 0 ;first sector of block (for write)FCB=FCB+2;;;;;;;;;;;;;;; end of TR-DOS descriptor ;;;;;;;;;;;;;;FCB.cursector=FCB;dw 0 ;cur sector for write, next sector for readFCB=FCB+2FCB.remain=FCB;db 0xff ;remaining bytes in buf (for read)FCB=FCB+1FCB.secwritten=FCB;db 0 ;sectors written (for write)FCB=FCB+1FCB.descpos=FCB;db 0 ;position of descriptor (for write) 0..127FCB=FCB+1FCB.buf=256;$-FCB;ds 256 ;buffer for last sector;FCB1.=0x4800 ;aligned;FCB2.=0x4a00 ;aligned;FCB3.=0x4c00 ;aligned;FCB4.=0x4e00 ;aligned;FCB5.=0x5000 ;aligned;DOSBUF=0xff00 ;aligned;hl = poi to filename in stringfindlastslash.nfopenfnslash.ld d,hld e,l ;de = after last slash;find last slashnfopenfnslash0.ld a,[hl]inc hlor ajr z,nfopenfnslashq.cp '/'jr nz,nfopenfnslash0.jr nfopenfnslash.nfopenfnslashq.;de = after last slashrettopenwr.db "wb"db 0openwriteEXPORT openwriteld hl,topenwr.ld [nfopen.B.],hlopenwrite.A.=$+1EXPORT openwrite.A.ld hl,0 ;filenameld [nfopen.A.],hlnfopenEXPORT nfopenxor ald hl,FCB1-0x0200inc hinc hcp [hl]jr nz,$-3;nfopenFCBnfopen.B.=$+1EXPORT nfopen.B.ld a,[0] ;poi to mode ("wb"/"rb")ld [hl],a ;mode in FCBinc hl ;poi to fn in FCBpush hl ;poi to fn in FCBld d,hld e,linc deld [hl],' 'ld bc,8ldir ;empty filenamenfopen.A.=$+1EXPORT nfopen.A.ld hl,0 ;poi to filename in stringcall findlastslash.;de = after last slashpop hl ;poi to fn in FCBld b,9nfopenfn0.ld a,[de]or ajr z,nfopenfnq. ;no extension in stringinc decp '.'jr z,nfopenfndot.ld [hl],ainc hldjnz nfopenfn0.;9 bytes in filename, no dot (9th byte goes to extension)jr nfopenfnq.nfopenfndot.inc hldjnz $-1 ;hl points to extension in FCBdec hlld a,[de] ;extension in stringld [hl],a ;extension in FCBnfopenfnq.xor ald l,FCB.blockld [hl],a;0 ;cur block (for write!)inc hlld [hl],0x60 ;(padding for "start")ld l,a;0ld a,(hl)cp 'w'jr z,nfopen_nofindfile. ;TODO єфрышЄ№, хёыш хёЄ№;яЁютхЁшЄ№, ўЄю Їрщы ёє∙хёЄтєхЄ, шэрўх тхЁэєЄ№ ю°шсъє ш юётюсюфшЄ№ FCBld c,9 ;FILENAMESZcall findfileor ajr nz,nfopen_fail.;hl,de = after filename;open for read!ld l,FCB.blockld a,(de)inc deld [hl],a;0 ;cur block for write, next block for readinc hlld a,(de)inc deld [hl],a;0x60 ;(padding for "start");ld a,FALSE;ld [_waseof],anfopen_nofindfile.xor a;ld l,FCB.block;ld [hl],a;0 ;cur block for write, next block for read;inc hl;ld [hl],0x60 ;(padding for "start");inc hlld l,FCB.lastlenld [hl],a;0 ;lastlen LSB ;???inc hlld [hl],a;0 ;lastlen HSB ;???inc hlld [hl],a;0 ;sectors remained in block (for read), block size (for write)ld l,FCB.remainld [hl],0xff ;remain (0xff = no data) for readinc hlld [hl],a;0 ;sectors written (for write)ld l,a;0;FCB.moderet ;hl = poi to FCBnfopen_fail.ld l,0ld (hl),l;0 ;empty FCBld h,l ;hl=0retclosewriteEXPORT closewritefcloseEXPORT fcloseclosewrite.A.=$+1EXPORT closewrite.A.fclose.A.=$+1EXPORT fclose.A.ld hl,0 ;poi to FCBld a,[hl]ld [hl],l;0cp 'w'ret nz ;hl!=0;hl = poi to FCBcall flush.;ёыхфє■∙р яЁютхЁър эх уюфшЄё , хёыш сєфхЄ Ёєўэющ flush:ld l,FCB.secwrittenld a,[hl]or aret z ;no sectors written - descriptor already saved;call flushdesc.;ld l,1 ;OK TODO;ret ;hl!=0;write descriptor;if created or finishedflushdesc.;hl = poi to FCBpush hl ;poi to FCBpush hl ;poi to FCBld l,FCB.descposld l,[hl]ld d,0 ;track of descriptorld h,d;0add hl,hladd hl,hladd hl,hladd hl,hlld e,h ;sector of descriptorld h,DOSBUF>>8push hl ;hl = poi to descriptorpush de ;track,sector of descriptorcall rdsecDOSBUFpop bc ;track,sector of descriptorpop de ;poi to descriptorpop hl ;poi to FCBld l,FCB.fnpush bc ;track,sector of descriptorld bc,16ldirpop de ;track,sector of descriptor;ld hl,DOSBUFcall wrsecDOSBUFpop hl ;poi to FCBret;FUNC LONG getfiletime FORWARD(PCHAR filename);getfiletimeEXPORT getfiletimegetfiletime.A.=$+1EXPORT getfiletime.A.ld de,0ld c,9 ;c=FILENAMESZcall findfile;carry = off, a = 0, de = DOSBUF after filename, b = 8-sectorld a,eand 0xf0ld e,ald a,8sub bld d,ald hl,0;out: hlde=datetimeretfindfile;find new block if exists;find Nth block of file with hl pointed filename (10 bytes: name, ext, block N);c=FILENAMESZld b,8 ;sectorsfindfile0.push bcpush hlld d,0 ;trackld a,8sub bld e,a ;sectorcall rdsecDOSBUFpop hlpop bc;hl=filename;b=sectorsld de,DOSBUFfindfilecp0.ld l,FCB.fn ;poi to fnpush bcld b,c ;FILENAMESZld c,0 ;b=bytes to compare, c=errorsfindfilecp00.ld a,[de]sub [hl]or cld c,a ;errorsinc hlinc dedjnz findfilecp00.pop bcret z ;found (carry = off, a = 0, hl,de = after filename)ld a,eor 15;add a,16-FILENAMESZ;6ld e,ainc ejr nz,findfilecp0. ;next descriptordjnz findfile0. ;next sector;not foundld a,0xff ;failret;length 0 while reading means either absence of files of zero length file (any sector length)readfEXPORT readfreadf.A.=$+1EXPORT readf.A.ld hl,0 ;poi to FCBjr fread1. ;a=data ;keeps bcreadfinEXPORT readfinld hl,[_fin] ;poi to FCBfread1.;a=data;;if ok then inc de?;keeps bcld l,FCB.remain ;0xff = no data, 0xfe = 1 byte, ... 0x00 = 255 bytesld e,[hl]ld d,hinc dinc eld a,[de]ld [hl],e ;inc [hl] ;remainret nzpush bc;push de;read new buf (if exists)ld l,FCB.secinblkxor acp [hl] ;sectors remained in block (0 means none)jr nz,fread1sec. ;a = 0ld c,10 ;FILENAMESZcall findfilejr z,fread1blkq. ;found (carry = off, a = 0, hl,de = after filename);not found;EOF - next block doesn't existfread1EOF.;pop depop bcld a,TRUEld [_waseof],ald a,'\n' ;EOF returns '\n';set vars as they were (next time EOF again)ld l,FCB.remaindec [hl] ;remain = 0xffretfread1blkq.;de = poi to descriptor + 10;hl = poi to fn + 10;a = 0;ld l,FCB.fn + 10ex de,hl;hl = poi to descriptor + 10;de = poi to filename + 10ld bc,16-10 ;padding, len(LSB), len(HSB), secinblk, sec, trackldirex de,hlld l,FCB.firstsectorld e,[hl]inc hlld d,[hl]ld l,FCB.cursectorld [hl],einc hlld [hl],d;secinblk = (lastlen+255)/256 = (lastlen-1)/256 + 1;шэрўх эхы№ч сєфхЄ т√фхы Є№ сыюъш эрт√ЁюёЄ (ъръ фхырхЄ TR-DOS)ld l,FCB.lastlenld e,[hl]inc hlld d,[hl]dec deinc d ;only for 16 sectors in block!inc hl ;ld l,FCB.secinblkld [hl],djr z,fread1EOF. ;(secinblk == 0)ld l,FCB.blockinc [hl] ;cur block for write, next block for readfread1sec.;read next sector;a = 0ld l,FCB.cursectorpush hl ;poi to cursectorld e,[hl]inc hlld d,[hl]inc hld l,a;0 ;poi to bufcall rdsec.ex de,hl ;ld de,[0x5cf4] ;de=next sectorpop hl ;poi to cursectorld [hl],einc hlld [hl],d;if last sector of block, then remain = -lastlen and shift data in buf to the end;else remain = 0 (read + 255 bytes)xor ald l,FCB.secinblkdec [hl] ;sectors remained in blockjr nz,fread1nlast.;last sector in block: shift data to the end of bufld l,FCB.lastlenld c,[hl] ;1..256ld b,a;0dec c ;0..255ld l,c ;end of datainc hinc bc ;1..256ld d,hld e,0xfflddr;hl = poi to buf - 1;h = poi to FCBld a,e ;0xfe (1 byte) ... -1 (256 bytes)inc a ;remain = 0xff (read + no data) ... 0 (read + 255 bytes)fread1nlast.ld l,FCB.remainld [hl],a;pop depop bcfread1ok.;hl = poi to remainld l,[hl]inc hld a,[hl];inc deretfreadEXPORT freadfread.A.=$+1EXPORT fread.A.ld hl,0 ;poi to data;ld de,0 ;total processed bytesfread.C.=$+1EXPORT fread.C.ld bc,0 ;countfread0.push bcfread.B.=$+1EXPORT fread.B.ld bc,0 ;sizefread00.push hlfread.D.=$+1EXPORT fread.D.ld hl,0 ;poi to FCBcall fread1. ;a=data ;keeps bcpop hlld [hl],ald a,[_waseof]or a ;FALSEjr nz,freadpopret.;cpidb 0xed,0xa1jp pe,fread00.pop bcdec hl;cpidb 0xed,0xa1jp pe,fread0.;ex de,hl ;hl = total processed bytesretfreadpopret.pop bcretwritebyteEXPORT writebytewritebyte.A.=$+1EXPORT writebyte.A.ld hl,0 ;filewritebyte.B.=$+1EXPORT writebyte.B.ld a,0jp fwrite1.writefoutEXPORT writefoutld hl,[_fout]writefout.A.=$+1EXPORT writefout.A.ld a,0;hl = poi to FCB;a=data;keeps bcfwrite1.ld l,FCB.lastlenld e,[hl]ld d,hinc dld [de],ainc [hl] ;lastlen (LSB);Z = end of bufret nzinc linc [hl] ;lastlen (HSB)flush.;Ёєўэющ flush яюър эхтючьюцхэ!!!;can create zero length file;hl = poi to FCBpush bc;if secwritten == 0 then reserve sectors, reserve descriptorld l,FCB.secwrittenld a,[hl]or ajr nz,flushnnew.;уы■ўшЄ, хёыш яюёыхфэшщ сыюъ <256;яюЄюьє ўЄю fclose тЄюЁющ Ёрч т√ч√трхЄ flushld l,FCB.secinblkld [hl],16 ;TR-DOS reserves 16 sectors per block;update sec8push hl ;poi to FCBld de,0x0008push decall rdsecDOSBUFpop de ;0x0008ld hl,[DOSBUF+0xe5] ;free sectorsld bc,-16add hl,bc;bit 7,h;jr nz,$ ;no free sectorsld [DOSBUF+0xe5],hl ;free sectorsld hl,DOSBUF+0xe4 ;filesld a,[hl] ;descriptor position 0..127;or a;jp m,$ ;128 files, can't addinc [hl] ;filesld l,0xe1 ;free sectorld c,[hl]inc hlld b,[hl]inc [hl] ;add 16 sectors = add 1 trackpop hl ;poi to FCBld l,FCB.descposld [hl],a ;descriptor position 0..127ld l,FCB.firstsectorld [hl],cinc hlld [hl],bld l,FCB.cursectorld [hl],cinc hlld [hl],bpush hl ;poi to FCB;ld de,0x0008;ld hl,DOSBUFcall wrsecDOSBUF ;write sec8pop hl ;poi to FCBflushnnew.;write bufld l,FCB.cursectorpush hl ;poi to cursectorld e,[hl]inc hlld d,[hl]ld l,0inc h ;poi to bufcall wrsec.ex de,hl ;ld de,(0x5cf4) ;de=next sectorpop hl ;poi to cursectorld [hl],einc hlld [hl],d;increase secwritten;get new block if this block filled upld l,FCB.secinblkld a,[hl]ld l,FCB.secwritteninc [hl]sub [hl]jr nz,flushnblk. ;not filled up;block is filled up;zero secwritten;ld l,FCB.secwrittenld [hl],a;0 ;block not created;write descriptorcall flushdesc.;increase block number (after flushdesc!!!)ld l,FCB.blockinc [hl] ;cur block for write, next block for read;ЄхяхЁ№ фхёъЁшяЄюЁ эхтрышфэ√щ, яюър эх ёючфрфшь хую т эрўрых фЁєуюую flush;zero lastlen (after flushdesc!!!)ld l,FCB.lastlen+1 ;(HSB), LSB is already 0 if not fcloseld [hl],0flushnblk.pop bcretfwriteEXPORT fwritefwrite.A.=$+1EXPORT fwrite.A.ld hl,0 ;poi to data;ld de,0 ;total processed bytes TODOfwrite.C.=$+1EXPORT fwrite.C.ld bc,0 ;countfwrite0.push bcfwrite.B.=$+1EXPORT fwrite.B.ld bc,0 ;sizefwrite00.ld a,[hl]push hl;push defwrite.D.=$+1ld hl,0 ;poi to FCBcall fwrite1. ;a=data ;keeps bc;pop de;inc depop hl;cpidb 0xed,0xa1jp pe,fwrite00.pop bcdec hl;cpidb 0xed,0xa1jp pe,fwrite0.;ex de,hl ;hl = total processed bytesretfputsEXPORT fputs;todo optimizefputs.A.=$+1EXPORT fputs.A.ld bc,0 ;poi to stringjp fputsgo.fputs0.fputs.B.=$+1EXPORT fputs.B.ld hl,0 ;poi to FCBcall fwrite1. ;a=datainc bcfputsgo.ld a,[bc]or ajp nz,fputs0.ret ;end of string ;(TODO hl = non-negative value)loadfileloadfile.A.=$+1 ;filenameld hl,0ld [nfopen.A.],hlld hl,loadfile.mode.ld [nfopen.B.],hlcall nfopenld a,hor lret zld [fclose.A.],hl ;FCBld [fread.D.],hl ;FCBloadfile.B.=$+1 ;addrld hl,0ld [fread.A.],hl ;addrld hl,1ld [fread.B.],hl ;sizeld hl,0xffffld [fread.C.],hl ;countld a,FALSEld [_waseof],acall freadpush hlcall fclosepop hlretloadfile.mode.db "rb"db 0;FUNC UINT readsectors FORWARD(PBYTE buf, UINT trsec, BYTE count);readsectorsreadsectors.A.=$+1 ;bufld hl,0readsectors.B.=$+1 ;trsecld de,0readsectors.C.=$+1 ;countld b,0jr rdsectors.rdsecDOSBUFld hl,DOSBUFrdsec.ld b,1rdsectors.ld c,0x05dos3d13.call 0x3d13ld hl,[0x5cf4] ;return hl=next sectorret;FUNC UINT writesectors FORWARD(PBYTE buf, UINT trsec, BYTE count);writesectorswritesectors.A.=$+1 ;bufld hl,0writesectors.B.=$+1 ;trsecld de,0writesectors.C.=$+1 ;countld b,0jr wrsectors.wrsecDOSBUFld hl,DOSBUFwrsec.ld b,1wrsectors.ld c,0x06jr dos3d13.