From ba2a9454177693e2e340d1196c96165c673ddfd9 Mon Sep 17 00:00:00 2001 From: uz Date: Sat, 16 Apr 2011 12:28:06 +0000 Subject: [PATCH] Changes by Greg King: Made cbm_readdir() report a disk's format-code and more file-access modes. Added more definitions to for cbm_readdir(). And, improved the header's comments. Added some ASCII-to-PetSCII character-mappings. git-svn-id: svn://svn.cc65.org/cc65/trunk@4986 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- include/cbm.h | 231 ++++++++++++++++++++++++------------------- libsrc/cbm/cbm_dir.c | 141 +++++++++++++++----------- 2 files changed, 214 insertions(+), 158 deletions(-) diff --git a/include/cbm.h b/include/cbm.h index dba955100..f9cf117c3 100644 --- a/include/cbm.h +++ b/include/cbm.h @@ -2,14 +2,14 @@ /* */ /* cbm.h */ /* */ -/* CBM system specific definitions */ +/* CBM system-specific definitions */ /* */ /* */ /* */ -/* (C) 1998-2004 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (c) 1998-2011, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -40,27 +40,33 @@ /* Check for errors */ #if !defined(__CBM__) -# error This module may only be used when compiling for CBM machines! +# error This module may be used only when compiling for CBM machines! #endif -/* Load the system specific files here, if needed */ -#if defined(__C64__) && !defined(_C64_H) +/* We need NULL. */ + +#if !defined(_STDDEF_H) +# include +#endif + +/* Load the system-specific files here, if needed. */ +#if defined(__C64__) && !defined(_C64_H) # include -#elif defined(__VIC20__) && !defined(_VIC20_H) +#elif defined(__VIC20__) && !defined(_VIC20_H) # include -#elif defined(__C128__) && !defined(_C128_H) +#elif defined(__C128__) && !defined(_C128_H) # include -#elif defined(__PLUS4__) && !defined(_PLUS4_H) +#elif defined(__PLUS4__) && !defined(_PLUS4_H) # include -#elif defined(__C16__) && !defined(_C16_H) +#elif defined(__C16__) && !defined(_C16_H) # include #elif defined(__CBM510__) && !defined(_CBM510_H) # include #elif defined(__CBM610__) && !defined(_CBM610_H) # include -#elif defined(__PET__) && !defined(_PET_H) +#elif defined(__PET__) && !defined(_PET_H) # include #endif @@ -75,38 +81,56 @@ /* The file stream implementation and the POSIX I/O functions will use the * following variables to determine the file type and the disk unit to use. */ -extern unsigned char _curunit; /* Default 8 */ -extern unsigned char _filetype; /* Default 'u' */ +extern unsigned char _curunit; /* Defaults to current when program started */ +extern char _filetype; /* Defaults to 'u' */ /*****************************************************************************/ -/* Characters codes (CBM charset) */ +/* Character-codes (CBM charset) */ /*****************************************************************************/ -#define CH_HLINE 96 -#define CH_VLINE 125 -#define CH_ULCORNER 176 -#define CH_URCORNER 174 -#define CH_LLCORNER 173 -#define CH_LRCORNER 189 -#define CH_TTEE 178 -#define CH_RTEE 179 -#define CH_BTEE 177 -#define CH_LTEE 171 -#define CH_CROSS 123 -#define CH_CURS_UP 145 -#define CH_CURS_DOWN 17 -#define CH_CURS_LEFT 157 -#define CH_CURS_RIGHT 29 -#define CH_PI 126 -#define CH_DEL 20 -#define CH_INS 148 -#define CH_ENTER 13 -#define CH_STOP 3 -#define CH_ESC 27 +#ifdef __CC65__ +/* ASCII-to-PetSCII character-map translations: + * These lines convert characters that are not in CBM's character-set + * into codes with shapes that resemble the ASCII shapes. + */ +#pragma charmap(0x5c,0xbf) /* '\\' */ +#pragma charmap(0x5f,0xa4) /* '_' thinner than built-in one */ +#pragma charmap(0x60,0xad) /* '`' */ +#pragma charmap(0x7b,0xb3) /* '{' */ +#pragma charmap(0x7c,0xdd) /* '|' "official" PetSCII code */ +#pragma charmap(0x7d,0xab) /* '}' */ +#pragma charmap(0x7e,0xb1) /* '~' */ +#endif + + + +#define CH_HLINE 192 +#define CH_VLINE 221 +#define CH_ULCORNER 176 +#define CH_URCORNER 174 +#define CH_LLCORNER 173 +#define CH_LRCORNER 189 +#define CH_TTEE 178 +#define CH_BTEE 177 +#define CH_LTEE 171 +#define CH_RTEE 179 +#define CH_CROSS 219 +#define CH_CURS_UP 145 +#define CH_CURS_DOWN 17 +#define CH_CURS_LEFT 157 +#define CH_CURS_RIGHT 29 +#define CH_PI 222 +#define CH_HOME 19 +#define CH_DEL 20 +#define CH_INS 148 +#define CH_ENTER 13 +#define CH_STOP 3 +#define CH_LIRA 92 +#define CH_ESC 27 @@ -117,25 +141,26 @@ extern unsigned char _filetype; /* Default 'u' */ /* CBM FILE TYPES */ -#define CBM_T_DEL 0 -#define CBM_T_SEQ 1 -#define CBM_T_PRG 2 -#define CBM_T_USR 3 -#define CBM_T_REL 4 -#define CBM_T_CBM 5 /* 1581 sub-partition */ -#define CBM_T_DIR 6 /* IDE64 and CMD sub-directory */ -#define CBM_T_RESERVED 7 /* Not used, but kept free for compatibility */ -#define CBM_T_VRP 8 /* Vorpal fast-loadable format */ -#define CBM_T_OTHER 9 /* Other file-types not yet defined */ -#define CBM_T_HEADER 10 /* Disk header / title */ +#define CBM_T_DEL 0 +#define CBM_T_SEQ 1 +#define CBM_T_PRG 2 +#define CBM_T_USR 3 +#define CBM_T_REL 4 +#define CBM_T_CBM 5 /* 1581 sub-partition */ +#define CBM_T_DIR 6 /* IDE64 and CMD sub-directory */ +#define CBM_T_LNK 7 /* IDE64 soft-link */ +#define CBM_T_VRP 8 /* Vorpal fast-loadable format */ +#define CBM_T_OTHER 9 /* File-type not recognized */ +#define CBM_T_HEADER 10 /* Disk header / title */ /* CBM FILE ACCESS */ #define CBM_A_RO 1 /* Read only */ +#define CBM_A_WO 2 /* Write only */ #define CBM_A_RW 3 /* Read, Write */ struct cbm_dirent { - char name[17]; /* File name in PETSCII, limited to 16 chars */ - unsigned int size; /* Size in 256B blocks */ + char name[17]; /* File name in PetSCII, limited to 16 chars */ + unsigned int size; /* Size, in 254-/256-byte blocks */ unsigned char type; unsigned char access; }; @@ -163,28 +188,31 @@ unsigned char __fastcall__ get_tv (void); -/* Constants to use with cbm_open() for opening a file for reading or +/* Constants to use with cbm_open() for openning a file for reading or * writing without the need to append ",r" or ",w" to the filename. * - * e.g.: cbm_open(2, 8, CBM_READ, "data,s"); + * e.g., cbm_open(2, 8, CBM_READ, "0:data,s"); */ -#define CBM_READ 0 -#define CBM_WRITE 1 +#define CBM_READ 0 /* default is ",p" */ +#define CBM_WRITE 1 /* ditto */ +#define CBM_SEQ 2 /* default is ",r" -- or ",s" when writing */ -/* Kernel level functions */ +/* Kernal-level functions */ void __fastcall__ cbm_k_setlfs (unsigned char LFN, unsigned char DEV, unsigned char SA); void __fastcall__ cbm_k_setnam (const char* Name); unsigned int __fastcall__ cbm_k_load(unsigned char flag, unsigned addr); unsigned char __fastcall__ cbm_k_save(unsigned int start, unsigned int end); -unsigned char __fastcall__ cbm_k_open (void); +unsigned char cbm_k_open (void); void __fastcall__ cbm_k_close (unsigned char FN); -unsigned char __fastcall__ cbm_k_readst (void); +signed char cbm_k_readst (void); unsigned char __fastcall__ cbm_k_chkin (unsigned char FN); unsigned char __fastcall__ cbm_k_ckout (unsigned char FN); -unsigned char __fastcall__ cbm_k_basin (void); +unsigned char cbm_k_basin (void); +unsigned char cbm_k_getin (void); void __fastcall__ cbm_k_bsout (unsigned char C); -void __fastcall__ cbm_k_clrch (void); +void cbm_k_clrch (void); +void cbm_clall (void); @@ -194,79 +222,82 @@ void __fastcall__ cbm_k_clrch (void); -/* All cbm_* IO functions set _oserror (see errno.h) in case of an - * error. +/* The cbm_* I/O functions below set _oserror (see errno.h), + * in case of an error. + * + * error-code BASIC error + * ---------- ----------- + * 1 = too many files + * 2 = file open + * 3 = file not open + * 4 = file not found + * 5 = device not present + * 6 = not input-file + * 7 = not output-file + * 8 = missing file-name + * 9 = illegal device-number * - * errorcode BASIC error - * 1 = too many files - * 2 = file open - * 3 = file not open - * 4 = file not found - * 5 = device not present - * 6 = not input file - * 7 = not output file - * 8 = missing filename - * 9 = illegal device number + * 10 = STOP-key pushed + * 11 = general I/O-error */ unsigned int cbm_load (const char* name, unsigned char device, void* data); -/* Loads file "name" from given device to given address or to the load +/* Loads file "name", from given device, to given address -- or, to the load * address of the file if "data" is the null pointer (like load"name",8,1 * in BASIC). - * Returns number of bytes that where loaded if loading was successful - * otherwise 0. "_oserror" contains an errorcode then (see table below). + * Returns number of bytes that were loaded if loading was successful; + * otherwise 0, "_oserror" contains an error-code, then (see table above). */ -unsigned char __fastcall__ cbm_save (const char* name, - unsigned char device, - const void* data, - unsigned int size); -/* Saves "size" bytes starting at "data" to a file. - * Returns 0 if saving was successful, otherwise an errorcode (see table - * below). +unsigned char __fastcall__ cbm_save (const char* name, unsigned char device, + const void* addr, unsigned int size); +/* Saves "size" bytes, starting at "addr", to a file. + * Returns 0 if saving was successful, otherwise an error-code (see table + * above). */ -unsigned char __fastcall__ cbm_open (unsigned char lfn, - unsigned char device, - unsigned char sec_addr, - const char* name); +unsigned char __fastcall__ cbm_open (unsigned char lfn, unsigned char device, + unsigned char sec_addr, const char* name); /* Opens a file. Works just like the BASIC command. - * Returns 0 if opening was successful, otherwise an errorcode (see table - * below). + * Returns 0 if openning was successful, otherwise an error-code (see table + * above). */ void __fastcall__ cbm_close (unsigned char lfn); /* Closes a file */ int __fastcall__ cbm_read (unsigned char lfn, void* buffer, unsigned int size); -/* Reads up to "size" bytes from a file to "buffer". - * Returns the number of actually read bytes, 0 if there are no bytes left - * (EOF) or -1 in case of an error. _oserror contains an errorcode then (see - * table below). +/* Reads up to "size" bytes from a file into "buffer". + * Returns the number of actually-read bytes, 0 if there are no bytes left. + * -1 in case of an error; then, _oserror contains an error-code (see table + * above). (Remember: 0 means end-of-file; -1 means error.) */ -int __fastcall__ cbm_write (unsigned char lfn, void* buffer, unsigned int size); +int __fastcall__ cbm_write (unsigned char lfn, const void* buffer, + unsigned int size); /* Writes up to "size" bytes from "buffer" to a file. - * Returns the number of actually written bytes or -1 in case of an error. - * _oserror contains an errorcode then (see above table). + * Returns the number of actually-written bytes, or -1 in case of an error; + * _oserror contains an error-code, then (see above table). */ unsigned char __fastcall__ cbm_opendir (unsigned char lfn, unsigned char device); /* Opens directory listing. - * Returns 0 if opening directory was successful, - * othervise errorcode corresponding to cbm_open() + * Returns 0 if openning directory was successful; + * otherwise, an error-code corresponding to cbm_open(). */ -unsigned char __fastcall__ cbm_readdir (unsigned char lfn, struct cbm_dirent* l_dirent); +unsigned char __fastcall__ cbm_readdir (unsigned char lfn, + struct cbm_dirent* l_dirent); /* Reads one directory line into cbm_dirent structure. - * Returns 0 if reading directory line was successful. - * Returns 'true' if reading directory failed or no more files to read. + * Returns 0 if reading directory-line was successful. + * Returns non-zero if reading directory failed, or no more file-names to read. + * Returns 2 on last line. Then, l_dirent->size = the number of "blocks free." */ void __fastcall__ cbm_closedir (unsigned char lfn); -/* Closes directory by cbm_close (unsigned char lfn) */ +/* Closes directory by cbm_close(lfn) */ diff --git a/libsrc/cbm/cbm_dir.c b/libsrc/cbm/cbm_dir.c index e27813d25..0b97e9803 100644 --- a/libsrc/cbm/cbm_dir.c +++ b/libsrc/cbm/cbm_dir.c @@ -1,94 +1,99 @@ -/* This is very simplified version of POSIX opendir(), readdir() and closedir() */ -/* for Commodore computers. */ -/* Created by Josef Soucek, 2003 E-mail:josef.soucek@ct.cz */ +/* This is a very simplified version of the POSIX opendir(), */ +/* readdir(), and closedir() -- for Commodore computers. */ +/* Created by Josef Soucek, 2003. E-mail: josef.soucek@ct.cz */ -/* Version 0.1 - 21.1.2003 */ -/* Tested with floppy drive and IDE64 devices */ -/* Not tested with messed (buggy) directory listing */ -/* Limits filenames to 16 chars (VICE supports more in directory listing) */ +/* 2003-01-21 -- Version 0.1 */ +/* 2009-10-10 -- Version 0.3 */ +/* 2011-04-07 -- Version 0.4, groepaz */ +/* 2011-04-14 -- Version 0.5, Greg King */ +/* Tested with floppy-drive and IDE64 devices. */ +/* Not tested with messed (buggy) directory listings. */ +/* Limits filenames to 16 chars. (VICE supports more */ +/* in directory listings). */ #include +#include +/* Opens directory listing. +** Returns 0 if openning directory was successful; +** otherwise, an error-code corresponding to cbm_open(). +*/ unsigned char __fastcall__ cbm_opendir (unsigned char lfn, unsigned char device) { - unsigned char status; - if ((status = cbm_open (lfn, device, CBM_READ, "$")) == 0) { - if (cbm_k_chkin (lfn) == 0) { + if (cbm_open (lfn, device, CBM_READ, "$") == 0) { + if ((_oserror = cbm_k_chkin (lfn)) == 0) { /* Ignore start address */ cbm_k_basin(); cbm_k_basin(); + cbm_k_clrch(); if (cbm_k_readst()) { cbm_close(lfn); - status = 2; - cbm_k_clrch(); - } else { - status = 0; - cbm_k_clrch(); + _oserror = 4; /* directory cannot be read */ } } } - return status; + return _oserror; } +/* Reads one directory line into cbm_dirent structure. +** Returns 0 if reading directory-line was successful. +** Returns non-zero if reading directory failed, or no more file-names to read. +** Returns 2 on last line. Then, l_dirent->size = the number of "blocks free." +*/ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_dirent* l_dirent) { - unsigned char byte, i; - unsigned char rv; - unsigned char is_header; + unsigned char byte, i = 0; + unsigned char is_header = 0; + unsigned char rv = 1; static const unsigned char types[] = { - CBM_T_OTHER, CBM_T_OTHER, CBM_T_CBM, CBM_T_DEL, /* a b c d */ - CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, /* e f g h */ - CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, /* i j k l */ - CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, CBM_T_PRG, /* m n o p */ - CBM_T_OTHER, CBM_T_REL, CBM_T_SEQ, CBM_T_OTHER, /* q r s t */ - CBM_T_USR, CBM_T_VRP /* u v */ + 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 */ }; - rv = 1; - is_header = 0; - if (!cbm_k_chkin(lfn)) { if (!cbm_k_readst()) { - /* skip 2 bytes, next basic line pointer */ + /* skip 2 bytes, next-BASIC-line pointer */ cbm_k_basin(); cbm_k_basin(); - /* File-size */ - l_dirent->size = cbm_k_basin() | ((cbm_k_basin()) << 8); + /* File-size or drive/partition number */ + l_dirent->size = cbm_k_basin() | (cbm_k_basin() << 8); byte = cbm_k_basin(); + switch (byte) { - /* "B" BLOCKS FREE. */ - if (byte == 'b') { - /* Read until end, careless callers may call us again */ + /* "B" BLOCKS FREE. */ + case 'b': + /* Read until end; careless callers might call us again. */ while (!cbm_k_readst()) { cbm_k_basin(); } rv = 2; /* EOF */ goto ret_val; - } - /* reverse text shows that this is the directory header */ - if (byte == 0x12) { /* RVS_ON */ + /* Reverse-text shows when this is the directory header. */ + case 0x12: /* RVS_ON */ is_header = 1; } while (byte != '\"') { - byte = cbm_k_basin(); /* prevent endless loop */ if (cbm_k_readst()) { rv = 3; goto ret_val; } + byte = cbm_k_basin(); } - i = 0; while ((byte = cbm_k_basin()) != '\"') { /* prevent endless loop */ if (cbm_k_readst()) { @@ -103,41 +108,60 @@ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_d } l_dirent->name[i] = '\0'; - while ((byte = cbm_k_basin()) == ' ') { - /* prevent endless loop */ - if (cbm_k_readst()) { - rv = 5; - goto ret_val; - } - } - if (is_header) { l_dirent->type = CBM_T_HEADER; + + /* Get the disk-format code. */ + i = 6; + do { + l_dirent->access = byte = cbm_k_basin(); + } while (--i != 0); + } else { - if (byte >= 'a' && byte < 'a' + sizeof(types)) { - l_dirent->type = types[byte - 'a']; + /* Go to the file-type column. */ + while ((byte = cbm_k_basin()) == ' ') { + /* prevent endless loop */ + if (cbm_k_readst()) { + rv = 5; + goto ret_val; + } + } + + l_dirent->access = CBM_A_RW; + + /* "Splat" files shouldn't be read. */ + if (byte == '*') { + l_dirent->access = CBM_A_WO; + byte = cbm_k_basin(); + } + + if (byte >= 'c' && byte < 'c' + sizeof types) { + l_dirent->type = types[byte - 'c']; } else { l_dirent->type = CBM_T_OTHER; } - if ((cbm_k_basin() == 'i') && (l_dirent->type == CBM_T_DEL)) { - l_dirent->type = CBM_T_DIR; - } + /* Notice whether it's a directory or a deleted file. */ + if (cbm_k_basin() == 'i' && byte == 'd') { + l_dirent->type = CBM_T_DIR; + } cbm_k_basin(); - byte = cbm_k_basin(); - - l_dirent->access = (byte == 0x3C)? CBM_A_RO : CBM_A_RW; + /* Locked files shouldn't be written. */ + if ((byte = cbm_k_basin()) == '<') { + l_dirent->access = (l_dirent->access == CBM_A_WO) + ? 0 : CBM_A_RO; + } } - /* read to end of line */ + /* Read to the end of the line. */ while (byte != 0) { - byte = cbm_k_basin(); /* prevent endless loop */ if (cbm_k_readst()) { rv = 6; goto ret_val; } + byte = cbm_k_basin(); } rv = 0; @@ -151,7 +175,8 @@ ret_val: } -void __fastcall__ cbm_closedir( unsigned char lfn) + +void __fastcall__ cbm_closedir (unsigned char lfn) { cbm_close(lfn); } -- 2.39.5