From 4f28289df2b411154d4f5cf8d3235b54da515d94 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Mon, 28 Mar 2016 14:06:47 +0200 Subject: [PATCH 1/4] Added a pfs_remove() function and a pfs_seek() stub to the Commodore platforms. - "Normalized" some Assembly code. - Implemented CFS_APPEND in pfs_open(). - Made CFS_WRITE work in VICE's virtual disk/file system. --- .gitignore | 2 +- cpu/6502/lib/pfs.h | 16 +- platform/c128/Makefile.c128 | 2 +- platform/c128/lib/pfs.S | 521 +++++++++++++++++---------------- platform/c128/lib/pfs_remove.S | 59 ++++ platform/c128/lib/pfs_seek.S | 46 +++ platform/c128/lib/pfs_write.S | 47 +-- platform/c64/Makefile.c64 | 2 +- platform/c64/lib/pfs.S | 521 +++++++++++++++++---------------- platform/c64/lib/pfs_remove.S | 59 ++++ platform/c64/lib/pfs_seek.S | 46 +++ platform/c64/lib/pfs_write.S | 47 +-- 12 files changed, 818 insertions(+), 550 deletions(-) create mode 100644 platform/c128/lib/pfs_remove.S create mode 100644 platform/c128/lib/pfs_seek.S create mode 100644 platform/c64/lib/pfs_remove.S create mode 100644 platform/c64/lib/pfs_seek.S diff --git a/.gitignore b/.gitignore index c166681da..f4905fca9 100644 --- a/.gitignore +++ b/.gitignore @@ -80,7 +80,7 @@ contiki-cc2530dk.lib *.dsc #cc65 build artifacts -*.S +*.s *.eth *.dsk *.po diff --git a/cpu/6502/lib/pfs.h b/cpu/6502/lib/pfs.h index 25c62e8bf..73102ce55 100644 --- a/cpu/6502/lib/pfs.h +++ b/cpu/6502/lib/pfs.h @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * This file is part of the Contiki operating system. - * + * * Author: Oliver Schmidt * */ @@ -35,11 +35,13 @@ #ifndef PFS_H_ #define PFS_H_ -int __fastcall__ pfs_open(const char* name, int flags); -void __fastcall__ pfs_close(int fd); -int __fastcall__ pfs_read(int fd, void* buf, unsigned int len); -int __fastcall__ pfs_write(int fd, void* buf, unsigned int len); -int __fastcall__ pfs_seek(int fd, int offset, int whence); -int __fastcall__ pfs_remove(const char *name); +#include + +int __fastcall__ pfs_open(const char *name, int flags); +void __fastcall__ pfs_close(int fd); +int __fastcall__ pfs_read(int fd, void *buf, unsigned int len); +int __fastcall__ pfs_write(int fd, const void *buf, unsigned int len); +off_t __fastcall__ pfs_seek(int fd, off_t offset, int whence); +int __fastcall__ pfs_remove(const char *name); #endif /* PFS_H_ */ diff --git a/platform/c128/Makefile.c128 b/platform/c128/Makefile.c128 index b186fac60..55889d4ab 100644 --- a/platform/c128/Makefile.c128 +++ b/platform/c128/Makefile.c128 @@ -31,7 +31,7 @@ # Author: Oliver Schmidt # -CONTIKI_TARGET_SOURCEFILES += lseek.c pfs.S pfs_write.S +CONTIKI_TARGET_SOURCEFILES += lseek.c pfs.S pfs_remove.S pfs_seek.S pfs_write.S CONTIKI_CPU = $(CONTIKI)/cpu/6502 include $(CONTIKI_CPU)/Makefile.6502 diff --git a/platform/c128/lib/pfs.S b/platform/c128/lib/pfs.S index 62a2a7840..7947b67d8 100644 --- a/platform/c128/lib/pfs.S +++ b/platform/c128/lib/pfs.S @@ -29,99 +29,212 @@ ; This file is part of the Contiki operating system. ; ; Author: Kajtar Zsolt +; Author: Greg King ; ;--------------------------------------------------------------------- - .define F_IDE64 0 ; support IDE64, not on C128 +.define F_IDE64 0 ; C128 doesn't have IDE64 - .constructor init_pfs - .destructor done_pfs - .importzp ptr1, ptr2, ptr3, sp - .import curunit, __filetype, popax, addysp, subysp - .export pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend - .if F_IDE64 - .export ide64_rwprepare, ide64_rwfinish - .endif - .export _pfs_open, _pfs_read, _pfs_close + .constructor init_pfs + .destructor done_pfs + .importzp sp, ptr1, ptr2, ptr3 + .import curunit, __filetype, popax, addysp, subysp + .export pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend +.if F_IDE64 + .export ide64_rwprepare, ide64_rwfinish +.endif + .export cmdc, flags + .export pfs_makename, pfs_scratch + + .export _pfs_open, _pfs_read, _pfs_close ;--------------------------------------------------------------------- -F_EOF = $80 -F_NBLK = $40 -F_OPEN = $20 -F_MAXLEN = 80 ;max filename length -ST = $90 ;status -FN = $BB ;filename -FNL = $B7 ;filenamelength -LF = $B8 ;logical file number -SA = $B9 ;secondary address -OPEN = $FFC0 -CLOSE = $FFC3 -CHKIN = $FFC6 -CHKOUT = $FFC9 -CLRCHN = $FFCC -CHRIN = $FFCF -CHROUT = $FFD2 -SETLFS = $FFBA -SETNAM = $FFBD -CLALL = $FFE7 -WRITE = $DEF1 -READ = $DEF4 +MAXLEN = 80 ;maximum filename length + +; Flag bits +F_EOF = %10000000 ;end of file +F_NBLK = %01000000 ;block read/write not available +F_OPEN = %00100000 + +; Kernal variables +ST := $90 ;status +FN := $BB ;filename +FNL := $B7 ;filename length +LF := $B8 ;logical file number + +OPNVec := $031A ;address vector to OPEN function's code + +; IDEDOS function +READ := $DEF4 + +; Kernal functions +SETLFS := $FFBA +SETNAM := $FFBD +OPEN := $FFC0 +CLOSE := $FFC3 +CHKIN := $FFC6 +CHKOUT := $FFC9 +CLRCHN := $FFCC +CHRIN := $FFCF +CHROUT := $FFD2 ;--------------------------------------------------------------------- .data -illchr: .byte $3A, $2A, $3F, $3D ;illegal chars -pw: .byte $2C, $50, $2C, $57 ;,p,w +; illchr and sw must stay together because the comma, also, is illegal in names. +illchr: .byte "*?:=" ;illegal chars +sw: .byte ",s,w" cmdc: .byte 0 -flags: .res 10 +flags: .res 10 ;(Kernal allows only ten open files) ;--------------------------------------------------------------------- .segment "ONCE" init_pfs: - ldy #F_MAXLEN+8 - jsr subysp ;allocate - lda #0 - sta FNL ;no name - ldy #15-1 - jsr open2 ;open command channel + ldy #MAXLEN + 8 + jsr subysp ;allocate because open2 will free it + lda #0 ;no name, file number 1 + sta FNL + ldy #15 - 1 ;secondary address 15 + jsr open2 ;open command channel sta cmdc rts ;--------------------------------------------------------------------- .code -error3: jmp error - _pfs_open: - sta ptr2 - ; Pop and store name + sta ptr2 ;save open-mode flags + + ; Get and store name jsr popax + jsr pfs_makename + lda FNL + beq error ;must have a filename + + lda #2 - 1 ;file number + tay ;secondary address +open2: sta ptr2 + sty ptr2 + 1 + +next: inc ptr2 ;next file number + ldx ptr2 ;file number + cpx #.sizeof(flags) + 1 + bcs error ;no more files + lda flags - 1,x + bne next ;already used + lda ptr2 + 1 + bne nextsa + inx + stx ptr2 + 1 +nextsa: inc ptr2 + 1 ;next channel +retr: lda ptr2 ;file number + ldx curunit + ldy ptr2 + 1 ;secondary address (channel number) + jsr SETLFS + jsr OPEN ;open a pair of files (in computer and drive) + bcs oerr ;branch if could not open computer file + ldx cmdc + beq opok ;branch if error channel just was openned + jsr CHKIN + bcs error + jsr CHRIN + pha ;first digit of error code + jsr CHRIN + sta ptr1 ;second digit +@L4: jsr CHRIN ;flush status message + lda ST + beq @L4 + jsr CLRCHN + pla + cmp #'2' + bcc opok ;no serious error + pha + lda ptr2 + jsr CLOSE ;close computer file + pla + ldx ptr1 + cmp #'7' ;no channel? + bne nnoc + cpx #'0' + bne error ;not "no channel" + lda ptr2 + 1 + cmp #14 + bcc nextsa ;try next channel + bcs error ;give up + +opok: ldx ptr2 + lda #F_OPEN + sta flags - 1,x + txa ;OK, return file number +ret0: ldx #>$0000 +ret: ldy #MAXLEN + 8 ;free filename space + jmp addysp + +oerr: dec ptr2 + 1 + cmp #2 ;already open, + beq next ;retry with next + +error: lda #<-1 + tax ;failed + bne ret + +nnoc: inc ptr3 + bne error ;no retry + cmp #'6' + bne error ;not "file exists" + cpx #'3' + bne error + jsr pfs_scratch + bcc retr + bcs error ;branch always + +pfs_scratch: + ldx cmdc + jsr CHKOUT + bcs @L5 + ldy #1 + lda #'s' ;scratch +@L4: jsr CHROUT + lda (FN),y + iny + cmp #',' + bne @L4 + lda #$0D ;carriage return + jsr CHROUT + jsr CLRCHN + clc ;carry = 0: OK +@L5: rts ;carry = 1: error + +pfs_makename: sta FN - stx FN+1 ;filename (kernal) - ldy #F_MAXLEN+8 - jsr subysp ;allocate name - ldy #255 + stx FN+1 ;Kernal filename pointer + ldy #MAXLEN + 8 + jsr subysp ;allocate name space + + ; Validate the name; and, find its length + ldy #<-1 sty ptr3 sty ptr1 @L10: iny - cpy #F_MAXLEN - bcs error3 ;too long... - ldx #4 ;4+1 (comma) + cpy #MAXLEN + bcs badchr ;too long + lda (FN),y + ldx #.sizeof(illchr); 4 + 1 (includes comma) @L12: cmp illchr,x - beq error3 ;illegal char? + beq badchr ;illegal char dex bpl @L12 - cmp #$2F + cmp #'/' bne @L11 - sty ptr1 ;last slash -@L11: lda (FN),y + sty ptr1 ;last slash +@L11: tax ;test for '\0' bne @L10 - sty FNL + cpy #0 + beq badchr ;no name - tay - tax - lda #$30 ;this partition + tay ;zero index reg. + lda #'0' ;drive 0 or current partition sta (sp),y iny inc ptr1 beq nopath - lda #$2F + lda #'/' @L13: sta (sp),y iny lda (FN,x) @@ -130,158 +243,67 @@ _pfs_open: inc FN+1 @L14: cpy ptr1 bcc @L13 - lda #$2F + ;lda #'/' ; (.A already has a slash) sta (sp),y iny -nopath: lda #$3A +nopath: lda #':' @L16: sta (sp),y iny lda (FN,x) inc FN bne @L15 inc FN+1 -@L15: ora #0 +@L15: ora #$00 ;test for '\0' bne @L16 lsr ptr2 - bcs ro ;read only + bcs ro ;read-only (read-write not supported) lda __filetype - sta pw+1 ;set filetype - ldx #252 -@L20: lda pw-252,x - sta (sp),y ;write + sta sw + 1 ;set filetype + lsr ptr2 + lda #'w' ;write-only + lsr ptr2 + bcc write + lda #'a' ;append +write: sta sw + 3 ;set mode + ldx #$0100 - .sizeof(sw) +@L20: lda sw - ($0100 - .sizeof(sw)),x + sta (sp),y iny inx bne @L20 -ro: tya ;name length (kernal) +ro: tya ;pathname length ldx sp ldy sp+1 - jsr SETNAM +namset: jmp SETNAM - lda #0 ;file number - tay ;secondary address -open2: sta ptr2 - sty ptr2+1 - -next: inc ptr2 ;next file number - ldx ptr2 ;file number - cpx #11 - bcs error ;no more files - lda flags-1,x - bne next ;already used - lda ptr2+1 - bne nextsa - inx - stx ptr2+1 -nextsa: inc ptr2+1 ;next channel -retr: lda ptr2 ;file number - ldx curunit - ldy ptr2+1 ;secondary address - jsr SETLFS - jsr OPEN ;open - bcs oerr - ldx cmdc - beq opok ;error channel open - jsr CHKIN - bcs error - jsr CHRIN - pha - jsr CHRIN - sta ptr1 -@L4: jsr CHRIN - lda ST - beq @L4 - jsr CLRCHN - pla - tax - lsr - cmp #$18 ;no serious error - beq opok - txa - pha - lda ptr2 - jsr CLOSE ;close - pla - ldx ptr1 - cmp #$37 ;no channel? - bne nnoc - cpx #$30 - bne error ;not no channel - lda ptr2+1 - cmp #14 - bcc nextsa ;try next channel - bcs error ;give up - -opok: ldx ptr2 - lda #F_OPEN - sta flags-1,x - txa ;ok, return file number - ldx #0 -ret: ldy #F_MAXLEN+8 ; free filename - jmp addysp - -oerr: dec ptr2+1 - cmp #2 ;already open, - beq next ;retry with next - -error: lda #$FF - tax ;failed - bne ret - -nnoc: inc ptr3 - bne error ;no retry - cmp #$36 - bne error ;no exists - cpx #$33 - bne error - ldx cmdc - jsr CHKOUT - bcs error - lda FNL - sec - sbc #5 - tax - lda #$53 ;scratch - jsr CHROUT - ldy #1 -@L4: lda (FN),y - iny - jsr CHROUT - dex - bne @L4 - lda #$3D - jsr CHROUT - iny - lda (FN),y - jsr CHROUT - lda #$0d - jsr CHROUT - jsr CLRCHN - jmp retr +badchr: lda #0 + beq namset .proc _pfs_read jsr pfs_rwcommon ; pop params, check handle beq error2 ; not open bmi eof - .if F_IDE64 - asl + +.if F_IDE64 + asl a bmi nblk ; no block operation jsr CHKIN bcs error2 - + ; check support jsr ide64_rwprepare bcs norm - - ; read + + ; do a block read jsr READ bcs nosup jmp ide64_rwfinish nosup: lda #F_NBLK jsr pfs_rwsetflags - .endif +.endif ; Valid lfn. Make it the input file nblk: jsr CHKIN @@ -292,15 +314,15 @@ norm: ldy #0 @L3: inc ptr1 bne @L0 inc ptr1+1 - beq done ; branch always + beq done ; Read the next byte @L0: jsr CHRIN tax ; save the input byte - lda ST ; read the IEEE status - cmp #1 ; save it - and #%10111111 ; check anything but the EOI bit + lda ST ; read the file status + cmp #$01 ; save it + and #%10111111 ; check anything but the EOF bit bne error5 ; assume device not present ; Store the byte just read @@ -310,45 +332,60 @@ norm: ldy #0 bne @L1 inc ptr2+1 ; *buf++ = A; - ; Get the status again and check the EOI bit -@L1: bcc @L3 ; loop if no end of file + ; Get the status again; and, check the EOF bit +@L1: bcc @L3 ; loop if not end of file - ; Set the EOI flag and bail out + ; Set the EOF flag; and, bail out lda #F_EOF jsr pfs_rwsetflags - ; Read done, close the input channel -done: jsr CLRCHN ; clrchn + ; Read done; cancel the input channel +done: jsr CLRCHN ; Return the number of chars read -eof: jmp pfs_rwcommonend +eof: +; jmp pfs_rwcommonend ; (fall through) +.endproc + +.proc pfs_rwcommonend + lda ptr2 + sec + sbc ptr3 + pha + lda ptr2+1 + sbc ptr3+1 + tax + pla + rts .endproc - ; Error entry, file is not open done_pfs: - ldx #10 -@L2: ldy flags-1,x ; file open? + ldx #.sizeof(flags) +@L2: ldy flags - 1,x ; file open? beq @L1 txa - jsr _pfs_close + jsr close1 @L1: dex - bne @L2 + bne @L2 rts -error5: jsr CLRCHN ; clrchn +error5: jsr CLRCHN -error2: ldx #255 + ; Error entry, file is not open +error2: ldx #>-1 txa rts _pfs_close: - pha - jsr CLOSE ;close + cmp #.sizeof(flags) + 1 + bcs close0 ; don't close if not valid file number +close1: pha + jsr CLOSE pla tax - lda #0 - sta flags-1,x - rts + lda #$00 + sta flags - 1,x +close0: rts ; .X = file number .proc pfs_rwcommon eor #$FF @@ -366,70 +403,56 @@ _pfs_close: jsr popax ; get the handle sta LF - lda #0 - beq pfs_rwsetflags + lda #$00 +; beq pfs_rwsetflags ; (fall through) .endproc - .if F_IDE64 -.proc ide64_rwprepare - sec - lda ptr1+1 - eor #255 - beq small ; too small, not worth it - tay - lda ptr1 ; setup registers - eor #255 - tax - lda $031B - eor #$DE - bne noide ; open vector set? - lda $DE60 - eor #$49 - bne noide ; check identification - lda $DE61 - eor #$44 - bne noide - lda $DE62 - eor #$45 - bne noide - clc - lda #ptr2 -small: rts - -noide: lda #F_NBLK - bne pfs_rwsetflags -.endproc - .endif - .proc pfs_rwsetflags ldx LF - ora flags-1,x - sta flags-1,x + ora flags - 1,x + sta flags - 1,x rts .endproc - .if F_IDE64 +.if F_IDE64 +.proc ide64_rwprepare + sec ; assume it won't use IDEDOS + lda ptr1+1 + eor #$FF ; convert -count-1 back to count + beq small ; too small, not worth it + tay + lda ptr1 ; set up registers + eor #$FF + tax + lda OPNVec+1 + eor #>$DE00 + bne noide ; is OPEN vector set to IDEDOS? + lda $DE60 + eor #'i' + bne noide ; check identification + lda $DE61 + eor #'d' + bne noide + lda $DE62 + eor #'e' + bne noide + clc ; it will use IDEDOS + lda #ptr2 +small: rts + +noide: lda #F_NBLK + bne pfs_rwsetflags +.endproc + .proc ide64_rwfinish - txa + txa ; push .YX pha tya pha jsr CLRCHN - pla - tax - pla - rts -.endproc - .endif - -.proc pfs_rwcommonend - lda ptr2 - sec - sbc ptr3 - pha - lda ptr2+1 - sbc ptr3+1 + pla ; pull .XA tax pla rts .endproc +.endif diff --git a/platform/c128/lib/pfs_remove.S b/platform/c128/lib/pfs_remove.S new file mode 100644 index 000000000..7477e4314 --- /dev/null +++ b/platform/c128/lib/pfs_remove.S @@ -0,0 +1,59 @@ +; +; Copyright (c) 2016, Greg King +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions, and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions, and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; 3. Neither the name of the author nor the names of contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS"; AND, +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. +; +; This file is part of the Contiki operating system. +; +; Author: Greg King +; +;--------------------------------------------------------------------- + .importzp ptr2 + .import addysp + .import pfs_makename, pfs_scratch + + .export _pfs_remove +;--------------------------------------------------------------------- +MAXLEN = 80 ; max. filename length + +FNL := $B7 ; filename length +;--------------------------------------------------------------------- +.proc _pfs_remove + asl ptr2 ; force pfs_makename to format for pfs_scratch + jsr pfs_makename + ldx FNL + beq error ; no name + + jsr pfs_scratch + ldx #>$0000 + bcs error +ret: txa + ldy #MAXLEN + 8 ; free filename space + jmp addysp + +error: dex ;(ldx #>-1) + bne ret +.endproc diff --git a/platform/c128/lib/pfs_seek.S b/platform/c128/lib/pfs_seek.S new file mode 100644 index 000000000..4ef0014d1 --- /dev/null +++ b/platform/c128/lib/pfs_seek.S @@ -0,0 +1,46 @@ +; +; Copyright (c) 2016, Greg King +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions, and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions, and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; 3. Neither the name of the author nor the names of contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS"; AND, +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. +; +; This file is part of the Contiki operating system. +; +; Author: Greg King +; +;--------------------------------------------------------------------- + .importzp sp, sreg, ptr1, ptr2, ptr3 + .import popax, incsp6 + .import cmdc, flags + + .export _pfs_seek +;--------------------------------------------------------------------- +.proc _pfs_seek + lda #<-1 ; seek not implemented + tax + stx sreg ; return long data type + stx sreg+1 + jmp incsp6 ; drop int and long arguments from stack +.endproc diff --git a/platform/c128/lib/pfs_write.S b/platform/c128/lib/pfs_write.S index 0fc8e3160..e17ff91b7 100644 --- a/platform/c128/lib/pfs_write.S +++ b/platform/c128/lib/pfs_write.S @@ -31,27 +31,33 @@ ; Author: Kajtar Zsolt ; ;--------------------------------------------------------------------- - .define F_IDE64 0 ; support IDE64, 100 byte only +.define F_IDE64 0 ; c128 doesn't have IDE64 - .importzp ptr1, ptr2 - .import pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend - .if F_IDE64 - .import ide64_rwprepare, ide64_rwfinish - .endif - .export _pfs_write + .importzp ptr1, ptr2 + .import pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend +.if F_IDE64 + .import ide64_rwprepare, ide64_rwfinish +.endif + + .export _pfs_write ;--------------------------------------------------------------------- -F_NBLK = $40 -ST = $90 ;status -CHKOUT = $FFC9 -CLRCHN = $FFCC -CHROUT = $FFD2 -WRITE = $DEF1 +F_NBLK = %01000000 ;block read/write not available + +ST := $90 ;status + +; IDEDOS function +WRITE := $DEF1 + +; Kernal functions +CHKOUT := $FFC9 +CLRCHN := $FFCC +CHROUT := $FFD2 ;--------------------------------------------------------------------- .code -error5: jsr CLRCHN ; clrchn +error5: jsr CLRCHN -error2: ldx #255 +error2: ldx #>-1 txa rts @@ -59,8 +65,8 @@ error2: ldx #255 jsr pfs_rwcommon ; pop params, check handle beq error2 ; not open - .if F_IDE64 - asl +.if F_IDE64 + asl a bmi nblk ; no block operation jsr CHKOUT @@ -70,7 +76,7 @@ error2: ldx #255 jsr ide64_rwprepare bcs norm - ; write + ; do a block write jsr WRITE bcs nosup jmp ide64_rwfinish @@ -98,10 +104,9 @@ norm: ldy #0 lda ST beq @L3 bne error5 ; bail out on errors -@L2: - ; Wrote all chars, close the output channel - jsr CLRCHN + ; Wrote all chars.; cancel the output channel +@L2: jsr CLRCHN ; Return the number of chars written jmp pfs_rwcommonend diff --git a/platform/c64/Makefile.c64 b/platform/c64/Makefile.c64 index bf0197565..5dce702a8 100644 --- a/platform/c64/Makefile.c64 +++ b/platform/c64/Makefile.c64 @@ -31,7 +31,7 @@ # Author: Oliver Schmidt # -CONTIKI_TARGET_SOURCEFILES += lseek.c pfs.S pfs_write.S +CONTIKI_TARGET_SOURCEFILES += lseek.c pfs.S pfs_remove.S pfs_seek.S pfs_write.S CONTIKI_CPU = $(CONTIKI)/cpu/6502 include $(CONTIKI_CPU)/Makefile.6502 diff --git a/platform/c64/lib/pfs.S b/platform/c64/lib/pfs.S index c63d08d2e..49ef496ec 100644 --- a/platform/c64/lib/pfs.S +++ b/platform/c64/lib/pfs.S @@ -29,99 +29,212 @@ ; This file is part of the Contiki operating system. ; ; Author: Kajtar Zsolt +; Author: Greg King ; ;--------------------------------------------------------------------- - .define F_IDE64 1 ; support IDE64, 100 byte only +.define F_IDE64 1 ; support IDE64, >= $0100 bytes only - .constructor init_pfs - .destructor done_pfs - .importzp ptr1, ptr2, ptr3, sp - .import curunit, __filetype, popax, addysp, subysp - .export pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend - .if F_IDE64 - .export ide64_rwprepare, ide64_rwfinish - .endif - .export _pfs_open, _pfs_read, _pfs_close + .constructor init_pfs + .destructor done_pfs + .importzp sp, ptr1, ptr2, ptr3 + .import curunit, __filetype, popax, addysp, subysp + .export pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend +.if F_IDE64 + .export ide64_rwprepare, ide64_rwfinish +.endif + .export cmdc, flags + .export pfs_makename, pfs_scratch + + .export _pfs_open, _pfs_read, _pfs_close ;--------------------------------------------------------------------- -F_EOF = $80 -F_NBLK = $40 -F_OPEN = $20 -F_MAXLEN = 80 ;max filename length -ST = $90 ;status -FN = $BB ;filename -FNL = $B7 ;filenamelength -LF = $B8 ;logical file number -SA = $B9 ;secondary address -OPEN = $FFC0 -CLOSE = $FFC3 -CHKIN = $FFC6 -CHKOUT = $FFC9 -CLRCHN = $FFCC -CHRIN = $FFCF -CHROUT = $FFD2 -SETLFS = $FFBA -SETNAM = $FFBD -CLALL = $FFE7 -WRITE = $DEF1 -READ = $DEF4 +MAXLEN = 80 ;maximum filename length + +; Flag bits +F_EOF = %10000000 ;end of file +F_NBLK = %01000000 ;block read/write not available +F_OPEN = %00100000 + +; Kernal variables +ST := $90 ;status +FN := $BB ;filename +FNL := $B7 ;filename length +LF := $B8 ;logical file number + +OPNVec := $031A ;address vector to OPEN function's code + +; IDEDOS function +READ := $DEF4 + +; Kernal functions +SETLFS := $FFBA +SETNAM := $FFBD +OPEN := $FFC0 +CLOSE := $FFC3 +CHKIN := $FFC6 +CHKOUT := $FFC9 +CLRCHN := $FFCC +CHRIN := $FFCF +CHROUT := $FFD2 ;--------------------------------------------------------------------- .data -illchr: .byte $3A, $2A, $3F, $3D ;illegal chars -pw: .byte $2C, $50, $2C, $57 ;,p,w +; illchr and sw must stay together because the comma, also, is illegal in names. +illchr: .byte "*?:=" ;illegal chars +sw: .byte ",s,w" cmdc: .byte 0 -flags: .res 10 +flags: .res 10 ;(Kernal allows only ten open files) ;--------------------------------------------------------------------- .segment "ONCE" init_pfs: - ldy #F_MAXLEN+8 - jsr subysp ;allocate - lda #0 - sta FNL ;no name - ldy #15-1 - jsr open2 ;open command channel + ldy #MAXLEN + 8 + jsr subysp ;allocate because open2 will free it + lda #0 ;no name, file number 1 + sta FNL + ldy #15 - 1 ;secondary address 15 + jsr open2 ;open command channel sta cmdc rts ;--------------------------------------------------------------------- .code -error3: jmp error - _pfs_open: - sta ptr2 - ; Pop and store name + sta ptr2 ;save open-mode flags + + ; Get and store name jsr popax + jsr pfs_makename + lda FNL + beq error ;must have a filename + + lda #2 - 1 ;file number + tay ;secondary address +open2: sta ptr2 + sty ptr2 + 1 + +next: inc ptr2 ;next file number + ldx ptr2 ;file number + cpx #.sizeof(flags) + 1 + bcs error ;no more files + lda flags - 1,x + bne next ;already used + lda ptr2 + 1 + bne nextsa + inx + stx ptr2 + 1 +nextsa: inc ptr2 + 1 ;next channel +retr: lda ptr2 ;file number + ldx curunit + ldy ptr2 + 1 ;secondary address (channel number) + jsr SETLFS + jsr OPEN ;open a pair of files (in computer and drive) + bcs oerr ;branch if could not open computer file + ldx cmdc + beq opok ;branch if error channel just was openned + jsr CHKIN + bcs error + jsr CHRIN + pha ;first digit of error code + jsr CHRIN + sta ptr1 ;second digit +@L4: jsr CHRIN ;flush status message + lda ST + beq @L4 + jsr CLRCHN + pla + cmp #'2' + bcc opok ;no serious error + pha + lda ptr2 + jsr CLOSE ;close computer file + pla + ldx ptr1 + cmp #'7' ;no channel? + bne nnoc + cpx #'0' + bne error ;not "no channel" + lda ptr2 + 1 + cmp #14 + bcc nextsa ;try next channel + bcs error ;give up + +opok: ldx ptr2 + lda #F_OPEN + sta flags - 1,x + txa ;OK, return file number +ret0: ldx #>$0000 +ret: ldy #MAXLEN + 8 ;free filename space + jmp addysp + +oerr: dec ptr2 + 1 + cmp #2 ;already open, + beq next ;retry with next + +error: lda #<-1 + tax ;failed + bne ret + +nnoc: inc ptr3 + bne error ;no retry + cmp #'6' + bne error ;not "file exists" + cpx #'3' + bne error + jsr pfs_scratch + bcc retr + bcs error ;branch always + +pfs_scratch: + ldx cmdc + jsr CHKOUT + bcs @L5 + ldy #1 + lda #'s' ;scratch +@L4: jsr CHROUT + lda (FN),y + iny + cmp #',' + bne @L4 + lda #$0D ;carriage return + jsr CHROUT + jsr CLRCHN + clc ;carry = 0: OK +@L5: rts ;carry = 1: error + +pfs_makename: sta FN - stx FN+1 ;filename (kernal) - ldy #F_MAXLEN+8 - jsr subysp ;allocate name - ldy #255 + stx FN+1 ;Kernal filename pointer + ldy #MAXLEN + 8 + jsr subysp ;allocate name space + + ; Validate the name; and, find its length + ldy #<-1 sty ptr3 sty ptr1 @L10: iny - cpy #F_MAXLEN - bcs error3 ;too long... - ldx #4 ;4+1 (comma) + cpy #MAXLEN + bcs badchr ;too long + lda (FN),y + ldx #.sizeof(illchr); 4 + 1 (includes comma) @L12: cmp illchr,x - beq error3 ;illegal char? + beq badchr ;illegal char dex bpl @L12 - cmp #$2F + cmp #'/' bne @L11 - sty ptr1 ;last slash -@L11: lda (FN),y + sty ptr1 ;last slash +@L11: tax ;test for '\0' bne @L10 - sty FNL + cpy #0 + beq badchr ;no name - tay - tax - lda #$30 ;this partition + tay ;zero index reg. + lda #'0' ;drive 0 or current partition sta (sp),y iny inc ptr1 beq nopath - lda #$2F + lda #'/' @L13: sta (sp),y iny lda (FN,x) @@ -130,158 +243,67 @@ _pfs_open: inc FN+1 @L14: cpy ptr1 bcc @L13 - lda #$2F + ;lda #'/' ; (.A already has a slash) sta (sp),y iny -nopath: lda #$3A +nopath: lda #':' @L16: sta (sp),y iny lda (FN,x) inc FN bne @L15 inc FN+1 -@L15: ora #0 +@L15: ora #$00 ;test for '\0' bne @L16 lsr ptr2 - bcs ro ;read only + bcs ro ;read-only (read-write not supported) lda __filetype - sta pw+1 ;set filetype - ldx #252 -@L20: lda pw-252,x - sta (sp),y ;write + sta sw + 1 ;set filetype + lsr ptr2 + lda #'w' ;write-only + lsr ptr2 + bcc write + lda #'a' ;append +write: sta sw + 3 ;set mode + ldx #$0100 - .sizeof(sw) +@L20: lda sw - ($0100 - .sizeof(sw)),x + sta (sp),y iny inx bne @L20 -ro: tya ;name length (kernal) +ro: tya ;pathname length ldx sp ldy sp+1 - jsr SETNAM +namset: jmp SETNAM - lda #0 ;file number - tay ;secondary address -open2: sta ptr2 - sty ptr2+1 - -next: inc ptr2 ;next file number - ldx ptr2 ;file number - cpx #11 - bcs error ;no more files - lda flags-1,x - bne next ;already used - lda ptr2+1 - bne nextsa - inx - stx ptr2+1 -nextsa: inc ptr2+1 ;next channel -retr: lda ptr2 ;file number - ldx curunit - ldy ptr2+1 ;secondary address - jsr SETLFS - jsr OPEN ;open - bcs oerr - ldx cmdc - beq opok ;error channel open - jsr CHKIN - bcs error - jsr CHRIN - pha - jsr CHRIN - sta ptr1 -@L4: jsr CHRIN - lda ST - beq @L4 - jsr CLRCHN - pla - tax - lsr - cmp #$18 ;no serious error - beq opok - txa - pha - lda ptr2 - jsr CLOSE ;close - pla - ldx ptr1 - cmp #$37 ;no channel? - bne nnoc - cpx #$30 - bne error ;not no channel - lda ptr2+1 - cmp #14 - bcc nextsa ;try next channel - bcs error ;give up - -opok: ldx ptr2 - lda #F_OPEN - sta flags-1,x - txa ;ok, return file number - ldx #0 -ret: ldy #F_MAXLEN+8 ; free filename - jmp addysp - -oerr: dec ptr2+1 - cmp #2 ;already open, - beq next ;retry with next - -error: lda #$FF - tax ;failed - bne ret - -nnoc: inc ptr3 - bne error ;no retry - cmp #$36 - bne error ;no exists - cpx #$33 - bne error - ldx cmdc - jsr CHKOUT - bcs error - lda FNL - sec - sbc #5 - tax - lda #$53 ;scratch - jsr CHROUT - ldy #1 -@L4: lda (FN),y - iny - jsr CHROUT - dex - bne @L4 - lda #$3D - jsr CHROUT - iny - lda (FN),y - jsr CHROUT - lda #$0d - jsr CHROUT - jsr CLRCHN - jmp retr +badchr: lda #0 + beq namset .proc _pfs_read jsr pfs_rwcommon ; pop params, check handle beq error2 ; not open bmi eof - .if F_IDE64 - asl + +.if F_IDE64 + asl a bmi nblk ; no block operation jsr CHKIN bcs error2 - + ; check support jsr ide64_rwprepare bcs norm - - ; read + + ; do a block read jsr READ bcs nosup jmp ide64_rwfinish nosup: lda #F_NBLK jsr pfs_rwsetflags - .endif +.endif ; Valid lfn. Make it the input file nblk: jsr CHKIN @@ -292,15 +314,15 @@ norm: ldy #0 @L3: inc ptr1 bne @L0 inc ptr1+1 - beq done ; branch always + beq done ; Read the next byte @L0: jsr CHRIN tax ; save the input byte - lda ST ; read the IEEE status - cmp #1 ; save it - and #%10111111 ; check anything but the EOI bit + lda ST ; read the file status + cmp #$01 ; save it + and #%10111111 ; check anything but the EOF bit bne error5 ; assume device not present ; Store the byte just read @@ -310,45 +332,60 @@ norm: ldy #0 bne @L1 inc ptr2+1 ; *buf++ = A; - ; Get the status again and check the EOI bit -@L1: bcc @L3 ; loop if no end of file + ; Get the status again; and, check the EOF bit +@L1: bcc @L3 ; loop if not end of file - ; Set the EOI flag and bail out + ; Set the EOF flag; and, bail out lda #F_EOF jsr pfs_rwsetflags - ; Read done, close the input channel -done: jsr CLRCHN ; clrchn + ; Read done; cancel the input channel +done: jsr CLRCHN ; Return the number of chars read -eof: jmp pfs_rwcommonend +eof: +; jmp pfs_rwcommonend ; (fall through) +.endproc + +.proc pfs_rwcommonend + lda ptr2 + sec + sbc ptr3 + pha + lda ptr2+1 + sbc ptr3+1 + tax + pla + rts .endproc - ; Error entry, file is not open done_pfs: - ldx #10 -@L2: ldy flags-1,x ; file open? + ldx #.sizeof(flags) +@L2: ldy flags - 1,x ; file open? beq @L1 txa - jsr _pfs_close + jsr close1 @L1: dex - bne @L2 + bne @L2 rts -error5: jsr CLRCHN ; clrchn +error5: jsr CLRCHN -error2: ldx #255 + ; Error entry, file is not open +error2: ldx #>-1 txa rts _pfs_close: - pha - jsr CLOSE ;close + cmp #.sizeof(flags) + 1 + bcs close0 ; don't close if not valid file number +close1: pha + jsr CLOSE pla tax - lda #0 - sta flags-1,x - rts + lda #$00 + sta flags - 1,x +close0: rts ; .X = file number .proc pfs_rwcommon eor #$FF @@ -366,70 +403,56 @@ _pfs_close: jsr popax ; get the handle sta LF - lda #0 - beq pfs_rwsetflags + lda #$00 +; beq pfs_rwsetflags ; (fall through) .endproc - .if F_IDE64 -.proc ide64_rwprepare - sec - lda ptr1+1 - eor #255 - beq small ; too small, not worth it - tay - lda ptr1 ; setup registers - eor #255 - tax - lda $031B - eor #$DE - bne noide ; open vector set? - lda $DE60 - eor #$49 - bne noide ; check identification - lda $DE61 - eor #$44 - bne noide - lda $DE62 - eor #$45 - bne noide - clc - lda #ptr2 -small: rts - -noide: lda #F_NBLK - bne pfs_rwsetflags -.endproc - .endif - .proc pfs_rwsetflags ldx LF - ora flags-1,x - sta flags-1,x + ora flags - 1,x + sta flags - 1,x rts .endproc - .if F_IDE64 +.if F_IDE64 +.proc ide64_rwprepare + sec ; assume it won't use IDEDOS + lda ptr1+1 + eor #$FF ; convert -count-1 back to count + beq small ; too small, not worth it + tay + lda ptr1 ; set up registers + eor #$FF + tax + lda OPNVec+1 + eor #>$DE00 + bne noide ; is OPEN vector set to IDEDOS? + lda $DE60 + eor #'i' + bne noide ; check identification + lda $DE61 + eor #'d' + bne noide + lda $DE62 + eor #'e' + bne noide + clc ; it will use IDEDOS + lda #ptr2 +small: rts + +noide: lda #F_NBLK + bne pfs_rwsetflags +.endproc + .proc ide64_rwfinish - txa + txa ; push .YX pha tya pha jsr CLRCHN - pla - tax - pla - rts -.endproc - .endif - -.proc pfs_rwcommonend - lda ptr2 - sec - sbc ptr3 - pha - lda ptr2+1 - sbc ptr3+1 + pla ; pull .XA tax pla rts .endproc +.endif diff --git a/platform/c64/lib/pfs_remove.S b/platform/c64/lib/pfs_remove.S new file mode 100644 index 000000000..7477e4314 --- /dev/null +++ b/platform/c64/lib/pfs_remove.S @@ -0,0 +1,59 @@ +; +; Copyright (c) 2016, Greg King +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions, and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions, and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; 3. Neither the name of the author nor the names of contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS"; AND, +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. +; +; This file is part of the Contiki operating system. +; +; Author: Greg King +; +;--------------------------------------------------------------------- + .importzp ptr2 + .import addysp + .import pfs_makename, pfs_scratch + + .export _pfs_remove +;--------------------------------------------------------------------- +MAXLEN = 80 ; max. filename length + +FNL := $B7 ; filename length +;--------------------------------------------------------------------- +.proc _pfs_remove + asl ptr2 ; force pfs_makename to format for pfs_scratch + jsr pfs_makename + ldx FNL + beq error ; no name + + jsr pfs_scratch + ldx #>$0000 + bcs error +ret: txa + ldy #MAXLEN + 8 ; free filename space + jmp addysp + +error: dex ;(ldx #>-1) + bne ret +.endproc diff --git a/platform/c64/lib/pfs_seek.S b/platform/c64/lib/pfs_seek.S new file mode 100644 index 000000000..4ef0014d1 --- /dev/null +++ b/platform/c64/lib/pfs_seek.S @@ -0,0 +1,46 @@ +; +; Copyright (c) 2016, Greg King +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions, and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions, and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; 3. Neither the name of the author nor the names of contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS"; AND, +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. +; +; This file is part of the Contiki operating system. +; +; Author: Greg King +; +;--------------------------------------------------------------------- + .importzp sp, sreg, ptr1, ptr2, ptr3 + .import popax, incsp6 + .import cmdc, flags + + .export _pfs_seek +;--------------------------------------------------------------------- +.proc _pfs_seek + lda #<-1 ; seek not implemented + tax + stx sreg ; return long data type + stx sreg+1 + jmp incsp6 ; drop int and long arguments from stack +.endproc diff --git a/platform/c64/lib/pfs_write.S b/platform/c64/lib/pfs_write.S index 7e511e513..82632df8f 100644 --- a/platform/c64/lib/pfs_write.S +++ b/platform/c64/lib/pfs_write.S @@ -31,27 +31,33 @@ ; Author: Kajtar Zsolt ; ;--------------------------------------------------------------------- - .define F_IDE64 1 ; support IDE64, 100 byte only +.define F_IDE64 1 ; support IDE64, >= $0100 bytes only - .importzp ptr1, ptr2 - .import pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend - .if F_IDE64 - .import ide64_rwprepare, ide64_rwfinish - .endif - .export _pfs_write + .importzp ptr1, ptr2 + .import pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend +.if F_IDE64 + .import ide64_rwprepare, ide64_rwfinish +.endif + + .export _pfs_write ;--------------------------------------------------------------------- -F_NBLK = $40 -ST = $90 ;status -CHKOUT = $FFC9 -CLRCHN = $FFCC -CHROUT = $FFD2 -WRITE = $DEF1 +F_NBLK = %01000000 ;block read/write not available + +ST := $90 ;status + +; IDEDOS function +WRITE := $DEF1 + +; Kernal functions +CHKOUT := $FFC9 +CLRCHN := $FFCC +CHROUT := $FFD2 ;--------------------------------------------------------------------- .code -error5: jsr CLRCHN ; clrchn +error5: jsr CLRCHN -error2: ldx #255 +error2: ldx #>-1 txa rts @@ -59,8 +65,8 @@ error2: ldx #255 jsr pfs_rwcommon ; pop params, check handle beq error2 ; not open - .if F_IDE64 - asl +.if F_IDE64 + asl a bmi nblk ; no block operation jsr CHKOUT @@ -70,7 +76,7 @@ error2: ldx #255 jsr ide64_rwprepare bcs norm - ; write + ; do a block write jsr WRITE bcs nosup jmp ide64_rwfinish @@ -98,10 +104,9 @@ norm: ldy #0 lda ST beq @L3 bne error5 ; bail out on errors -@L2: - ; Wrote all chars, close the output channel - jsr CLRCHN + ; Wrote all chars.; cancel the output channel +@L2: jsr CLRCHN ; Return the number of chars written jmp pfs_rwcommonend From 111a976f1e8ef8f31929184403e63a985db8e645 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Mon, 28 Mar 2016 14:39:16 +0200 Subject: [PATCH 2/4] Explicitly mark constant as 'unsigned' to avoid unnecessary promotion to 'long'. Long constants trigger the performance warning "Constant is long" with cc65. --- core/net/mac/tsch/tsch-conf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/mac/tsch/tsch-conf.h b/core/net/mac/tsch/tsch-conf.h index bd9726042..3f877884a 100644 --- a/core/net/mac/tsch/tsch-conf.h +++ b/core/net/mac/tsch/tsch-conf.h @@ -135,7 +135,7 @@ #define TSCH_DEFAULT_TS_MAX_TX 4256 #define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 15000 -#elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 65000 +#elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 65000U /* 65ms timeslot, i.e. nearly the max length allowed by standard (16-bit unsigned in micro-seconds). * Useful for running link-layer security on sky or z1 in Cooja, where only S/W security is supported. * Note: this slot timing would require a total of 120ms. If a slot overlaps with the next active slot, From b287351d9959dd11956966b547605f02fb363f40 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Mon, 28 Mar 2016 19:43:51 +0200 Subject: [PATCH 3/4] Activated CBM PFS for the C64 Telnet server. Now that the CBM PFS supports file removal (and a file seek stub) it is possible to have the Telnet server leverage the IDE64 support of the CBM PFS. Note: Using the CBM PFS for the Telnet server does _not_ reduce the code size since the POSIX I/O functions are additionally still linked in because the POSIX directory functions internally use the POSIX I/O functions. And that's the very reason why the CBM PFS is _not_ activated for the C128 Telnet server: The CBM PFS for the C128 doesn't bring IDE64 support but is supposed to be used to reduce code size - but this isn't possible for the Telnet server. --- examples/telnet-server/Makefile.c64.defines | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/telnet-server/Makefile.c64.defines b/examples/telnet-server/Makefile.c64.defines index bcd39d550..caf0dfa69 100644 --- a/examples/telnet-server/Makefile.c64.defines +++ b/examples/telnet-server/Makefile.c64.defines @@ -1 +1 @@ -DEFINES = CONNECTIONS=3,WITH_LOGGING,WITH_CLIENT,WITH_DNS +DEFINES = CONNECTIONS=3,WITH_LOGGING,WITH_CLIENT,WITH_DNS,WITH_PFS From 7a5249b0666caa6f515502466327f5416b4fdda1 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Mon, 28 Mar 2016 20:03:47 +0200 Subject: [PATCH 4/4] Added a Contiki version of the CBM exec() system file; it uses PFS instead of POSIX. It reduces the webbrowsers' size by 735 bytes. --- platform/c128/Makefile.c128 | 2 +- platform/c128/lib/exec.c | 139 ++++++++++++++++++++++++++++++++++++ platform/c64/Makefile.c64 | 2 +- platform/c64/lib/exec.c | 139 ++++++++++++++++++++++++++++++++++++ 4 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 platform/c128/lib/exec.c create mode 100644 platform/c64/lib/exec.c diff --git a/platform/c128/Makefile.c128 b/platform/c128/Makefile.c128 index 55889d4ab..fbbcf8eda 100644 --- a/platform/c128/Makefile.c128 +++ b/platform/c128/Makefile.c128 @@ -31,7 +31,7 @@ # Author: Oliver Schmidt # -CONTIKI_TARGET_SOURCEFILES += lseek.c pfs.S pfs_remove.S pfs_seek.S pfs_write.S +CONTIKI_TARGET_SOURCEFILES += exec.c lseek.c pfs.S pfs_remove.S pfs_seek.S pfs_write.S CONTIKI_CPU = $(CONTIKI)/cpu/6502 include $(CONTIKI_CPU)/Makefile.6502 diff --git a/platform/c128/lib/exec.c b/platform/c128/lib/exec.c new file mode 100644 index 000000000..5a633d45d --- /dev/null +++ b/platform/c128/lib/exec.c @@ -0,0 +1,139 @@ +/* +** Program-chaining function for Commodore platforms. +** +** This copy of the cc65 system library function makes smaller code by using +** Contiki's Personal File System (instead of POSIX) functions. +** +** 2016-03-16, Greg King +** +** This function exploits the program-chaining feature in CBM BASIC's ROM. +** +** CC65's CBM programs have a BASIC program stub. We start those programs by +** RUNning that stub; it SYSes to the Machine Language code. Normally, after +** the ML code exits, the BASIC ROM continues running the stub. But, it has +** no more statements; so, the program stops. +** +** This function puts the desired program's name and device number into a LOAD +** statement. Then, it points BASIC to that statement, so that the ROM will run +** that statement after this program quits. The ROM will load the next program, +** and will execute it (because the LOAD will be seen in a running program). +*/ + +#include +#include +#include +#include +#include + +#include "cfs.h" + + +/* The struct below is a line of BASIC code. It sits in the LOWCODE segment +** to make sure that it won't be hidden by a ROM when BASIC is re-enabled. +** The line is: +** 0 CLR:LOAD""+"" ,01 +** After this function has written into the line, it might look like this: +** 0 CLR:LOAD""+"program name" ,08 +** +** When BASIC's LOAD command asks the Kernal to load a file, it gives the +** Kernal a pointer to a file-name string. CC65's CBM programs use that +** pointer to give a copy of the program's name to main()'s argv[0] parameter. +** But, when BASIC uses a string literal that is in a program, it points +** directly to that literal -- in the models that don't use banked RAM +** (Pet/CBM, VIC-20, and 64). The literal is overwritten by the next program +** that is loaded. So, argv[0] would point to machine code. String operations +** create a new result string -- even when that operation changes nothing. The +** result is put in the string space at the top of BASIC's memory. So, the ""+ +** in this BASIC line guarantees that argv[0] will get a name from a safe place. +*/ +#pragma data-name(push, "LOWCODE") +static struct line { + const char end_of_line; /* fake previous line */ + const struct line* const next; + const unsigned line_num; + const char CLR_token, colon, LOAD_token, quotes[2], add_token, quote; + char name[21]; + const char comma; + char unit[3]; +} basic = { + '\0', &basic + 1, /* high byte of link must be non-zero */ + 0, 0x9C, ':', 0x93, "\"\"", 0xAA, '\"', + "\" ", /* format: "123:1234567890123456\"" */ + ',', "01" +}; +#pragma data-name(pop) + +/* These values are platform-specific. */ +extern const void* vartab; /* points to BASIC program variables */ +#pragma zpsym("vartab") +extern const void* memsize; /* points to top of BASIC RAM */ +#pragma zpsym("memsize") +extern const struct line* txtptr; /* points to BASIC code */ +#pragma zpsym("txtptr") +extern char basbuf[]; /* BASIC's input buffer */ +extern void basbuf_len[]; +#pragma zpsym("basbuf_len") + + +int __fastcall__ +exec(const char *progname, const char *cmdline) +{ + static int fd; + static unsigned char dv, n; + + /* Exclude devices that can't load files. */ + /* (Use hand optimization, to make smaller code.) */ + dv = getcurrentdevice(); + if(dv < 8 && __AX__ != 1 || __AX__ > 30) { + return _mappederrno(9); /* illegal device number */ + } + utoa(dv, basic.unit, 10); + + /* Tape files can be openned only once; skip this test for the Datasette. */ + if(dv != 1) { + /* Don't try to run a program that can't be found. */ + fd = cfs_open(progname, CFS_READ); + if(fd < 0) { + return -1; + } + cfs_close(fd); + } + + n = 0; + do { + if((basic.name[n] = progname[n]) == '\0') { + break; + } + } while(++n < 20); /* truncate long names */ + basic.name[n] = '\"'; + +/* This next part isn't needed by machines that put +** BASIC source and variables in different RAM banks. +*/ +#if !defined(__C128__) + /* cc65 program loads might extend beyond the end of the RAM that is allowed + ** for BASIC. Then, the LOAD statement would complain that it is "out of + ** memory". Some pointers that say where to put BASIC program variables + ** must be changed, so that we do not get that error. One pointer is + ** changed here; a BASIC CLR statement changes the others. Some space is + ** needed for the file-name string. Subtracting an entire RAM page allows + ** better optimization of this expression. + */ + vartab = (char*)memsize - 0x0100; +#endif + + /* Build the next program's argument list. */ + basbuf[0] = 0x8F; /* REM token */ + basbuf[1] = '\0'; + if(cmdline != NULL) { + strncat(basbuf, cmdline, (size_t)basbuf_len - 2); + } + + /* Tell the ROM where to find that BASIC program. */ + txtptr = &basic; + + /* (The return code, in ST [status], will be destroyed by LOAD. + ** So, don't bother to set it here.) + */ + exit(__AX__); +} diff --git a/platform/c64/Makefile.c64 b/platform/c64/Makefile.c64 index 5dce702a8..7769b6ceb 100644 --- a/platform/c64/Makefile.c64 +++ b/platform/c64/Makefile.c64 @@ -31,7 +31,7 @@ # Author: Oliver Schmidt # -CONTIKI_TARGET_SOURCEFILES += lseek.c pfs.S pfs_remove.S pfs_seek.S pfs_write.S +CONTIKI_TARGET_SOURCEFILES += exec.c lseek.c pfs.S pfs_remove.S pfs_seek.S pfs_write.S CONTIKI_CPU = $(CONTIKI)/cpu/6502 include $(CONTIKI_CPU)/Makefile.6502 diff --git a/platform/c64/lib/exec.c b/platform/c64/lib/exec.c new file mode 100644 index 000000000..5a633d45d --- /dev/null +++ b/platform/c64/lib/exec.c @@ -0,0 +1,139 @@ +/* +** Program-chaining function for Commodore platforms. +** +** This copy of the cc65 system library function makes smaller code by using +** Contiki's Personal File System (instead of POSIX) functions. +** +** 2016-03-16, Greg King +** +** This function exploits the program-chaining feature in CBM BASIC's ROM. +** +** CC65's CBM programs have a BASIC program stub. We start those programs by +** RUNning that stub; it SYSes to the Machine Language code. Normally, after +** the ML code exits, the BASIC ROM continues running the stub. But, it has +** no more statements; so, the program stops. +** +** This function puts the desired program's name and device number into a LOAD +** statement. Then, it points BASIC to that statement, so that the ROM will run +** that statement after this program quits. The ROM will load the next program, +** and will execute it (because the LOAD will be seen in a running program). +*/ + +#include +#include +#include +#include +#include + +#include "cfs.h" + + +/* The struct below is a line of BASIC code. It sits in the LOWCODE segment +** to make sure that it won't be hidden by a ROM when BASIC is re-enabled. +** The line is: +** 0 CLR:LOAD""+"" ,01 +** After this function has written into the line, it might look like this: +** 0 CLR:LOAD""+"program name" ,08 +** +** When BASIC's LOAD command asks the Kernal to load a file, it gives the +** Kernal a pointer to a file-name string. CC65's CBM programs use that +** pointer to give a copy of the program's name to main()'s argv[0] parameter. +** But, when BASIC uses a string literal that is in a program, it points +** directly to that literal -- in the models that don't use banked RAM +** (Pet/CBM, VIC-20, and 64). The literal is overwritten by the next program +** that is loaded. So, argv[0] would point to machine code. String operations +** create a new result string -- even when that operation changes nothing. The +** result is put in the string space at the top of BASIC's memory. So, the ""+ +** in this BASIC line guarantees that argv[0] will get a name from a safe place. +*/ +#pragma data-name(push, "LOWCODE") +static struct line { + const char end_of_line; /* fake previous line */ + const struct line* const next; + const unsigned line_num; + const char CLR_token, colon, LOAD_token, quotes[2], add_token, quote; + char name[21]; + const char comma; + char unit[3]; +} basic = { + '\0', &basic + 1, /* high byte of link must be non-zero */ + 0, 0x9C, ':', 0x93, "\"\"", 0xAA, '\"', + "\" ", /* format: "123:1234567890123456\"" */ + ',', "01" +}; +#pragma data-name(pop) + +/* These values are platform-specific. */ +extern const void* vartab; /* points to BASIC program variables */ +#pragma zpsym("vartab") +extern const void* memsize; /* points to top of BASIC RAM */ +#pragma zpsym("memsize") +extern const struct line* txtptr; /* points to BASIC code */ +#pragma zpsym("txtptr") +extern char basbuf[]; /* BASIC's input buffer */ +extern void basbuf_len[]; +#pragma zpsym("basbuf_len") + + +int __fastcall__ +exec(const char *progname, const char *cmdline) +{ + static int fd; + static unsigned char dv, n; + + /* Exclude devices that can't load files. */ + /* (Use hand optimization, to make smaller code.) */ + dv = getcurrentdevice(); + if(dv < 8 && __AX__ != 1 || __AX__ > 30) { + return _mappederrno(9); /* illegal device number */ + } + utoa(dv, basic.unit, 10); + + /* Tape files can be openned only once; skip this test for the Datasette. */ + if(dv != 1) { + /* Don't try to run a program that can't be found. */ + fd = cfs_open(progname, CFS_READ); + if(fd < 0) { + return -1; + } + cfs_close(fd); + } + + n = 0; + do { + if((basic.name[n] = progname[n]) == '\0') { + break; + } + } while(++n < 20); /* truncate long names */ + basic.name[n] = '\"'; + +/* This next part isn't needed by machines that put +** BASIC source and variables in different RAM banks. +*/ +#if !defined(__C128__) + /* cc65 program loads might extend beyond the end of the RAM that is allowed + ** for BASIC. Then, the LOAD statement would complain that it is "out of + ** memory". Some pointers that say where to put BASIC program variables + ** must be changed, so that we do not get that error. One pointer is + ** changed here; a BASIC CLR statement changes the others. Some space is + ** needed for the file-name string. Subtracting an entire RAM page allows + ** better optimization of this expression. + */ + vartab = (char*)memsize - 0x0100; +#endif + + /* Build the next program's argument list. */ + basbuf[0] = 0x8F; /* REM token */ + basbuf[1] = '\0'; + if(cmdline != NULL) { + strncat(basbuf, cmdline, (size_t)basbuf_len - 2); + } + + /* Tell the ROM where to find that BASIC program. */ + txtptr = &basic; + + /* (The return code, in ST [status], will be destroyed by LOAD. + ** So, don't bother to set it here.) + */ + exit(__AX__); +}