--- /dev/null
+;
+; Definitions for CBM file types. From cbm.h
+;
+; Ullrich von Bassewitz, 2012-06-03
+;
+
+; Define bitmapped constants for the table entries
+
+.enum
+ CBM_T_DEL ; Deleted file
+ CBM_T_SEQ ; Sequential file
+ CBM_T_PRG ; Program file
+ CBM_T_USR ; User file
+ CBM_T_REL ; Relative file
+ CBM_T_CBM ; 1581 sub-partition
+ CBM_T_DIR ; IDE64 and CMD sub-directory
+ CBM_T_LNK ; IDE64 soft-link
+ CBM_T_VRP ; Vorpal fast-loadable format
+ CBM_T_OTHER ; File-type not recognized
+ CBM_T_HEADER ; Disk header / title
+.endenum
+
+
+; The following function maps the start character for a file type to
+; one of the file types above. Note: 'd' will always mapped to CBM_T_DEL.
+; The calling function has to look at the following character to determine
+; if the file type is actually CBM_T_DIR.
+;
+; unsigned char __fastcall__ _cbm_filetype (unsigned char c);
+
+ .global __cbm_filetype
+
+
/* */
/* */
/* */
-/* (C) 1998-2011, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#define CH_LIRA 92
#define CH_ESC 27
-
+
/*****************************************************************************/
/* Definitions for directory reading functions */
unsigned char access;
};
+unsigned char __fastcall__ _cbm_filetype (unsigned char c);
+/* Map the start character for a file type to one of the file types above.
+ * Note: 'd' will always mapped to CBM_T_DEL. The calling function has to
+ * look at the following character to determine if the file type is actually
+ * CBM_T_DIR.
+ * This is a function used by the implementation. There is usually no need
+ * to call it from user code.
+ */
/*****************************************************************************/
struct dirent {
char d_name[16+1];
unsigned int d_off;
- unsigned int d_reclen;
+ unsigned int d_blocks;
unsigned char d_type;
-
+
/* bsd extensions */
unsigned char d_namlen;
};
C_OBJS = cbm_dir.o \
cbm_load.o \
cbm_save.o \
- opendir.o
+ opendir.o \
+ readdir.o
S_OBJS = c_acptr.o \
c_basin.o \
c_unlsn.o \
c_untlk.o \
cbm_close.o \
+ cbm_ftype.o \
cbm_open.o \
cbm_read.o \
cbm_write.o \
unsigned char byte, i = 0;
unsigned char is_header = 0;
unsigned char rv = 1;
- static const unsigned char types[] = {
- CBM_T_CBM, CBM_T_DEL, CBM_T_OTHER, CBM_T_OTHER, /* c d e f */
- CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, /* g h i j */
- CBM_T_OTHER, CBM_T_LNK, CBM_T_OTHER, CBM_T_OTHER, /* k l m n */
- CBM_T_OTHER, CBM_T_PRG, CBM_T_OTHER, CBM_T_REL, /* o p q r */
- CBM_T_SEQ, CBM_T_OTHER, CBM_T_USR, CBM_T_VRP /* s t u v */
- };
if (!cbm_k_chkin(lfn)) {
if (!cbm_k_readst()) {
byte = cbm_k_basin();
}
- if (byte >= 'c' && byte < 'c' + sizeof types) {
- l_dirent->type = types[byte - 'c'];
- } else {
- l_dirent->type = CBM_T_OTHER;
- }
+ /* Determine the file type */
+ l_dirent->type = _cbm_filetype (byte);
/* Notice whether it's a directory or a deleted file. */
if (cbm_k_basin() == 'i' && byte == 'd') {
--- /dev/null
+;
+; Determine the CBM file type. From cbm_dir.c by Josef Soucek. Moved into an
+; assembler function by Ullrich von Bassewitz 2012-06-03
+;
+; unsigned char __fastcall__ _cbm_filetype (unsigned char c);
+;
+
+ .include "cbm_ftype.inc"
+
+ .macpack generic
+
+
+; --------------------------------------------------------------------------
+; Table with types for a list of start characters
+
+.rodata
+.proc TypeTable
+ .byte CBM_T_CBM ; c
+ .byte CBM_T_DEL ; d
+ .byte CBM_T_OTHER ; e
+ .byte CBM_T_OTHER ; f
+ .byte CBM_T_OTHER ; g
+ .byte CBM_T_OTHER ; h
+ .byte CBM_T_OTHER ; i
+ .byte CBM_T_OTHER ; j
+ .byte CBM_T_OTHER ; k
+ .byte CBM_T_LNK ; l
+ .byte CBM_T_OTHER ; m
+ .byte CBM_T_OTHER ; n
+ .byte CBM_T_OTHER ; o
+ .byte CBM_T_PRG ; p
+ .byte CBM_T_OTHER ; q
+ .byte CBM_T_REL ; r
+ .byte CBM_T_SEQ ; s
+ .byte CBM_T_OTHER ; t
+ .byte CBM_T_USR ; u
+ .byte CBM_T_VRP ; v
+.endproc
+
+
+; --------------------------------------------------------------------------
+; Mapper function
+
+.code
+.proc __cbm_filetype
+
+ ldx #0 ; Clear high byte
+
+; Check that the given char is in table range
+
+ sec
+ sbc #'c'
+ bcc L1
+ cmp #.sizeof (TypeTable)
+ bge L1
+
+; Ok, load the type
+
+ tay
+ lda TypeTable,y
+ rts
+
+; Out of table range, return CBM_T_OTHER
+
+L1: lda #CBM_T_OTHER
+ rts
+
+.endproc
+
+
+
struct DIR {
int fd; /* File descriptor for directory */
- unsigned offs; /* Current byte offset in directory */
+ unsigned off; /* Current byte offset in directory */
char name[16+1]; /* Name passed to opendir */
};
/* Setup file name and offset */
d.name[0] = '$';
d.name[1] = '\0';
- d.offs = 0;
+ d.off = 0;
/* Open the directory on disk for reading */
d.fd = open (d.name, O_RDONLY);
--- /dev/null
+/*
+ * Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz.
+ */
+
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <cbm.h>
+#include "dir.h"
+
+#include <stdio.h>
+
+
+struct dirent* __fastcall__ readdir (register DIR* dir)
+{
+ static struct dirent entry;
+ register unsigned char* b;
+ register unsigned char i;
+ unsigned char count;
+ unsigned char j;
+ unsigned char s;
+ unsigned char buffer[0x40];
+
+
+ /* Remember the directory offset for this entry */
+ entry.d_off = dir->off;
+
+ /* Skip the basic line-link */
+ if (!_dirskip (2, dir)) {
+ /* errno already set */
+ goto exit;
+ }
+ dir->off += 2;
+
+ /* Read the number of blocks */
+ if (read (dir->fd, &entry.d_blocks, sizeof (entry.d_blocks)) !=
+ sizeof (entry.d_blocks)) {
+ goto error;
+ }
+
+ /* Read the next file entry into the buffer */
+ for (count = 0, b = buffer; count < sizeof (buffer); ++count, ++b) {
+ if (read (dir->fd, b, 1) != 1) {
+ /* ### Check for EOF */
+ goto error;
+ }
+ if (*b == '\0') {
+ break;
+ }
+ }
+
+ /* End of directory is reached if the buffer contains "blocks free". It is
+ * sufficient here to check for the leading 'b'. To avoid problems if we're
+ * called again, read until end of directory.
+ */
+ if (count > 0 && buffer[0] == 'b') {
+ while (read (dir->fd, buffer, 1) == 1) ;
+ return 0;
+ }
+
+ /* Bump the directory offset */
+ dir->off += count;
+
+ /* Parse the buffer for the filename and file type */
+ i = 0;
+ j = 0;
+ s = 0;
+ b = buffer;
+ while (i < count) {
+ switch (s) {
+
+ case 0:
+ /* Searching for start of file name */
+ if (*b == '"') {
+ s = 1;
+ }
+ break;
+
+ case 1:
+ /* Within file name */
+ if (*b == '"') {
+ entry.d_name[j] = '\0';
+ entry.d_namlen = j;
+ s = 2;
+ } else if (j < sizeof (entry.d_name) - 1) {
+ entry.d_name[j] = *b;
+ ++j;
+ }
+ break;
+
+ case 2:
+ /* Searching for file type */
+ if (*b != ' ') {
+ entry.d_type = _cbm_filetype (*b);
+ if (*b == 'd') {
+ /* May be DEL or DIR, check next char */
+ s = 3;
+ } else {
+ /* Done */
+ return &entry;
+ }
+ }
+ break;
+
+ case 3:
+ /* Distinguish DEL or DIR file type entries */
+ switch (*b) {
+ case 'e': break;
+ case 'i': entry.d_type = CBM_T_DIR; break;
+ default: entry.d_type = CBM_T_OTHER; break;
+ }
+ return &entry;
+ }
+ ++i;
+ ++b;
+ }
+
+ /* Something went wrong - terminating quote not found */
+error:
+ _errno = EIO;
+exit:
+ return 0;
+}
+
+
+