Login

Subversion Repositories NedoOS

Rev

Rev 53 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

_fin
        EXPORT _fin
        DW 0
_fout
        EXPORT _fout
        DW 0
_waseof
        EXPORT _waseof
        DB 0

FCB=0
        ;db 0 ;0 = free, 'r' = read, 'w' = write
FCB=FCB+1
;;;;;;;;;;;;;;; copy of TR-DOS descriptor ;;;;;;;;;;;;;;
FCB.fn=FCB
        ;db "12345678c" ;filename
FCB=FCB+9
FCB.block=FCB
        ;db 0 ;cur block for write, next block for read
        ;db 0x60 ;(padding for "start")
FCB=FCB+2
FCB.lastlen=FCB
        ;dw 0 ;length of block
FCB=FCB+2
FCB.secinblk=FCB
        ;db 0 ;sectors remained in block (for read), block size (for write)
FCB=FCB+1
FCB.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 read
FCB=FCB+2
FCB.remain=FCB
        ;db 0xff ;remaining bytes in buf (for read)
FCB=FCB+1
FCB.secwritten=FCB
        ;db 0 ;sectors written (for write)
FCB=FCB+1
FCB.descpos=FCB
        ;db 0 ;position of descriptor (for write) 0..127
FCB=FCB+1
FCB.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 string
findlastslash.
nfopenfnslash.
        ld d,h
        ld e,l ;de = after last slash
;find last slash
nfopenfnslash0.
        ld a,[hl]
        inc hl
        or a
        jr z,nfopenfnslashq.
        cp '/'
        jr nz,nfopenfnslash0.
        jr nfopenfnslash.
nfopenfnslashq.
;de = after last slash
        ret

topenwr.
        db "wb"
        db 0

openwrite
        EXPORT openwrite
        ld hl,topenwr.
        ld [nfopen.B.],hl
openwrite.A.=$+1
        EXPORT openwrite.A.
        ld hl,0 ;filename
        ld [nfopen.A.],hl
nfopen
        EXPORT nfopen
        xor a
        ld hl,FCB1-0x0200

        inc h
        inc h
        cp [hl]
        jr nz,$-3

;nfopenFCB
nfopen.B.=$+1
        EXPORT nfopen.B.
        ld a,[0] ;poi to mode ("wb"/"rb")
        ld [hl],a ;mode in FCB
        inc hl ;poi to fn in FCB
        push hl ;poi to fn in FCB
        ld d,h
        ld e,l
        inc de
        ld [hl],' '
        ld bc,8
        ldir ;empty filename
nfopen.A.=$+1
        EXPORT nfopen.A.
        ld hl,0 ;poi to filename in string
        call findlastslash.
;de = after last slash
        pop hl ;poi to fn in FCB
        ld b,9
nfopenfn0.
        ld a,[de]
        or a
        jr z,nfopenfnq. ;no extension in string
        inc de
        cp '.'
        jr z,nfopenfndot.
        ld [hl],a
        inc hl
        djnz nfopenfn0.
;9 bytes in filename, no dot (9th byte goes to extension)
        jr nfopenfnq.
nfopenfndot.
        inc hl
        djnz $-1 ;hl points to extension in FCB
        dec hl
        ld a,[de] ;extension in string
        ld [hl],a ;extension in FCB
nfopenfnq.

        xor a
        ld l,FCB.block
        ld [hl],a;0 ;cur block (for write!)
        inc hl
        ld [hl],0x60 ;(padding for "start")

        ld l,a;0
        ld a,(hl)
        cp 'w'
        jr z,nfopen_nofindfile. ;TODO єфрышЄ№, хёыш хёЄ№
;яЁютхЁшЄ№, ўЄю Їрщы ёє∙хёЄтєхЄ, шэрўх тхЁэєЄ№ ю°шсъє ш юётюсюфшЄ№ FCB
        ld c,9 ;FILENAMESZ
        call findfile
        or a
        jr nz,nfopen_fail.
;hl,de = after filename
;open for read!
        ld l,FCB.block
        ld a,(de)
        inc de
        ld [hl],a;0 ;cur block for write, next block for read
        inc hl
        ld a,(de)
        inc de
        ld [hl],a;0x60 ;(padding for "start")
       ;ld a,FALSE
       ;ld [_waseof],a
nfopen_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 hl
        ld l,FCB.lastlen
        ld [hl],a;0 ;lastlen LSB ;???
        inc hl
        ld [hl],a;0 ;lastlen HSB ;???
        inc hl
        ld [hl],a;0 ;sectors remained in block (for read), block size (for write)
        ld l,FCB.remain
        ld [hl],0xff ;remain (0xff = no data) for read
        inc hl
        ld [hl],a;0 ;sectors written (for write)
        ld l,a;0;FCB.mode
        ret ;hl = poi to FCB

nfopen_fail.
        ld l,0
        ld (hl),l;0 ;empty FCB
        ld h,l ;hl=0
        ret

closewrite
        EXPORT closewrite
fclose
        EXPORT fclose
closewrite.A.=$+1
        EXPORT closewrite.A.
fclose.A.=$+1
        EXPORT fclose.A.
        ld hl,0 ;poi to FCB
        ld a,[hl]
        ld [hl],l;0
        cp 'w'
        ret nz ;hl!=0
;hl = poi to FCB
        call flush.
        ;ёыхфє■∙р  яЁютхЁър эх уюфшЄё , хёыш сєфхЄ Ёєўэющ flush:
        ld l,FCB.secwritten
        ld a,[hl]
        or a
        ret z ;no sectors written - descriptor already saved
        ;call flushdesc.
        ;ld l,1 ;OK TODO
        ;ret ;hl!=0
;write descriptor
;if created or finished
flushdesc.
;hl = poi to FCB
        push hl ;poi to FCB

        push hl ;poi to FCB
        ld l,FCB.descpos
        ld l,[hl]
        ld d,0 ;track of descriptor
        ld h,d;0
        add hl,hl
        add hl,hl
        add hl,hl
        add hl,hl
        ld e,h ;sector of descriptor
        ld h,DOSBUF>>8
        push hl ;hl = poi to descriptor
        push de ;track,sector of descriptor
        call rdsecDOSBUF
        pop bc ;track,sector of descriptor
        pop de ;poi to descriptor
        pop hl ;poi to FCB
        ld l,FCB.fn
        push bc ;track,sector of descriptor
        ld bc,16
        ldir
        pop de ;track,sector of descriptor
        ;ld hl,DOSBUF
        call wrsecDOSBUF

        pop hl ;poi to FCB
        ret

;FUNC LONG getfiletime FORWARD(PCHAR filename);
getfiletime
        EXPORT getfiletime
getfiletime.A.=$+1
        EXPORT getfiletime.A.
        ld de,0
        ld c,9 ;c=FILENAMESZ
        call findfile
;carry = off, a = 0, de = DOSBUF after filename, b = 8-sector
        ld a,e
       and 0xf0
        ld e,a
        ld a,8
        sub b
        ld d,a
        ld hl,0
;out: hlde=datetime
        ret

findfile
;find new block if exists
;find Nth block of file with hl pointed filename (10 bytes: name, ext, block N)
;c=FILENAMESZ
        ld b,8 ;sectors
findfile0.
        push bc
        push hl
        ld d,0 ;track
        ld a,8
        sub b
        ld e,a ;sector
        call rdsecDOSBUF
        pop hl
        pop bc
;hl=filename
;b=sectors
        ld de,DOSBUF
findfilecp0.
        ld l,FCB.fn ;poi to fn
        push bc
        ld b,c ;FILENAMESZ
        ld c,0 ;b=bytes to compare, c=errors
findfilecp00.
        ld a,[de]
        sub [hl]
        or c
        ld c,a ;errors
        inc hl
        inc de
        djnz findfilecp00.
        pop bc
        ret z ;found (carry = off, a = 0, hl,de = after filename)
        ld a,e
        or 15;add a,16-FILENAMESZ;6
        ld e,a
        inc e
        jr nz,findfilecp0. ;next descriptor
        djnz findfile0. ;next sector
;not found
        ld a,0xff ;fail
        ret

;length 0 while reading means either absence of files of zero length file (any sector length)

readf
        EXPORT readf
readf.A.=$+1
        EXPORT readf.A.
        ld hl,0 ;poi to FCB
        jr fread1. ;a=data ;keeps bc
readfin
        EXPORT readfin
        ld hl,[_fin] ;poi to FCB
fread1.
;a=data
 ;;if ok then inc de?
;keeps bc
        ld l,FCB.remain ;0xff = no data, 0xfe = 1 byte, ... 0x00 = 255 bytes
        ld e,[hl]
        ld d,h
        inc d
        inc e
        ld a,[de]
        ld [hl],e ;inc [hl] ;remain
        ret nz

        push bc
         ;push de
;read new buf (if exists)
        ld l,FCB.secinblk
        xor a
        cp [hl] ;sectors remained in block (0 means none)
        jr nz,fread1sec. ;a = 0
        ld c,10 ;FILENAMESZ
        call findfile
        jr z,fread1blkq. ;found (carry = off, a = 0, hl,de = after filename)
;not found
;EOF - next block doesn't exist
fread1EOF.
         ;pop de
        pop bc
       ld a,TRUE
       ld [_waseof],a
       ld a,'\n' ;EOF returns '\n'
;set vars as they were (next time EOF again)
        ld l,FCB.remain
        dec [hl] ;remain = 0xff
        ret
fread1blkq.
;de = poi to descriptor + 10
;hl = poi to fn + 10
;a = 0
        ;ld l,FCB.fn + 10
        ex de,hl
;hl = poi to descriptor + 10
;de = poi to filename + 10
        ld bc,16-10 ;padding, len(LSB), len(HSB), secinblk, sec, track
        ldir
        ex de,hl
        ld l,FCB.firstsector
        ld e,[hl]
        inc hl
        ld d,[hl]
        ld l,FCB.cursector
        ld [hl],e
        inc hl
        ld [hl],d
;secinblk = (lastlen+255)/256 = (lastlen-1)/256 + 1
;шэрўх эхы№ч  сєфхЄ т√фхы Є№ сыюъш эрт√ЁюёЄ (ъръ фхырхЄ TR-DOS)
        ld l,FCB.lastlen
        ld e,[hl]
        inc hl
        ld d,[hl]
        dec de
        inc d ;only for 16 sectors in block!
        inc hl ;ld l,FCB.secinblk
        ld [hl],d
        jr z,fread1EOF. ;(secinblk == 0)
        ld l,FCB.block
        inc [hl] ;cur block for write, next block for read
fread1sec.
;read next sector
;a = 0
        ld l,FCB.cursector
        push hl ;poi to cursector
        ld e,[hl]
        inc hl
        ld d,[hl]
        inc h
        ld l,a;0 ;poi to buf
        call rdsec.
        ex de,hl ;ld de,[0x5cf4] ;de=next sector
        pop hl ;poi to cursector
        ld [hl],e
        inc hl
        ld [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 a
        ld l,FCB.secinblk
        dec [hl] ;sectors remained in block
        jr nz,fread1nlast.
;last sector in block: shift data to the end of buf
        ld l,FCB.lastlen
        ld c,[hl] ;1..256
        ld b,a;0
        dec c ;0..255
        ld l,c ;end of data
        inc h
        inc bc ;1..256
        ld d,h
        ld e,0xff
        lddr
        ;hl = poi to buf - 1
        ;h = poi to FCB
        ld a,e ;0xfe (1 byte) ... -1 (256 bytes)
        inc a ;remain = 0xff (read + no data) ... 0 (read + 255 bytes)
fread1nlast.
        ld l,FCB.remain
        ld [hl],a
         ;pop de
        pop bc
fread1ok.
;hl = poi to remain
        ld l,[hl]
        inc h
        ld a,[hl]
         ;inc de
        ret

fread
        EXPORT fread
fread.A.=$+1
        EXPORT fread.A.
        ld hl,0 ;poi to data
         ;ld de,0 ;total processed bytes
fread.C.=$+1
        EXPORT fread.C.
        ld bc,0 ;count
fread0.
        push bc
fread.B.=$+1
        EXPORT fread.B.
        ld bc,0 ;size
fread00.
        push hl
fread.D.=$+1
        EXPORT fread.D.
        ld hl,0 ;poi to FCB
        call fread1. ;a=data ;keeps bc
        pop hl
        ld [hl],a
       ld a,[_waseof]
       or a ;FALSE
       jr nz,freadpopret.
        ;cpi
        db 0xed,0xa1
        jp pe,fread00.
        pop bc
        dec hl
        ;cpi
        db 0xed,0xa1
        jp pe,fread0.
         ;ex de,hl ;hl = total processed bytes
        ret
freadpopret.
        pop bc
        ret

writebyte
        EXPORT writebyte
writebyte.A.=$+1
        EXPORT writebyte.A.
        ld hl,0 ;file
writebyte.B.=$+1
        EXPORT writebyte.B.
        ld a,0
        jp fwrite1.
writefout
        EXPORT writefout
        ld hl,[_fout]
writefout.A.=$+1
        EXPORT writefout.A.
        ld a,0
;hl = poi to FCB
;a=data
;keeps bc
fwrite1.
        ld l,FCB.lastlen
        ld e,[hl]
        ld d,h
        inc d
        ld [de],a
        inc [hl] ;lastlen (LSB)
        ;Z = end of buf
        ret nz
        inc l
        inc [hl] ;lastlen (HSB)
flush.
;Ёєўэющ flush яюър эхтючьюцхэ!!!
;can create zero length file
;hl = poi to FCB
        push bc

;if secwritten == 0 then reserve sectors, reserve descriptor
        ld l,FCB.secwritten
        ld a,[hl]
        or a
        jr nz,flushnnew.
;уы■ўшЄ, хёыш яюёыхфэшщ сыюъ <256
;яюЄюьє ўЄю fclose тЄюЁющ Ёрч т√ч√трхЄ flush
        ld l,FCB.secinblk
        ld [hl],16 ;TR-DOS reserves 16 sectors per block
;update sec8
        push hl ;poi to FCB
        ld de,0x0008
        push de
        call rdsecDOSBUF
        pop de ;0x0008
        ld hl,[DOSBUF+0xe5] ;free sectors
        ld bc,-16
        add hl,bc
         ;bit 7,h
         ;jr nz,$ ;no free sectors
        ld [DOSBUF+0xe5],hl ;free sectors

        ld hl,DOSBUF+0xe4 ;files
        ld a,[hl] ;descriptor position 0..127
         ;or a
         ;jp m,$ ;128 files, can't add
        inc [hl] ;files

        ld l,0xe1 ;free sector
        ld c,[hl]
        inc hl
        ld b,[hl]
        inc [hl] ;add 16 sectors = add 1 track

        pop hl ;poi to FCB
        ld l,FCB.descpos
        ld [hl],a ;descriptor position 0..127
        ld l,FCB.firstsector
        ld [hl],c
        inc hl
        ld [hl],b
        ld l,FCB.cursector
        ld [hl],c
        inc hl
        ld [hl],b

        push hl ;poi to FCB
        ;ld de,0x0008
        ;ld hl,DOSBUF
        call wrsecDOSBUF ;write sec8
        pop hl ;poi to FCB
flushnnew.

;write buf
        ld l,FCB.cursector
        push hl ;poi to cursector
        ld e,[hl]
        inc hl
        ld d,[hl]
        ld l,0
        inc h ;poi to buf
        call wrsec.
        ex de,hl ;ld de,(0x5cf4) ;de=next sector
        pop hl ;poi to cursector
        ld [hl],e
        inc hl
        ld [hl],d

;increase secwritten
;get new block if this block filled up
        ld l,FCB.secinblk
        ld a,[hl]
        ld l,FCB.secwritten
        inc [hl]
        sub [hl]
        jr nz,flushnblk. ;not filled up
;block is filled up
;zero secwritten
        ;ld l,FCB.secwritten
        ld [hl],a;0 ;block not created
;write descriptor
        call flushdesc.
;increase block number (after flushdesc!!!)
        ld l,FCB.block
        inc [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 fclose
        ld [hl],0
flushnblk.

        pop bc
        ret

fwrite
        EXPORT fwrite
fwrite.A.=$+1
        EXPORT fwrite.A.
        ld hl,0 ;poi to data
         ;ld de,0 ;total processed bytes TODO
fwrite.C.=$+1
        EXPORT fwrite.C.
        ld bc,0 ;count
fwrite0.
        push bc
fwrite.B.=$+1
        EXPORT fwrite.B.
        ld bc,0 ;size
fwrite00.
        ld a,[hl]
        push hl
         ;push de
fwrite.D.=$+1
        ld hl,0 ;poi to FCB
        call fwrite1. ;a=data ;keeps bc
         ;pop de
         ;inc de
        pop hl
        ;cpi
        db 0xed,0xa1
        jp pe,fwrite00.
        pop bc
        dec hl
        ;cpi
        db 0xed,0xa1
        jp pe,fwrite0.
         ;ex de,hl ;hl = total processed bytes
        ret

fputs
        EXPORT fputs
;todo optimize
fputs.A.=$+1
        EXPORT fputs.A.
        ld bc,0 ;poi to string
        jp fputsgo.
fputs0.
fputs.B.=$+1
        EXPORT fputs.B.
        ld hl,0 ;poi to FCB
        call fwrite1. ;a=data
        inc bc
fputsgo.
        ld a,[bc]
        or a
        jp nz,fputs0.
        ret ;end of string ;(TODO hl = non-negative value)

loadfile
loadfile.A.=$+1 ;filename
        ld hl,0
        ld [nfopen.A.],hl
        ld hl,loadfile.mode.
        ld [nfopen.B.],hl
        call nfopen
         ld a,h
         or l
         ret z
        ld [fclose.A.],hl ;FCB
        ld [fread.D.],hl ;FCB
loadfile.B.=$+1 ;addr
        ld hl,0
        ld [fread.A.],hl ;addr
        ld hl,1
        ld [fread.B.],hl ;size
        ld hl,0xffff
        ld [fread.C.],hl ;count
       ld a,FALSE
       ld [_waseof],a
        call fread
        push hl
        call fclose
        pop hl
        ret
loadfile.mode.
        db "rb"
        db 0

;FUNC UINT readsectors FORWARD(PBYTE buf, UINT trsec, BYTE count);
readsectors
readsectors.A.=$+1 ;buf
        ld hl,0
readsectors.B.=$+1 ;trsec
        ld de,0
readsectors.C.=$+1 ;count
        ld b,0
        jr rdsectors.
rdsecDOSBUF
        ld hl,DOSBUF
rdsec.
        ld b,1
rdsectors.
        ld c,0x05
dos3d13.
        call 0x3d13
        ld hl,[0x5cf4] ;return hl=next sector
        ret

;FUNC UINT writesectors FORWARD(PBYTE buf, UINT trsec, BYTE count);
writesectors
writesectors.A.=$+1 ;buf
        ld hl,0
writesectors.B.=$+1 ;trsec
        ld de,0
writesectors.C.=$+1 ;count
        ld b,0
        jr wrsectors.
wrsecDOSBUF
        ld hl,DOSBUF
wrsec.
        ld b,1
wrsectors.
        ld c,0x06
        jr dos3d13.