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__);
+}