ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/1541fs.cpp
(Generate patch)

Comparing Frodo4/Src/1541fs.cpp (file contents):
Revision 1.3 by cebix, 2003-07-09T13:54:22Z vs.
Revision 1.9 by cebix, 2005-06-27T19:55:48Z

# Line 1 | Line 1
1   /*
2   *  1541fs.cpp - 1541 emulation in host file system
3   *
4 < *  Frodo (C) 1994-1997,2002-2003 Christian Bauer
4 > *  Frodo (C) 1994-1997,2002-2005 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 47 | Line 47
47   #endif
48  
49  
50 // Access modes
51 enum {
52        FMODE_READ, FMODE_WRITE, FMODE_APPEND
53 };
54
55 // File types
56 enum {
57        FTYPE_PRG, FTYPE_SEQ
58 };
59
50   // Prototypes
51 < static bool match(char *p, char *n);
51 > static bool match(const char *p, const char *n);
52  
53  
54   /*
55   *  Constructor: Prepare emulation
56   */
57  
58 < FSDrive::FSDrive(IEC *iec, char *path) : Drive(iec)
58 > FSDrive::FSDrive(IEC *iec, const char *path) : Drive(iec)
59   {
60          strcpy(orig_dir_path, path);
61          dir_path[0] = 0;
# Line 127 | Line 117 | bool FSDrive::change_dir(char *dirpath)
117   *  Open channel
118   */
119  
120 < uint8 FSDrive::Open(int channel, char *filename)
120 > uint8 FSDrive::Open(int channel, const uint8 *name, int name_len)
121   {
122          set_error(ERR_OK);
123  
124          // Channel 15: Execute file name as command
125          if (channel == 15) {
126 <                execute_command(filename);
126 >                execute_cmd(name, name_len);
127                  return ST_OK;
128          }
129  
# Line 143 | Line 133 | uint8 FSDrive::Open(int channel, char *f
133                  file[channel] = NULL;
134          }
135  
136 <        if (filename[0] == '$')
147 <                return open_directory(channel, filename+1);
148 <
149 <        if (filename[0] == '#') {
136 >        if (name[0] == '#') {
137                  set_error(ERR_NOCHANNEL);
138                  return ST_OK;
139          }
140  
141 <        return open_file(channel, filename);
141 >        if (name[0] == '$')
142 >                return open_directory(channel, name + 1, name_len - 1);
143 >
144 >        return open_file(channel, name, name_len);
145   }
146  
147  
# Line 159 | Line 149 | uint8 FSDrive::Open(int channel, char *f
149   *  Open file
150   */
151  
152 < uint8 FSDrive::open_file(int channel, char *filename)
152 > uint8 FSDrive::open_file(int channel, const uint8 *name, int name_len)
153   {
154 <        char plainname[NAMEBUF_LENGTH];
155 <        int filemode = FMODE_READ;
156 <        int filetype = FTYPE_PRG;
157 <        bool wildflag = false;
158 <        char *mode = "rb";
159 <        
160 <        convert_filename(filename, plainname, &filemode, &filetype, &wildflag);
161 <
162 <        // Channel 0 is READ PRG, channel 1 is WRITE PRG
163 <        if (!channel) {
164 <                filemode = FMODE_READ;
165 <                filetype = FTYPE_PRG;
166 <        }
167 <        if (channel == 1) {
168 <                filemode = FMODE_WRITE;
169 <                filetype = FTYPE_PRG;
170 <        }
171 <
172 <        // Wildcards are only allowed on reading
183 <        if (wildflag) {
184 <                if (filemode != FMODE_READ) {
154 >        char plain_name[NAMEBUF_LENGTH];
155 >        int plain_name_len;
156 >        int mode = FMODE_READ;
157 >        int type = FTYPE_PRG;
158 >        int rec_len = 0;
159 >        parse_file_name(name, name_len, (uint8 *)plain_name, plain_name_len, mode, type, rec_len, true);
160 >
161 >        // Channel 0 is READ, channel 1 is WRITE
162 >        if (channel == 0 || channel == 1) {
163 >                mode = channel ? FMODE_WRITE : FMODE_READ;
164 >                if (type == FTYPE_DEL)
165 >                        type = FTYPE_PRG;
166 >        }
167 >
168 >        bool writing = (mode == FMODE_WRITE || mode == FMODE_APPEND);
169 >
170 >        // Expand wildcards (only allowed on reading)
171 >        if (strchr(plain_name, '*') || strchr(plain_name, '?')) {
172 >                if (writing) {
173                          set_error(ERR_SYNTAX33);
174                          return ST_OK;
175 <                }
176 <                find_first_file(plainname);
175 >                } else
176 >                        find_first_file(plain_name);
177 >        }
178 >
179 >        // Relative files are not supported
180 >        if (type == FTYPE_REL) {
181 >                set_error(ERR_UNIMPLEMENTED);
182 >                return ST_OK;
183          }
184  
185          // Select fopen() mode according to file mode
186 <        switch (filemode) {
187 <                case FMODE_READ:
194 <                        mode = "rb";
195 <                        break;
186 >        const char *mode_str = "rb";
187 >        switch (mode) {
188                  case FMODE_WRITE:
189 <                        mode = "wb";
189 >                        mode_str = "wb";
190                          break;
191                  case FMODE_APPEND:
192 <                        mode = "ab";
192 >                        mode_str = "ab";
193                          break;
194          }
195  
# Line 205 | Line 197 | uint8 FSDrive::open_file(int channel, ch
197   #ifndef __riscos__
198          if (chdir(dir_path))
199                  set_error(ERR_NOTREADY);
200 <        else if ((file[channel] = fopen(plainname, mode)) != NULL) {
201 <                if (filemode == FMODE_READ)     // Read and buffer first byte
200 >        else if ((file[channel] = fopen(plain_name, mode_str)) != NULL) {
201 >                if (mode == FMODE_READ || mode == FMODE_M)      // Read and buffer first byte
202                          read_char[channel] = fgetc(file[channel]);
203          } else
204                  set_error(ERR_FILENOTFOUND);
# Line 216 | Line 208 | uint8 FSDrive::open_file(int channel, ch
208            char fullname[NAMEBUF_LENGTH];
209  
210            // On RISC OS make a full filename
211 <          sprintf(fullname,"%s.%s",dir_path,plainname);
211 >          sprintf(fullname,"%s.%s",dir_path,plain_name);
212            if ((file[channel] = fopen(fullname, mode)) != NULL)
213            {
214 <            if (filemode == FMODE_READ)
214 >            if (mode == FMODE_READ || mode == FMODE_M)
215              {
216                read_char[channel] = fgetc(file[channel]);
217              }
# Line 236 | Line 228 | uint8 FSDrive::open_file(int channel, ch
228  
229  
230   /*
239 *  Analyze file name, get access mode and type
240 */
241
242 void FSDrive::convert_filename(char *srcname, char *destname, int *filemode, int *filetype, bool *wildflag)
243 {
244        char *p, *q;
245        int i;
246
247        // Search for ':', p points to first character after ':'
248        if ((p = strchr(srcname, ':')) != NULL)
249                p++;
250        else
251                p = srcname;
252
253        // Convert char set of the remaining string -> destname
254        q = destname;
255        for (i=0; i<NAMEBUF_LENGTH && (*q++ = conv_from_64(*p++, true)); i++) ;
256
257        // Look for mode parameters seperated by ','
258        p = destname;
259        while ((p = strchr(p, ',')) != NULL) {
260
261                // Cut string after the first ','
262                *p++ = 0;
263
264                switch (*p) {
265                        case 'p':
266                                *filetype = FTYPE_PRG;
267                                break;
268                        case 's':
269                                *filetype = FTYPE_SEQ;
270                                break;
271                        case 'r':
272                                *filemode = FMODE_READ;
273                                break;
274                        case 'w':
275                                *filemode = FMODE_WRITE;
276                                break;
277                        case 'a':
278                                *filemode = FMODE_APPEND;
279                                break;
280                }
281        }
282
283        // Search for wildcards
284        *wildflag = (strchr(destname, '?') != NULL) || (strchr(destname, '*') != NULL);
285 }
286
287
288 /*
231   *  Find first file matching wildcard pattern and get its real name
232   */
233  
234   // Return true if name 'n' matches pattern 'p'
235 < static bool match(char *p, char *n)
235 > static bool match(const char *p, const char *n)
236   {
237          if (!*p)                // Null pattern matches everything
238                  return true;
# Line 306 | Line 248 | static bool match(char *p, char *n)
248          return !*n;
249   }
250  
251 < void FSDrive::find_first_file(char *name)
251 > void FSDrive::find_first_file(char *pattern)
252   {
253   #ifndef __riscos__
254          DIR *dir;
# Line 322 | Line 264 | void FSDrive::find_first_file(char *name
264          while (de) {
265  
266                  // Match found? Then copy real file name
267 <                if (match(name, de->d_name)) {
268 <                        strncpy(name, de->d_name, NAMEBUF_LENGTH);
267 >                if (match(pattern, de->d_name)) {
268 >                        strncpy(pattern, de->d_name, NAMEBUF_LENGTH);
269                          closedir(dir);
270                          return;
271                  }
# Line 355 | Line 297 | void FSDrive::find_first_file(char *name
297   *  Open directory, create temporary file
298   */
299  
300 < uint8 FSDrive::open_directory(int channel, char *filename)
300 > uint8 FSDrive::open_directory(int channel, const uint8 *pattern, int pattern_len)
301   {
302          char buf[] = "\001\004\001\001\0\0\022\042                \042 00 2A";
303          char str[NAMEBUF_LENGTH];
362        char pattern[NAMEBUF_LENGTH];
304          char *p, *q;
305          int i;
306          int filemode;
# Line 372 | Line 313 | uint8 FSDrive::open_directory(int channe
313          struct stat statbuf;
314  
315          // Special treatment for "$0"
316 <        if (filename[0] == '0' && filename[1] == 0)
317 <                filename += 1;
316 >        if (pattern[0] == '0' && pattern[1] == 0) {
317 >                pattern++;
318 >                pattern_len--;
319 >        }
320  
321 <        // Convert filename ('$' already stripped), filemode/type are ignored
322 <        convert_filename(filename, pattern, &filemode, &filetype, &wildflag);
321 >        // Skip everything before the ':' in the pattern
322 >        uint8 *t = (uint8 *)memchr(pattern, ':', pattern_len);
323 >        if (t)
324 >                pattern = t + 1;
325 >
326 >        // Convert pattern to ASCII
327 >        char ascii_pattern[NAMEBUF_LENGTH];
328 >        petscii2ascii(ascii_pattern, pattern, NAMEBUF_LENGTH);
329  
330          // Open directory for reading and skip '.' and '..'
331          if ((dir = opendir(dir_path)) == NULL) {
# Line 396 | Line 345 | uint8 FSDrive::open_directory(int channe
345          // Create directory title
346          p = &buf[8];
347          for (i=0; i<16 && dir_title[i]; i++)
348 <                *p++ = conv_to_64(dir_title[i], false);
348 >                *p++ = ascii2petscii(dir_title[i]);
349          fwrite(buf, 1, 32, file[channel]);
350  
351          // Create and write one line for every directory entry
352          while (de) {
353  
354 <                // Include only files matching the pattern
355 <                if (match(pattern, de->d_name)) {
354 >                // Include only files matching the ascii_pattern
355 >                if (match(ascii_pattern, de->d_name)) {
356  
357                          // Get file statistics
358                          chdir(dir_path);
# Line 432 | Line 381 | uint8 FSDrive::open_directory(int channe
381                          *p++ = '\"';
382                          q = p;
383                          for (i=0; i<16 && str[i]; i++)
384 <                                *q++ = conv_to_64(str[i], true);
384 >                                *q++ = ascii2petscii(str[i]);
385                          *q++ = '\"';
386                          p += 18;
387  
# Line 460 | Line 409 | uint8 FSDrive::open_directory(int channe
409          unsigned char c;
410  
411          // Much of this is very similar to the original
412 <        if ((filename[0] == '0') && (filename[1] == 0)) {filename++;}
412 >        if ((pattern[0] == '0') && (pattern[1] == 0)) {pattern++;}
413  
414 <        // Concatenate dir_path and pattern in buffer pattern ==> read subdirs!
415 <        strcpy(pattern,dir_path); i = strlen(pattern); pattern[i++] = '.'; pattern[i] = 0;
416 <        convert_filename(filename, pattern + i, &filemode, &filetype, &wildflag);
417 <        p = pattern + i; q = p;
414 >        // Concatenate dir_path and ascii_pattern in buffer ascii_pattern ==> read subdirs!
415 >        strcpy(ascii_pattern,dir_path); i = strlen(ascii_pattern); ascii_pattern[i++] = '.'; ascii_pattern[i] = 0;
416 >        convert_filename(pattern, ascii_pattern + i, &filemode, &filetype, &wildflag);
417 >        p = ascii_pattern + i; q = p;
418          do {c = *q++; if (c == '.') p = q;} while (c >= 32);
419 <        *(p-1) = 0;  // separate directory-path and pattern
419 >        *(p-1) = 0;  // separate directory-path and ascii_pattern
420          if ((uint8)(*p) < 32) {*p = '*'; *(p+1) = 0;}
421  
422          // We don't use tmpfile() -- problems involved!
# Line 484 | Line 433 | uint8 FSDrive::open_directory(int channe
433  
434          do {
435                  de.readno = 1;
436 <                if (ReadDirNameInfo(pattern,&di,&de) != NULL)
436 >                if (ReadDirNameInfo(ascii_pattern,&di,&de) != NULL)
437                          de.offset = -1;
438                  else if (de.readno > 0) {       // don't have to check for match here
439                          memset(buf,' ',31); buf[31] = 0;        // most of this: see above
# Line 563 | Line 512 | void FSDrive::close_all_channels(void)
512   *  Read from channel
513   */
514  
515 < uint8 FSDrive::Read(int channel, uint8 *byte)
515 > uint8 FSDrive::Read(int channel, uint8 &byte)
516   {
517          int c;
518  
519          // Channel 15: Error channel
520          if (channel == 15) {
521 <                *byte = *error_ptr++;
521 >                byte = *error_ptr++;
522  
523 <                if (*byte != '\r')
523 >                if (byte != '\r')
524                          return ST_OK;
525                  else {  // End of message
526                          set_error(ERR_OK);
# Line 582 | Line 531 | uint8 FSDrive::Read(int channel, uint8 *
531          if (!file[channel]) return ST_READ_TIMEOUT;
532  
533          // Read one byte
534 <        *byte = read_char[channel];
534 >        byte = read_char[channel];
535          c = fgetc(file[channel]);
536          if (c == EOF)
537                  return ST_EOF;
# Line 601 | Line 550 | uint8 FSDrive::Write(int channel, uint8
550   {
551          // Channel 15: Collect chars and execute command on EOI
552          if (channel == 15) {
553 <                if (cmd_len >= 40)
553 >                if (cmd_len >= 58)
554                          return ST_TIMEOUT;
555                  
556 <                cmd_buffer[cmd_len++] = byte;
556 >                cmd_buf[cmd_len++] = byte;
557  
558                  if (eoi) {
559 <                        cmd_buffer[cmd_len] = 0;
559 >                        execute_cmd(cmd_buf, cmd_len);
560                          cmd_len = 0;
612                        execute_command(cmd_buffer);
561                  }
562                  return ST_OK;
563          }
# Line 619 | Line 567 | uint8 FSDrive::Write(int channel, uint8
567                  return ST_TIMEOUT;
568          }
569  
570 <        if (fputc(byte, file[channel]) == EOF) {
571 <                set_error(ERR_WRITEERROR);
570 >        if (putc(byte, file[channel]) == EOF) {
571 >                set_error(ERR_WRITE25);
572                  return ST_TIMEOUT;
573          }
574  
# Line 629 | Line 577 | uint8 FSDrive::Write(int channel, uint8
577  
578  
579   /*
580 < *  Execute command string
580 > *  Execute drive commands
581   */
582  
583 < void FSDrive::execute_command(char *command)
583 > // INITIALIZE
584 > void FSDrive::initialize_cmd(void)
585   {
586 <        switch (command[0]) {
638 <                case 'I':
639 <                        close_all_channels();
640 <                        set_error(ERR_OK);
641 <                        break;
642 <
643 <                case 'U':
644 <                        if ((command[1] & 0x0f) == 0x0a) {
645 <                                Reset();
646 <                        } else
647 <                                set_error(ERR_SYNTAX30);
648 <                        break;
649 <
650 <                case 'G':
651 <                        if (command[1] != ':')
652 <                                set_error(ERR_SYNTAX30);
653 <                        else
654 <                                chdir_cmd(&command[2]);
655 <                        break;
656 <
657 <                default:
658 <                        set_error(ERR_SYNTAX30);
659 <        }
586 >        close_all_channels();
587   }
588  
589 <
590 < /*
664 < *  Execute 'G' command
665 < */
666 <
667 < void FSDrive::chdir_cmd(char *dirpath)
589 > // VALIDATE
590 > void FSDrive::validate_cmd(void)
591   {
669        char str[NAMEBUF_LENGTH];
670        char *p = str;
671
672        close_all_channels();
673
674        // G:. resets the directory path to its original setting
675        if (dirpath[0] == '.' && dirpath[1] == 0) {
676                change_dir(orig_dir_path);
677        } else {
678
679                // Convert directory name
680                for (int i=0; i<NAMEBUF_LENGTH && (*p++ = conv_from_64(*dirpath++, false)); i++) ;
681
682                if (!change_dir(str))
683                        set_error(ERR_NOTREADY);
684        }
592   }
593  
594  
# Line 695 | Line 602 | void FSDrive::Reset(void)
602          cmd_len = 0;    
603          set_error(ERR_STARTUP);
604   }
698
699
700 /*
701 *  Conversion PETSCII->ASCII
702 */
703
704 uint8 FSDrive::conv_from_64(uint8 c, bool map_slash)
705 {
706        if ((c >= 'A') && (c <= 'Z') || (c >= 'a') && (c <= 'z'))
707                return c ^ 0x20;
708        if ((c >= 0xc1) && (c <= 0xda))
709                return c ^ 0x80;
710        if ((c == '/') && map_slash && ThePrefs.MapSlash)
711 #ifdef __riscos__
712                return '.';     // directory separator is '.' in RO
713        if (c == '.') {return('_');}    // convert dot to underscore
714        if (c == ' ') {return(0xa0);}   // space --> hard space
715 #else
716                return '\\';
717 #endif
718        return c;
719 }
720
721
722 /*
723 *  Conversion ASCII->PETSCII
724 */
725
726 uint8 FSDrive::conv_to_64(uint8 c, bool map_slash)
727 {
728        if ((c >= 'A') && (c <= 'Z') || (c >= 'a') && (c <= 'z'))
729                return c ^ 0x20;
730 #ifdef __riscos__
731        if ((c == '.') && map_slash && ThePrefs.MapSlash)
732 #else
733        if ((c == '\\') && map_slash && ThePrefs.MapSlash)
734 #endif
735                return '/';
736 #ifdef __riscos__
737        if (c == '_') {return('.');}    // convert underscore to dot
738        if (c == 0xa0) {return(' ');}   // hard space -> space
739 #endif
740        return c;
741 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines