diff --git a/apps/webbrowser/htmlparser.c b/apps/webbrowser/htmlparser.c
index b0d8cfdc3..07653be8e 100644
--- a/apps/webbrowser/htmlparser.c
+++ b/apps/webbrowser/htmlparser.c
@@ -410,6 +410,7 @@ parse_tag(void)
switch_majorstate(s.lastmajorstate);
break;
case TAG_BODY:
+ do_word();
s.majorstate = s.lastmajorstate = MAJORSTATE_BODY;
break;
case TAG_IMG:
diff --git a/core/cfs/cfs-posix-dir.c b/core/cfs/cfs-posix-dir.c
index 0eb2ba9cb..623471b29 100644
--- a/core/cfs/cfs-posix-dir.c
+++ b/core/cfs/cfs-posix-dir.c
@@ -36,6 +36,7 @@
#include
#include
+#define CFS_IMPL 1
#include "cfs/cfs.h"
struct cfs_posix_dir {
diff --git a/core/cfs/cfs-posix.c b/core/cfs/cfs-posix.c
index 1ee1b99df..452ddbbbb 100644
--- a/core/cfs/cfs-posix.c
+++ b/core/cfs/cfs-posix.c
@@ -40,6 +40,7 @@
#include
#endif
+#define CFS_IMPL 1
#include "cfs/cfs.h"
/*---------------------------------------------------------------------------*/
diff --git a/cpu/6502/6502def.h b/cpu/6502/6502def.h
index 2da81b02e..c0f5c999a 100644
--- a/cpu/6502/6502def.h
+++ b/cpu/6502/6502def.h
@@ -74,6 +74,12 @@ typedef unsigned short uip_stats_t;
#define LOADER_CONF_ARCH "lib/unload.h"
+#ifdef HAVE_LOGSCR
+void logscr(const void *msg, unsigned len);
+#else
+#define logscr(msg, len) write(STDERR_FILENO, msg, len)
+#endif
+
#if MTU_SIZE
#define UIP_CONF_BUFFER_SIZE (UIP_LLH_LEN + MTU_SIZE)
#else /* MTU_SIZE */
diff --git a/cpu/6502/lib/log.c b/cpu/6502/lib/log.c
index 93ed0eeda..a259c06d6 100644
--- a/cpu/6502/lib/log.c
+++ b/cpu/6502/lib/log.c
@@ -32,7 +32,6 @@
*
*/
-#include
#include
#include "net/ip/uip.h"
@@ -43,8 +42,8 @@
void
uip_log(char *message)
{
- write(STDERR_FILENO, message, strlen(message));
- write(STDERR_FILENO, "\n", 1);
+ logscr(message, strlen(message));
+ logscr("\n", 1);
}
#endif /* UIP_LOGGING */
/*-----------------------------------------------------------------------------------*/
@@ -52,9 +51,9 @@ uip_log(char *message)
void
log_message(const char *part1, const char *part2)
{
- write(STDERR_FILENO, part1, strlen(part1));
- write(STDERR_FILENO, part2, strlen(part2));
- write(STDERR_FILENO, "\n", 1);
+ logscr(part1, strlen(part1));
+ logscr(part2, strlen(part2));
+ logscr("\n", 1);
}
#endif /* LOG_CONF_ENABLED */
/*-----------------------------------------------------------------------------------*/
diff --git a/cpu/6502/lib/pfs.h b/cpu/6502/lib/pfs.h
index 73102ce55..51fcd7c5b 100644
--- a/cpu/6502/lib/pfs.h
+++ b/cpu/6502/lib/pfs.h
@@ -29,6 +29,7 @@
* This file is part of the Contiki operating system.
*
* Author: Oliver Schmidt
+ * Author: Greg King
*
*/
@@ -37,11 +38,17 @@
#include
+struct cfs_dir;
+struct cfs_dirent;
+
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);
+int __fastcall__ pfs_opendir(struct cfs_dir *dirp, const char *name);
+void __fastcall__ pfs_closedir(struct cfs_dir *dirp);
+int __fastcall__ pfs_readdir(struct cfs_dir *dirp, struct cfs_dirent *dirent);
#endif /* PFS_H_ */
diff --git a/examples/telnet-server/Makefile.c128.defines b/examples/telnet-server/Makefile.c128.defines
index 062a12cd7..d8cd8baee 100644
--- a/examples/telnet-server/Makefile.c128.defines
+++ b/examples/telnet-server/Makefile.c128.defines
@@ -1 +1 @@
-DEFINES = WITH_LOGGING,WITH_80COL
+DEFINES = WITH_LOGGING,WITH_PFS,WITH_80COL
diff --git a/examples/wget/wget.c b/examples/wget/wget.c
index bdba5b25d..bf1daf141 100644
--- a/examples/wget/wget.c
+++ b/examples/wget/wget.c
@@ -35,6 +35,10 @@
#include
#include
+#ifdef __CC65__
+#include
+#endif /* __CC65__ */
+
#include "contiki-net.h"
#include "webclient.h"
#include "cfs/cfs.h"
@@ -146,8 +150,12 @@ app_quit(void)
if(file != -1) {
cfs_close(file);
}
- puts("Press to continue...");
- getchar();
+#ifdef __CC65__
+ if(doesclrscrafterexit()) {
+ puts("Press to continue...");
+ getchar();
+ }
+#endif /* __CC65__ */
process_exit(&wget_process);
LOADER_UNLOAD();
}
diff --git a/platform/apple2enh/lib/error.c b/platform/apple2enh/lib/error.c
index b030d5877..39f3b0d7b 100644
--- a/platform/apple2enh/lib/error.c
+++ b/platform/apple2enh/lib/error.c
@@ -33,6 +33,7 @@
*/
#include
+#include
#include "sys/log.h"
@@ -43,8 +44,10 @@ void
error_exit(void)
{
#if LOG_CONF_ENABLED
- log_message("Press any key to continue ...", "");
- ctk_arch_getkey();
+ if(doesclrscrafterexit()) {
+ log_message("Press any key to continue ...", "");
+ ctk_arch_getkey();
+ }
#endif /* LOG_CONF_ENABLED */
exit(EXIT_FAILURE);
}
diff --git a/platform/atarixl/lib/error.c b/platform/atarixl/lib/error.c
index b030d5877..39f3b0d7b 100644
--- a/platform/atarixl/lib/error.c
+++ b/platform/atarixl/lib/error.c
@@ -33,6 +33,7 @@
*/
#include
+#include
#include "sys/log.h"
@@ -43,8 +44,10 @@ void
error_exit(void)
{
#if LOG_CONF_ENABLED
- log_message("Press any key to continue ...", "");
- ctk_arch_getkey();
+ if(doesclrscrafterexit()) {
+ log_message("Press any key to continue ...", "");
+ ctk_arch_getkey();
+ }
#endif /* LOG_CONF_ENABLED */
exit(EXIT_FAILURE);
}
diff --git a/platform/c128/Makefile.c128 b/platform/c128/Makefile.c128
index 0c674ee38..c1adbaf08 100644
--- a/platform/c128/Makefile.c128
+++ b/platform/c128/Makefile.c128
@@ -31,7 +31,8 @@
# Author: Oliver Schmidt
#
-CONTIKI_TARGET_SOURCEFILES += exec.c lseek.c pfs.S pfs_remove.S pfs_seek.S pfs_write.S
+CONTIKI_TARGET_SOURCEFILES += exec.c logscr.S lseek.c \
+ pfs.S pfs-dir.c pfs-dir-asm.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/contiki-conf.h b/platform/c128/contiki-conf.h
index 057d6473d..9ee7cc2b7 100644
--- a/platform/c128/contiki-conf.h
+++ b/platform/c128/contiki-conf.h
@@ -35,8 +35,16 @@
#ifndef CONTIKI_CONF_H_
#define CONTIKI_CONF_H_
+#define HAVE_LOGSCR
+
#include "6502def.h"
+#if (WITH_PFS && !CFS_IMPL)
+#define cfs_opendir pfs_opendir
+#define cfs_closedir pfs_closedir
+#define cfs_readdir pfs_readdir
+#endif
+
#define CTK_CONF_MENU_KEY CH_F1
#define CTK_CONF_WINDOWSWITCH_KEY CH_F3
#define CTK_CONF_WIDGETUP_KEY CH_F5
diff --git a/platform/c128/lib/logscr.S b/platform/c128/lib/logscr.S
new file mode 100644
index 000000000..e87e2aa17
--- /dev/null
+++ b/platform/c128/lib/logscr.S
@@ -0,0 +1,5 @@
+; 2016-04-28, Greg King
+;
+; The C128 function is the same as the C64 function.
+
+ .include "../../c64/lib/logscr.S"
diff --git a/platform/c128/lib/pfs-dir-asm.S b/platform/c128/lib/pfs-dir-asm.S
new file mode 100644
index 000000000..dbc1c956f
--- /dev/null
+++ b/platform/c128/lib/pfs-dir-asm.S
@@ -0,0 +1,114 @@
+;
+; Helper functions for pfs_opendir() and pfs_readdir()
+;
+; Close a directory listing that had been openned by pfs_opendir().
+;
+; 2012-06-01, Ullrich von Bassewitz
+; 2016-04-10, Greg King
+;
+
+ .importzp sp, ptr1, tmp1
+ .import pushax, _pfs_read, _pfs_close
+ .export __pfs_dirread1, __pfs_dirread
+
+ .export _pfs_closedir
+
+;---------------------------------------------------------------------------
+; Data structure
+
+.struct DIR
+ fd .word
+.endstruct
+
+;---------------------------------------------------------------------------
+; /* Read one byte from the directory into the supplied buffer.
+; ** Return true if the read was successful, and false otherwise.
+; */
+; unsigned char __fastcall__ _pfs_dirread1(struct cfs_dir *dir, void *buf);
+
+__pfs_dirread1:
+ jsr pushax ; Push buf
+ lda #1 ; Load count = 1
+
+; Run directly into __dirread
+
+;---------------------------------------------------------------------------
+; /* Read characters from the directory into the supplied buffer.
+; ** Return true if the read was successful, and false otherwise.
+; */
+; unsigned char __fastcall__ _pfs_dirread(struct cfs_dir *dir, void *buf,
+
+__pfs_dirread:
+ pha ; Save count
+
+; Replace dir by ((DIR*)dir)->fd.
+
+ ldy #$02
+ lda (sp),y
+ sta ptr1
+ iny
+ lda (sp),y
+ sta ptr1+1
+ ldy #DIR::fd+1
+ lda (ptr1),y
+ pha
+ dey
+ lda (ptr1),y
+ ldy #$02
+ sta (sp),y
+ pla
+ iny
+ sta (sp),y
+
+; Get count, save it again, clear the high byte, and call pfs_read().
+; By the previous actions, the stack frame is as pfs_read() needs it;
+; and, pfs_read() also will drop it.
+
+ pla
+ pha
+ ldx #>$0000
+ jsr _pfs_read
+
+; Check for errors.
+
+ cpx #>-1
+ beq L3
+
+; pfs_read() was successful; check number of bytes read. We assume that
+; pfs_read() will not return more than count; so, .X is zero if we come here.
+
+ sta tmp1 ; Save returned count
+ pla ; Our count
+ cmp tmp1
+ beq L2 ; OK, return count
+
+; Didn't read enough bytes. That is an error for us.
+
+ bne L1 ; Branch always
+
+; pfs_read() returned an error.
+
+L3: pla ; Drop count
+ inx ; .X = 0
+L1: txa ; Return zero
+L2: rts
+
+;---------------------------------------------------------------------------
+; void __fastcall__ pfs_closedir(struct cfs_dir *dirp);
+
+.proc _pfs_closedir
+ sta ptr1
+ stx ptr1+1
+
+; Load ((DIR *)dirp)->fd.
+
+ ldy #DIR::fd+1
+ lda (ptr1),y
+ tax
+ dey
+ lda (ptr1),y
+
+; Close the directory file.
+
+ jmp _pfs_close
+.endproc
diff --git a/platform/c128/lib/pfs-dir.c b/platform/c128/lib/pfs-dir.c
new file mode 100644
index 000000000..2b9d959f9
--- /dev/null
+++ b/platform/c128/lib/pfs-dir.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2016, Greg King
+ *
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 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 a part of the Contiki operating system.
+ */
+
+/*
+** Open a directory listing, so that it can be read by pfs_readdir().
+**
+** Read one file-name from a directory listing that was opened by pfs_opendir().
+**
+** 2012-05-30, Ullrich von Bassewitz
+** 2016-04-22, Greg King
+*/
+
+#include "cfs.h"
+
+typedef struct {
+ int fd; /* File descriptor for a directory */
+} DIR;
+
+/*---------------------------------------------------------------------------*/
+/*
+** Read characters from the directory into the supplied buffer.
+** Return true if the read was successful, and false otherwise.
+*/
+extern unsigned char __fastcall__ _pfs_dirread(struct cfs_dir *dir, void *buf,
+ unsigned char count);
+
+/*
+** Read one byte from the directory into the supplied buffer.
+** Return true if the read was successful, and false otherwise.
+*/
+extern unsigned char __fastcall__ _pfs_dirread1(struct cfs_dir *dir, void *buf);
+/*---------------------------------------------------------------------------*/
+int __fastcall__
+pfs_opendir(struct cfs_dir *dirp, register const char *name)
+{
+ static int fd;
+ static char buf[2 + 1] = "$";
+
+ /* Set up the actual file name that is sent to the DOS.
+ ** We accept "0:", "1:", "/", and "." as directory names.
+ */
+ if(name == NULL || name[0] == '\0' || (name[0] == '.' || name[0] == '/') && name[1] == '\0') {
+ buf[1] = '\0';
+ } else if((name[0] == '0' || name[0] == '1') && name[1] == ':' && name[2] == '\0') {
+ buf[1] = name[0];
+ buf[2] = '\0';
+ } else {
+ return -1;
+ }
+
+ /* Open the directory on a disk, for reading. */
+ fd = pfs_open(buf, CFS_READ);
+ if(fd >= 0) {
+ ((DIR *)dirp)->fd = fd;
+
+ /* Skip the load address. */
+ if(_pfs_dirread(dirp, buf + 1, 2)) {
+ return 0;
+ } else {
+ pfs_close(fd);
+ }
+ }
+
+ return -1;
+}
+/*---------------------------------------------------------------------------*/
+int __fastcall__
+pfs_readdir(struct cfs_dir *dirp, register struct cfs_dirent *dirent)
+{
+ register unsigned char *b;
+ register unsigned char i;
+ register unsigned char count;
+ unsigned char buffer[0x40];
+ static unsigned char s;
+ static unsigned char j;
+
+ /* Skip the BASIC line-link. */
+ if(!_pfs_dirread(dirp, buffer, 2)) {
+ return -1;
+ }
+
+ /* Read the number of blocks. It's a two-byte number; but, the size is
+ ** a four-byte number. Zero the size; then, put the block number in
+ ** the first two bytes. It works because the 6502 CPU's numbers are
+ ** little-endian.
+ */
+ dirent->size = 0;
+ if(!_pfs_dirread(dirp, &dirent->size, 2)) {
+ return -1;
+ }
+
+ /* Read the next file entry into a buffer. */
+ for(count = 0, b = buffer; count < sizeof(buffer); ++b) {
+ if(!_pfs_dirread1(dirp, b)) {
+ return -1;
+ }
+ ++count;
+ if(*b == '\0') {
+ break;
+ }
+ }
+
+ /* The end of the directory was reached if the buffer contains "blocks free."
+ ** It is sufficient here to check for the leading 'b'. The buffer will have
+ ** at least one byte if we come here.
+ */
+ if(buffer[0] == 'b') {
+ return -1;
+ }
+
+ /* Parse the buffer for the file-name. */
+ b = buffer;
+ j = 0;
+ s = 0;
+ i = 0;
+ while(i < count) {
+ switch(s) {
+ case 0:
+ /* Search for the start of the file-name. */
+ if(*b == '"') {
+ s = 1;
+ }
+ break;
+ case 1:
+ /* Within the file-name. */
+ if(*b == '"') {
+ /* The end of the file-name was found. */
+ dirent->name[j] = '\0';
+ return 0;
+ } else if(j < sizeof(dirent->name) - 1) {
+ dirent->name[j] = *b;
+ ++j;
+ }
+ break;
+ }
+ ++b;
+ ++i;
+ }
+
+ /* The file-name is too long for the buffer. Return what could be read. */
+ dirent->name[j] = '\0';
+ return 0;
+}
diff --git a/platform/c128/lib/pfs.S b/platform/c128/lib/pfs.S
index 7947b67d8..b835f613e 100644
--- a/platform/c128/lib/pfs.S
+++ b/platform/c128/lib/pfs.S
@@ -36,7 +36,7 @@
.constructor init_pfs
.destructor done_pfs
- .importzp sp, ptr1, ptr2, ptr3
+ .importzp sp, ptr1, ptr2, ptr3, tmp1
.import curunit, __filetype, popax, addysp, subysp
.export pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend
.if F_IDE64
@@ -46,6 +46,7 @@
.export pfs_makename, pfs_scratch
.export _pfs_open, _pfs_read, _pfs_close
+
;---------------------------------------------------------------------
MAXLEN = 80 ;maximum filename length
@@ -107,7 +108,14 @@ _pfs_open:
lda FNL
beq error ;must have a filename
- lda #2 - 1 ;file number
+ ; A directory listing needs a special secondary address
+ ldy tmp1
+ bne open1 ;branch if not directory
+ lda #2 - 1
+ dey ;.Y = 0 - 1
+ bne open2 ;branch always
+
+open1: lda #2 - 1 ;file number
tay ;secondary address
open2: sta ptr2
sty ptr2 + 1
@@ -118,10 +126,6 @@ next: inc ptr2 ;next file number
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
@@ -209,7 +213,7 @@ pfs_makename:
; Validate the name; and, find its length
ldy #<-1
- sty ptr3
+ sty ptr3 ;init. the count of retries
sty ptr1
@L10: iny
cpy #MAXLEN
@@ -227,9 +231,17 @@ pfs_makename:
bne @L10
cpy #0
beq badchr ;no name
+ sty FNL ;save original length
tay ;zero index reg.
- lda #'0' ;drive 0 or current partition
+ lda (FN),y
+ sta tmp1 ;preset not-directory flag to true
+ cmp #'$'
+ bne @L9
+ sty tmp1 ;set not-directory flag to false
+ rts
+
+@L9: lda #'0' ;drive 0 or current partition
sta (sp),y
iny
inc ptr1
diff --git a/platform/c64/Makefile.c64 b/platform/c64/Makefile.c64
index f78dcf717..7fcb4d19f 100644
--- a/platform/c64/Makefile.c64
+++ b/platform/c64/Makefile.c64
@@ -31,7 +31,8 @@
# Author: Oliver Schmidt
#
-CONTIKI_TARGET_SOURCEFILES += exec.c lseek.c pfs.S pfs_remove.S pfs_seek.S pfs_write.S
+CONTIKI_TARGET_SOURCEFILES += exec.c logscr.S lseek.c \
+ pfs.S pfs-dir.c pfs-dir-asm.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/contiki-conf.h b/platform/c64/contiki-conf.h
index 7d5a8d070..21ea459bd 100644
--- a/platform/c64/contiki-conf.h
+++ b/platform/c64/contiki-conf.h
@@ -35,8 +35,16 @@
#ifndef CONTIKI_CONF_H_
#define CONTIKI_CONF_H_
+#define HAVE_LOGSCR
+
#include "6502def.h"
+#if (WITH_PFS && !CFS_IMPL)
+#define cfs_opendir pfs_opendir
+#define cfs_closedir pfs_closedir
+#define cfs_readdir pfs_readdir
+#endif
+
#define CTK_CONF_MENU_KEY CH_F1
#define CTK_CONF_WINDOWSWITCH_KEY CH_F3
#define CTK_CONF_WIDGETUP_KEY CH_F5
diff --git a/platform/c64/lib/logscr.S b/platform/c64/lib/logscr.S
new file mode 100644
index 000000000..e9f297be7
--- /dev/null
+++ b/platform/c64/lib/logscr.S
@@ -0,0 +1,38 @@
+; 2002-11-16, Ullrich von Bassewitz
+; 2016-04-28, Greg King
+;
+; void logscr(const void *msg, unsigned len);
+
+ .export _logscr
+
+ .import BSOUT
+ .import popax
+ .importzp ptr1, ptr2
+
+;--------------------------------------------------------------------------
+
+.proc _logscr
+ eor #$FF
+ sta ptr2
+ txa
+ eor #$FF
+ sta ptr2+1 ; remember -count-1
+
+ jsr popax ; get buf
+ sta ptr1
+ stx ptr1+1
+
+L1: inc ptr2 ; count the char that will be printed
+ bne L2
+ inc ptr2+1
+ beq L9
+L2: ldy #$00
+ lda (ptr1),y
+ jsr BSOUT
+ inc ptr1
+ bne L1
+ inc ptr1+1
+ bne L1 ; branch always
+
+L9: rts
+.endproc
diff --git a/platform/c64/lib/pfs-dir-asm.S b/platform/c64/lib/pfs-dir-asm.S
new file mode 100644
index 000000000..dbc1c956f
--- /dev/null
+++ b/platform/c64/lib/pfs-dir-asm.S
@@ -0,0 +1,114 @@
+;
+; Helper functions for pfs_opendir() and pfs_readdir()
+;
+; Close a directory listing that had been openned by pfs_opendir().
+;
+; 2012-06-01, Ullrich von Bassewitz
+; 2016-04-10, Greg King
+;
+
+ .importzp sp, ptr1, tmp1
+ .import pushax, _pfs_read, _pfs_close
+ .export __pfs_dirread1, __pfs_dirread
+
+ .export _pfs_closedir
+
+;---------------------------------------------------------------------------
+; Data structure
+
+.struct DIR
+ fd .word
+.endstruct
+
+;---------------------------------------------------------------------------
+; /* Read one byte from the directory into the supplied buffer.
+; ** Return true if the read was successful, and false otherwise.
+; */
+; unsigned char __fastcall__ _pfs_dirread1(struct cfs_dir *dir, void *buf);
+
+__pfs_dirread1:
+ jsr pushax ; Push buf
+ lda #1 ; Load count = 1
+
+; Run directly into __dirread
+
+;---------------------------------------------------------------------------
+; /* Read characters from the directory into the supplied buffer.
+; ** Return true if the read was successful, and false otherwise.
+; */
+; unsigned char __fastcall__ _pfs_dirread(struct cfs_dir *dir, void *buf,
+
+__pfs_dirread:
+ pha ; Save count
+
+; Replace dir by ((DIR*)dir)->fd.
+
+ ldy #$02
+ lda (sp),y
+ sta ptr1
+ iny
+ lda (sp),y
+ sta ptr1+1
+ ldy #DIR::fd+1
+ lda (ptr1),y
+ pha
+ dey
+ lda (ptr1),y
+ ldy #$02
+ sta (sp),y
+ pla
+ iny
+ sta (sp),y
+
+; Get count, save it again, clear the high byte, and call pfs_read().
+; By the previous actions, the stack frame is as pfs_read() needs it;
+; and, pfs_read() also will drop it.
+
+ pla
+ pha
+ ldx #>$0000
+ jsr _pfs_read
+
+; Check for errors.
+
+ cpx #>-1
+ beq L3
+
+; pfs_read() was successful; check number of bytes read. We assume that
+; pfs_read() will not return more than count; so, .X is zero if we come here.
+
+ sta tmp1 ; Save returned count
+ pla ; Our count
+ cmp tmp1
+ beq L2 ; OK, return count
+
+; Didn't read enough bytes. That is an error for us.
+
+ bne L1 ; Branch always
+
+; pfs_read() returned an error.
+
+L3: pla ; Drop count
+ inx ; .X = 0
+L1: txa ; Return zero
+L2: rts
+
+;---------------------------------------------------------------------------
+; void __fastcall__ pfs_closedir(struct cfs_dir *dirp);
+
+.proc _pfs_closedir
+ sta ptr1
+ stx ptr1+1
+
+; Load ((DIR *)dirp)->fd.
+
+ ldy #DIR::fd+1
+ lda (ptr1),y
+ tax
+ dey
+ lda (ptr1),y
+
+; Close the directory file.
+
+ jmp _pfs_close
+.endproc
diff --git a/platform/c64/lib/pfs-dir.c b/platform/c64/lib/pfs-dir.c
new file mode 100644
index 000000000..2b9d959f9
--- /dev/null
+++ b/platform/c64/lib/pfs-dir.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2016, Greg King
+ *
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 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 a part of the Contiki operating system.
+ */
+
+/*
+** Open a directory listing, so that it can be read by pfs_readdir().
+**
+** Read one file-name from a directory listing that was opened by pfs_opendir().
+**
+** 2012-05-30, Ullrich von Bassewitz
+** 2016-04-22, Greg King
+*/
+
+#include "cfs.h"
+
+typedef struct {
+ int fd; /* File descriptor for a directory */
+} DIR;
+
+/*---------------------------------------------------------------------------*/
+/*
+** Read characters from the directory into the supplied buffer.
+** Return true if the read was successful, and false otherwise.
+*/
+extern unsigned char __fastcall__ _pfs_dirread(struct cfs_dir *dir, void *buf,
+ unsigned char count);
+
+/*
+** Read one byte from the directory into the supplied buffer.
+** Return true if the read was successful, and false otherwise.
+*/
+extern unsigned char __fastcall__ _pfs_dirread1(struct cfs_dir *dir, void *buf);
+/*---------------------------------------------------------------------------*/
+int __fastcall__
+pfs_opendir(struct cfs_dir *dirp, register const char *name)
+{
+ static int fd;
+ static char buf[2 + 1] = "$";
+
+ /* Set up the actual file name that is sent to the DOS.
+ ** We accept "0:", "1:", "/", and "." as directory names.
+ */
+ if(name == NULL || name[0] == '\0' || (name[0] == '.' || name[0] == '/') && name[1] == '\0') {
+ buf[1] = '\0';
+ } else if((name[0] == '0' || name[0] == '1') && name[1] == ':' && name[2] == '\0') {
+ buf[1] = name[0];
+ buf[2] = '\0';
+ } else {
+ return -1;
+ }
+
+ /* Open the directory on a disk, for reading. */
+ fd = pfs_open(buf, CFS_READ);
+ if(fd >= 0) {
+ ((DIR *)dirp)->fd = fd;
+
+ /* Skip the load address. */
+ if(_pfs_dirread(dirp, buf + 1, 2)) {
+ return 0;
+ } else {
+ pfs_close(fd);
+ }
+ }
+
+ return -1;
+}
+/*---------------------------------------------------------------------------*/
+int __fastcall__
+pfs_readdir(struct cfs_dir *dirp, register struct cfs_dirent *dirent)
+{
+ register unsigned char *b;
+ register unsigned char i;
+ register unsigned char count;
+ unsigned char buffer[0x40];
+ static unsigned char s;
+ static unsigned char j;
+
+ /* Skip the BASIC line-link. */
+ if(!_pfs_dirread(dirp, buffer, 2)) {
+ return -1;
+ }
+
+ /* Read the number of blocks. It's a two-byte number; but, the size is
+ ** a four-byte number. Zero the size; then, put the block number in
+ ** the first two bytes. It works because the 6502 CPU's numbers are
+ ** little-endian.
+ */
+ dirent->size = 0;
+ if(!_pfs_dirread(dirp, &dirent->size, 2)) {
+ return -1;
+ }
+
+ /* Read the next file entry into a buffer. */
+ for(count = 0, b = buffer; count < sizeof(buffer); ++b) {
+ if(!_pfs_dirread1(dirp, b)) {
+ return -1;
+ }
+ ++count;
+ if(*b == '\0') {
+ break;
+ }
+ }
+
+ /* The end of the directory was reached if the buffer contains "blocks free."
+ ** It is sufficient here to check for the leading 'b'. The buffer will have
+ ** at least one byte if we come here.
+ */
+ if(buffer[0] == 'b') {
+ return -1;
+ }
+
+ /* Parse the buffer for the file-name. */
+ b = buffer;
+ j = 0;
+ s = 0;
+ i = 0;
+ while(i < count) {
+ switch(s) {
+ case 0:
+ /* Search for the start of the file-name. */
+ if(*b == '"') {
+ s = 1;
+ }
+ break;
+ case 1:
+ /* Within the file-name. */
+ if(*b == '"') {
+ /* The end of the file-name was found. */
+ dirent->name[j] = '\0';
+ return 0;
+ } else if(j < sizeof(dirent->name) - 1) {
+ dirent->name[j] = *b;
+ ++j;
+ }
+ break;
+ }
+ ++b;
+ ++i;
+ }
+
+ /* The file-name is too long for the buffer. Return what could be read. */
+ dirent->name[j] = '\0';
+ return 0;
+}
diff --git a/platform/c64/lib/pfs.S b/platform/c64/lib/pfs.S
index 49ef496ec..eae0838d4 100644
--- a/platform/c64/lib/pfs.S
+++ b/platform/c64/lib/pfs.S
@@ -36,7 +36,7 @@
.constructor init_pfs
.destructor done_pfs
- .importzp sp, ptr1, ptr2, ptr3
+ .importzp sp, ptr1, ptr2, ptr3, tmp1
.import curunit, __filetype, popax, addysp, subysp
.export pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend
.if F_IDE64
@@ -46,6 +46,7 @@
.export pfs_makename, pfs_scratch
.export _pfs_open, _pfs_read, _pfs_close
+
;---------------------------------------------------------------------
MAXLEN = 80 ;maximum filename length
@@ -107,7 +108,14 @@ _pfs_open:
lda FNL
beq error ;must have a filename
- lda #2 - 1 ;file number
+ ; A directory listing needs a special secondary address
+ ldy tmp1
+ bne open1 ;branch if not directory
+ lda #2 - 1
+ dey ;.Y = 0 - 1
+ bne open2 ;branch always
+
+open1: lda #2 - 1 ;file number
tay ;secondary address
open2: sta ptr2
sty ptr2 + 1
@@ -118,10 +126,6 @@ next: inc ptr2 ;next file number
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
@@ -209,7 +213,7 @@ pfs_makename:
; Validate the name; and, find its length
ldy #<-1
- sty ptr3
+ sty ptr3 ;init. the count of retries
sty ptr1
@L10: iny
cpy #MAXLEN
@@ -227,9 +231,17 @@ pfs_makename:
bne @L10
cpy #0
beq badchr ;no name
+ sty FNL ;save original length
tay ;zero index reg.
- lda #'0' ;drive 0 or current partition
+ lda (FN),y
+ sta tmp1 ;preset not-directory flag to true
+ cmp #'$'
+ bne @L9
+ sty tmp1 ;set not-directory flag to false
+ rts
+
+@L9: lda #'0' ;drive 0 or current partition
sta (sp),y
iny
inc ptr1
diff --git a/tools/apple2enh/prodos.po b/tools/apple2enh/prodos.po
index ed32e7a38..af35b8c45 100644
Binary files a/tools/apple2enh/prodos.po and b/tools/apple2enh/prodos.po differ