--- Frodo4/Src/1541t64.cpp 2003/07/01 17:51:17 1.2 +++ Frodo4/Src/1541t64.cpp 2004/01/11 00:09:51 1.3 @@ -43,20 +43,6 @@ #include "Prefs.h" -// Access modes -enum { - FMODE_READ, FMODE_WRITE, FMODE_APPEND -}; - -// File types -enum { - FTYPE_PRG, FTYPE_SEQ, FTYPE_USR, FTYPE_REL -}; - -// Prototypes -static bool match(char *p, char *n); - - /* * Constructor: Prepare emulation */ @@ -145,7 +131,7 @@ bool T64Drive::parse_t64_file(void) { uint8 buf[32]; uint8 *buf2; - char *p; + uint8 *p; int max, i, j; // Read header and get maximum number of files contained @@ -260,13 +246,13 @@ bool T64Drive::parse_lynx_file(void) * Open channel */ -uint8 T64Drive::Open(int channel, char *filename) +uint8 T64Drive::Open(int channel, const uint8 *name, int name_len) { set_error(ERR_OK); // Channel 15: Execute file name as command if (channel == 15) { - execute_command(filename); + execute_cmd(name, name_len); return ST_OK; } @@ -276,7 +262,7 @@ uint8 T64Drive::Open(int channel, char * file[channel] = NULL; } - if (filename[0] == '#') { + if (name[0] == '#') { set_error(ERR_NOCHANNEL); return ST_OK; } @@ -286,10 +272,10 @@ uint8 T64Drive::Open(int channel, char * return ST_OK; } - if (filename[0] == '$') - return open_directory(channel, filename+1); + if (name[0] == '$') + return open_directory(channel, name + 1, name_len - 1); - return open_file(channel, filename); + return open_file(channel, name, name_len); } @@ -297,33 +283,45 @@ uint8 T64Drive::Open(int channel, char * * Open file */ -uint8 T64Drive::open_file(int channel, char *filename) +uint8 T64Drive::open_file(int channel, const uint8 *name, int name_len) { - char plainname[NAMEBUF_LENGTH]; - int filemode = FMODE_READ; - int filetype = FTYPE_PRG; - int num; - - convert_filename(filename, plainname, &filemode, &filetype); - - // Channel 0 is READ PRG, channel 1 is WRITE PRG - if (!channel) { - filemode = FMODE_READ; - filetype = FTYPE_PRG; - } - if (channel == 1) { - filemode = FMODE_WRITE; - filetype = FTYPE_PRG; + uint8 plain_name[NAMEBUF_LENGTH]; + int plain_name_len; + int mode = FMODE_READ; + int type = FTYPE_PRG; + int rec_len; + parse_file_name(name, name_len, plain_name, plain_name_len, mode, type, rec_len); + + // Channel 0 is READ, channel 1 is WRITE + if (channel == 0 || channel == 1) { + mode = channel ? FMODE_WRITE : FMODE_READ; + if (type == FTYPE_DEL) + type = FTYPE_PRG; + } + + bool writing = (mode == FMODE_WRITE || mode == FMODE_APPEND); + + // Wildcards are only allowed on reading + if (writing && (strchr((const char *)plain_name, '*') || strchr((const char *)plain_name, '?'))) { + set_error(ERR_SYNTAX33); + return ST_OK; } // Allow only read accesses - if (filemode != FMODE_READ) { + if (writing) { set_error(ERR_WRITEPROTECT); return ST_OK; } + // Relative files are not supported + if (type == FTYPE_REL) { + set_error(ERR_UNIMPLEMENTED); + return ST_OK; + } + // Find file - if (find_first_file(plainname, filetype, &num)) { + int num; + if (find_first_file(plain_name, plain_name_len, num)) { // Open temporary file if ((file[channel] = tmpfile()) != NULL) { @@ -342,7 +340,7 @@ uint8 T64Drive::open_file(int channel, c rewind(file[channel]); delete[] buf; - if (filemode == FMODE_READ) // Read and buffer first byte + if (mode == FMODE_READ) // Read and buffer first byte read_char[channel] = fgetc(file[channel]); } } else @@ -353,89 +351,31 @@ uint8 T64Drive::open_file(int channel, c /* - * Analyze file name, get access mode and type - */ - -void T64Drive::convert_filename(char *srcname, char *destname, int *filemode, int *filetype) -{ - char *p; - - // Search for ':', p points to first character after ':' - if ((p = strchr(srcname, ':')) != NULL) - p++; - else - p = srcname; - - // Remaining string -> destname - strncpy(destname, p, NAMEBUF_LENGTH); - - // Search for ',' - p = destname; - while (*p && (*p != ',')) p++; - - // Look for mode parameters seperated by ',' - p = destname; - while ((p = strchr(p, ',')) != NULL) { - - // Cut string after the first ',' - *p++ = 0; - - switch (*p) { - case 'P': - *filetype = FTYPE_PRG; - break; - case 'S': - *filetype = FTYPE_SEQ; - break; - case 'U': - *filetype = FTYPE_USR; - break; - case 'L': - *filetype = FTYPE_REL; - break; - case 'R': - *filemode = FMODE_READ; - break; - case 'W': - *filemode = FMODE_WRITE; - break; - case 'A': - *filemode = FMODE_APPEND; - break; - } - } -} - - -/* * Find first file matching wildcard pattern */ // Return true if name 'n' matches pattern 'p' -static bool match(char *p, char *n) +static bool match(const uint8 *p, int p_len, const uint8 *n) { - if (!*p) // Null pattern matches everything - return true; - - do { + while (p_len-- > 0) { if (*p == '*') // Wildcard '*' matches all following characters return true; if ((*p != *n) && (*p != '?')) // Wildcard '?' matches single character return false; p++; n++; - } while (*p); + } - return !(*n); + return *n == 0; } -bool T64Drive::find_first_file(char *name, int type, int *num) +bool T64Drive::find_first_file(const uint8 *pattern, int pattern_len, int &num) { - for (int i=0; i> 8) & 0xff; + int n = (file_info[num].length + 254) / 254; + *p++ = n & 0xff; + *p++ = (n >> 8) & 0xff; p++; - if (i < 10) p++; // Less than 10: add one space - if (i < 100) p++; // Less than 100: add another space + if (n < 10) p++; // Less than 10: add one space + if (n < 100) p++; // Less than 100: add another space // Convert and insert file name - strcpy(str, file_info[num].name); + uint8 str[NAMEBUF_LENGTH]; + memcpy(str, file_info[num].name, 17); *p++ = '\"'; - q = p; - for (i=0; i<16 && str[i]; i++) + uint8 *q = p; + for (int i=0; i<16 && str[i]; i++) *q++ = str[i]; *q++ = '\"'; p += 18; @@ -623,15 +563,14 @@ uint8 T64Drive::Write(int channel, uint8 { // Channel 15: Collect chars and execute command on EOI if (channel == 15) { - if (cmd_len >= 40) + if (cmd_len >= 58) return ST_TIMEOUT; - cmd_buffer[cmd_len++] = byte; + cmd_buf[cmd_len++] = byte; if (eoi) { - cmd_buffer[cmd_len] = 0; + execute_cmd(cmd_buf, cmd_len); cmd_len = 0; - execute_command(cmd_buffer); } return ST_OK; } @@ -646,59 +585,39 @@ uint8 T64Drive::Write(int channel, uint8 /* - * Execute command string + * Execute drive commands */ -void T64Drive::execute_command(char *command) +// RENAME:new=old +// ^ ^ +// new_file old_file +void T64Drive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len) { - switch (command[0]) { - case 'I': - close_all_channels(); - set_error(ERR_OK); - break; - - case 'U': - if ((command[1] & 0x0f) == 0x0a) { - Reset(); - } else - set_error(ERR_SYNTAX30); - break; - - case 'G': - if (command[1] != ':') - set_error(ERR_SYNTAX30); - else - cht64_cmd(&command[2]); - break; - - default: - set_error(ERR_SYNTAX30); + // Check if destination file is already present + int num; + if (find_first_file(new_file, new_file_len, num)) { + set_error(ERR_FILEEXISTS); + return; } -} + // Check if source file is present + if (!find_first_file(old_file, old_file_len, num)) { + set_error(ERR_FILENOTFOUND); + return; + } -/* - * Execute 'G' command - */ + set_error(ERR_WRITEPROTECT); +} -void T64Drive::cht64_cmd(char *t64name) +// INITIALIZE +void T64Drive::initialize_cmd(void) { - char str[NAMEBUF_LENGTH]; - char *p = str; - - // Convert .t64 file name - for (int i=0; iASCII - */ - -uint8 T64Drive::conv_from_64(uint8 c, bool map_slash) -{ - if ((c >= 'A') && (c <= 'Z') || (c >= 'a') && (c <= 'z')) - return c ^ 0x20; - if ((c >= 0xc1) && (c <= 0xda)) - return c ^ 0x80; - if ((c == '/') && map_slash && ThePrefs.MapSlash) - return '\\'; - return c; -}