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

Comparing Frodo4/Src/1541d64.cpp (file contents):
Revision 1.3 by cebix, 2003-07-02T14:46:24Z vs.
Revision 1.4 by cebix, 2004-01-11T00:09:51Z

# Line 44 | Line 44 | enum {
44          CHMOD_DIRECT            // Direct buffer access ('#')
45   };
46  
47 // Access modes
48 enum {
49        FMODE_READ, FMODE_WRITE, FMODE_APPEND
50 };
51
52 // File types
53 enum {
54        FTYPE_PRG, FTYPE_SEQ, FTYPE_USR, FTYPE_REL
55 };
56
47   // Number of tracks/sectors
48   const int NUM_TRACKS = 35;
49   const int NUM_SECTORS = 683;
# Line 160 | Line 150 | void D64Drive::open_close_d64_file(char
150   *  Open channel
151   */
152  
153 < uint8 D64Drive::Open(int channel, char *filename)
153 > uint8 D64Drive::Open(int channel, const uint8 *name, int name_len)
154   {
155          set_error(ERR_OK);
156  
157          // Channel 15: execute file name as command
158          if (channel == 15) {
159 <                execute_command(filename);
159 >                execute_cmd(name, name_len);
160                  return ST_OK;
161          }
162  
# Line 175 | Line 165 | uint8 D64Drive::Open(int channel, char *
165                  return ST_OK;
166          }
167  
168 <        if (filename[0] == '$')
168 >        if (name[0] == '$')
169                  if (channel)
170                          return open_file_ts(channel, 18, 0);
171                  else
172 <                        return open_directory(filename+1);
172 >                        return open_directory(name + 1, name_len - 1);
173  
174 <        if (filename[0] == '#')
175 <                return open_direct(channel, filename);
174 >        if (name[0] == '#')
175 >                return open_direct(channel, name);
176  
177 <        return open_file(channel, filename);
177 >        return open_file(channel, name, name_len);
178   }
179  
180  
# Line 192 | Line 182 | uint8 D64Drive::Open(int channel, char *
182   *  Open file
183   */
184  
185 < uint8 D64Drive::open_file(int channel, char *filename)
185 > uint8 D64Drive::open_file(int channel, const uint8 *name, int name_len)
186   {
187 <        char plainname[256];
188 <        int filemode = FMODE_READ;
189 <        int filetype = FTYPE_PRG;
190 <        int track, sector;
191 <
192 <        convert_filename(filename, plainname, &filemode, &filetype);
193 <
194 <        // Channel 0 is READ PRG, channel 1 is WRITE PRG
195 <        if (!channel) {
196 <                filemode = FMODE_READ;
197 <                filetype = FTYPE_PRG;
198 <        }
199 <        if (channel == 1) {
200 <                filemode = FMODE_WRITE;
211 <                filetype = FTYPE_PRG;
187 >        uint8 plain_name[256];
188 >        int plain_name_len;
189 >        int mode = FMODE_READ;
190 >        int type = FTYPE_PRG;
191 >        int rec_len = 0;
192 >        parse_file_name(name, name_len, plain_name, plain_name_len, mode, type, rec_len);
193 >        if (plain_name_len > 16)
194 >                plain_name_len = 16;
195 >
196 >        // Channel 0 is READ, channel 1 is WRITE
197 >        if (channel == 0 || channel == 1) {
198 >                mode = channel ? FMODE_WRITE : FMODE_READ;
199 >                if (type == FTYPE_DEL)
200 >                        type = FTYPE_PRG;
201          }
202  
203          // Allow only read accesses
204 <        if (filemode != FMODE_READ) {
204 >        if (mode != FMODE_READ) {
205                  set_error(ERR_WRITEPROTECT);
206                  return ST_OK;
207          }
208  
209 +        // Relative files are not supported
210 +        if (type == FTYPE_REL) {
211 +                set_error(ERR_UNIMPLEMENTED);
212 +                return ST_OK;
213 +        }
214 +
215          // Find file in directory and open it
216 <        if (find_file(plainname, &track, &sector))
216 >        int track, sector;
217 >        if (find_file(plain_name, &track, &sector))
218                  return open_file_ts(channel, track, sector);
219          else
220                  set_error(ERR_FILENOTFOUND);
# Line 228 | Line 224 | uint8 D64Drive::open_file(int channel, c
224  
225  
226   /*
231 *  Analyze file name, get access mode and type
232 */
233
234 void D64Drive::convert_filename(char *srcname, char *destname, int *filemode, int *filetype)
235 {
236        char *p;
237
238        // Search for ':', p points to first character after ':'
239        if ((p = strchr(srcname, ':')) != NULL)
240                p++;
241        else
242                p = srcname;
243
244        // Remaining string -> destname
245        strncpy(destname, p, NAMEBUF_LENGTH);
246
247        // Search for ','
248        p = destname;
249        while (*p && (*p != ',')) p++;
250
251        // Look for mode parameters seperated by ','
252        p = destname;
253        while ((p = strchr(p, ',')) != NULL) {
254
255                // Cut string after the first ','
256                *p++ = 0;
257
258                switch (*p) {
259                        case 'P':
260                                *filetype = FTYPE_PRG;
261                                break;
262                        case 'S':
263                                *filetype = FTYPE_SEQ;
264                                break;
265                        case 'U':
266                                *filetype = FTYPE_USR;
267                                break;
268                        case 'L':
269                                *filetype = FTYPE_REL;
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
284
285 /*
227   *  Search file in directory, find first track and sector
228   *  false: not found, true: found
229   */
230  
231 < bool D64Drive::find_file(char *filename, int *track, int *sector)
231 > bool D64Drive::find_file(const uint8 *pattern, int *track, int *sector)
232   {
233          int i, j;
234 <        uint8 *p, *q;
234 >        const uint8 *p, *q;
235          DirEntry *de;
236  
237          // Scan all directory blocks
# Line 308 | Line 249 | bool D64Drive::find_file(char *filename,
249                          *sector = de->sector;
250  
251                          if (de->type) {
252 <                                p = (uint8 *)filename;
252 >                                p = pattern;
253                                  q = de->name;
254                                  for (i=0; i<16 && *p; i++, p++, q++) {
255                                          if (*p == '*')  // Wildcard '*' matches all following characters
# Line 373 | Line 314 | static bool match(uint8 *p, uint8 *n)
314          return *n == 0xa0;
315   }
316  
317 < uint8 D64Drive::open_directory(char *pattern)
317 > uint8 D64Drive::open_directory(const uint8 *pattern, int pattern_len)
318   {
378        int i, j, n, m;
379        uint8 *p, *q;
380        DirEntry *de;
381        uint8 c;
382        char *tmppat;
383
319          // Special treatment for "$0"
320 <        if (pattern[0] == '0' && pattern[1] == 0)
321 <                pattern += 1;
320 >        if (pattern[0] == '0' && pattern[1] == 0) {
321 >                pattern++;
322 >                pattern_len--;
323 >        }
324  
325          // Skip everything before the ':' in the pattern
326 <        if ((tmppat = strchr(pattern, ':')) != NULL)
327 <                pattern = tmppat + 1;
326 >        uint8 *t = (uint8 *)memchr(pattern, ':', pattern_len);
327 >        if (t) {
328 >                t++;
329 >                pattern_len -= t - pattern;
330 >                pattern = t;
331 >        }
332  
392        p = buf_ptr[0] = chan_buf[0] = new uint8[8192];
333          chan_mode[0] = CHMOD_DIRECTORY;
334 +        uint8 *p = buf_ptr[0] = chan_buf[0] = new uint8[8192];
335  
336          // Create directory title
337          *p++ = 0x01;    // Load address $0401 (from PET days :-)
# Line 402 | Line 343 | uint8 D64Drive::open_directory(char *pat
343          *p++ = 0x12;    // RVS ON
344          *p++ = '\"';
345  
346 <        q = bam->disk_name;
347 <        for (i=0; i<23; i++) {
346 >        uint8 *q = bam->disk_name;
347 >        for (int i=0; i<23; i++) {
348 >                int c;
349                  if ((c = *q++) == 0xa0)
350                          *p++ = ' ';             // Replace 0xa0 by space
351                  else
# Line 421 | Line 363 | uint8 D64Drive::open_directory(char *pat
363                          return ST_OK;
364  
365                  // Scan all 8 entries of a block
366 <                for (j=0; j<8; j++) {
367 <                        de = &dir.entry[j];
366 >                for (int j=0; j<8; j++) {
367 >                        DirEntry *de = &dir.entry[j];
368  
369                          if (de->type && match((uint8 *)pattern, de->name)) {
370                                  *p++ = 0x01; // Dummy line link
# Line 432 | Line 374 | uint8 D64Drive::open_directory(char *pat
374                                  *p++ = de->num_blocks_h;
375  
376                                  *p++ = ' ';
377 <                                n = (de->num_blocks_h << 8) + de->num_blocks_l;
377 >                                int n = (de->num_blocks_h << 8) + de->num_blocks_l;
378                                  if (n<10) *p++ = ' ';
379                                  if (n<100) *p++ = ' ';
380  
381                                  *p++ = '\"';
382                                  q = de->name;
383 <                                m = 0;
384 <                                for (i=0; i<16; i++) {
383 >                                uint8 c;
384 >                                int m = 0;
385 >                                for (int i=0; i<16; i++) {
386                                          if ((c = *q++) == 0xa0) {
387                                                  if (m)
388 <                                                        *p++ = ' ';             // Replace all 0xa0 by spaces
388 >                                                        *p++ = ' ';                     // Replace all 0xa0 by spaces
389                                                  else
390                                                          m = *p++ = '\"';        // But the first by a '"'
391                                          } else
# Line 453 | Line 396 | uint8 D64Drive::open_directory(char *pat
396                                  else
397                                          *p++ = '\"';                    // No 0xa0, then append a space
398  
399 +                                // Open files are marked by '*'
400                                  if (de->type & 0x80)
401                                          *p++ = ' ';
402                                  else
403                                          *p++ = '*';
404  
405 +                                // File type
406                                  *p++ = type_char_1[de->type & 0x0f];
407                                  *p++ = type_char_2[de->type & 0x0f];
408                                  *p++ = type_char_3[de->type & 0x0f];
409  
410 +                                // Protected files are marked by '<'
411                                  if (de->type & 0x40)
412                                          *p++ = '<';
413                                  else
414                                          *p++ = ' ';
415  
416 +                                // Appropriate number of spaces at the end
417                                  *p++ = ' ';
418                                  if (n >= 10) *p++ = ' ';
419                                  if (n >= 100) *p++ = ' ';
# Line 475 | Line 422 | uint8 D64Drive::open_directory(char *pat
422                  }
423          }
424  
425 <        // Final line
426 <        q = p;
427 <        for (i=0; i<29; i++)
428 <                *q++ = ' ';
429 <
430 <        n = 0;
484 <        for (i=0; i<35; i++)
485 <                n += bam->bitmap[i*4];
425 >        // Final line, count number of free blocks
426 >        int n = 0;
427 >        for (int i=0; i<35; i++) {
428 >                if (i != 17) // exclude directory track
429 >                        n += bam->bitmap[i*4];
430 >        }
431  
432          *p++ = 0x01;            // Dummy line link
433          *p++ = 0x01;
# Line 502 | Line 447 | uint8 D64Drive::open_directory(char *pat
447          *p++ = 'E';
448          *p++ = '.';
449  
450 <        p = q;
450 >        memset(p, ' ', 13);
451 >        p += 13;
452 >
453          *p++ = 0;
454          *p++ = 0;
455          *p++ = 0;
# Line 517 | Line 464 | uint8 D64Drive::open_directory(char *pat
464   *  Open channel for direct buffer access
465   */
466  
467 < uint8 D64Drive::open_direct(int channel, char *filename)
467 > uint8 D64Drive::open_direct(int channel, const uint8 *name)
468   {
469          int buf = -1;
470  
471 <        if (filename[1] == 0)
471 >        if (name[1] == 0)
472                  buf = alloc_buffer(-1);
473          else
474 <                if ((filename[1] >= '0') && (filename[1] <= '3') && (filename[2] == 0))
475 <                        buf = alloc_buffer(filename[1] - '0');
474 >                if ((name[1] >= '0') && (name[1] <= '3') && (name[2] == 0))
475 >                        buf = alloc_buffer(name[1] - '0');
476  
477          if (buf == -1) {
478                  set_error(ERR_NOCHANNEL);
# Line 657 | Line 604 | uint8 D64Drive::Write(int channel, uint8
604  
605                  case CHMOD_COMMAND:
606                          // Collect characters and execute command on EOI
607 <                        if (cmd_len >= 40)
607 >                        if (cmd_len >= 58)
608                                  return ST_TIMEOUT;
609  
610 <                        cmd_buffer[cmd_len++] = byte;
610 >                        cmd_buf[cmd_len++] = byte;
611  
612                          if (eoi) {
613 <                                cmd_buffer[cmd_len++] = 0;
613 >                                execute_cmd(cmd_buf, cmd_len);
614                                  cmd_len = 0;
668                                execute_command(cmd_buffer);
615                          }
616                          return ST_OK;
617  
# Line 681 | Line 627 | uint8 D64Drive::Write(int channel, uint8
627   *  Execute command string
628   */
629  
630 < void D64Drive::execute_command(char *command)
630 > // BLOCK-READ:channel,0,track,sector
631 > void D64Drive::block_read_cmd(int channel, int track, int sector, bool user_cmd)
632   {
633 <        uint16 adr;
634 <        int len;
635 <
636 <        switch (command[0]) {
637 <                case 'B':
638 <                        if (command[1] != '-')
639 <                                set_error(ERR_SYNTAX30);
640 <                        else
641 <                                switch (command[2]) {
642 <                                        case 'R':
643 <                                                block_read_cmd(&command[3]);
697 <                                                break;
698 <
699 <                                        case 'P':
700 <                                                buffer_ptr_cmd(&command[3]);
701 <                                                break;
702 <
703 <                                        case 'A':
704 <                                        case 'F':
705 <                                        case 'W':
706 <                                                set_error(ERR_WRITEPROTECT);
707 <                                                break;
708 <
709 <                                        default:
710 <                                                set_error(ERR_SYNTAX30);
711 <                                                break;
712 <                                }
713 <                        break;
714 <
715 <                case 'M':
716 <                        if (command[1] != '-')
717 <                                set_error(ERR_SYNTAX30);
718 <                        else
719 <                                switch (command[2]) {
720 <                                        case 'R':
721 <                                                adr = ((uint8)command[4] << 8) | ((uint8)command[3]);
722 <                                                error_ptr = (char *)(ram + (adr & 0x07ff));
723 <                                                if (!(error_len = (uint8)command[5]))
724 <                                                        error_len = 1;
725 <                                                break;
726 <
727 <                                        case 'W':
728 <                                                adr = ((uint8)command[4] << 8) | ((uint8)command[3]);
729 <                                                len = (uint8)command[5];
730 <                                                for (int i=0; i<len; i++)
731 <                                                        ram[adr+i] = (uint8)command[i+6];
732 <                                                break;
733 <
734 <                                        default:
735 <                                                set_error(ERR_SYNTAX30);
736 <                                }
737 <                        break;
738 <
739 <                case 'I':
740 <                        close_all_channels();
741 <                        read_sector(18, 0, (uint8 *)bam);
742 <                        set_error(ERR_OK);
743 <                        break;
744 <
745 <                case 'U':
746 <                        switch (command[1] & 0x0f) {
747 <                                case 1:         // U1/UA: Block-Read
748 <                                        block_read_cmd(&command[2]);
749 <                                        break;
750 <
751 <                                case 2:         // U2/UB: Block-Write
752 <                                        set_error(ERR_WRITEPROTECT);
753 <                                        break;
754 <
755 <                                case 10:        // U:/UJ: Reset
756 <                                        Reset();
757 <                                        break;
758 <
759 <                                default:
760 <                                        set_error(ERR_SYNTAX30);
761 <                                        break;
762 <                        }
763 <                        break;
764 <
765 <                case 'G':
766 <                        if (command[1] != ':')
767 <                                set_error(ERR_SYNTAX30);
768 <                        else
769 <                                chd64_cmd(&command[2]);
770 <                        break;
771 <
772 <                case 'C':
773 <                case 'N':
774 <                case 'R':
775 <                case 'S':
776 <                case 'V':
777 <                        set_error(ERR_WRITEPROTECT);
778 <                        break;
779 <
780 <                default:
781 <                        set_error(ERR_SYNTAX30);
782 <                        break;
633 >        if (channel >= 16 || chan_mode[channel] != CHMOD_DIRECT) {
634 >                set_error(ERR_NOCHANNEL);
635 >                return;
636 >        }
637 >        read_sector(track, sector, chan_buf[channel]);
638 >        if (user_cmd) {
639 >                buf_len[channel] = 256;
640 >                buf_ptr[channel] = chan_buf[channel];
641 >        } else {
642 >                buf_len[channel] = chan_buf[channel][0];
643 >                buf_ptr[channel] = chan_buf[channel] + 1;
644          }
645   }
646  
647 <
648 < /*
788 < *  Execute B-R command
789 < */
790 <
791 < void D64Drive::block_read_cmd(char *command)
647 > // BUFFER-POINTER:channel,pos
648 > void D64Drive::buffer_pointer_cmd(int channel, int pos)
649   {
650 <        int channel, drvnum, track, sector;
651 <
652 <        if (parse_bcmd(command, &channel, &drvnum, &track, &sector)) {
653 <                if (chan_mode[channel] == CHMOD_DIRECT) {
654 <                        read_sector(track, sector, buf_ptr[channel] = chan_buf[channel]);
655 <                        buf_len[channel] = 256;
799 <                        set_error(ERR_OK);
800 <                } else
801 <                        set_error(ERR_NOCHANNEL);
802 <        } else
803 <                set_error(ERR_SYNTAX30);
650 >        if (channel >= 16 || chan_mode[channel] != CHMOD_DIRECT) {
651 >                set_error(ERR_NOCHANNEL);
652 >                return;
653 >        }
654 >        buf_ptr[channel] = chan_buf[channel] + pos;
655 >        buf_len[channel] = 256 - pos;
656   }
657  
658 <
659 < /*
808 < *  Execute B-P command
809 < */
810 <
811 < void D64Drive::buffer_ptr_cmd(char *command)
658 > // M-R<adr low><adr high>[<number>]
659 > void D64Drive::mem_read_cmd(uint16 adr, uint8 len)
660   {
661 <        int channel, pointer, i;
662 <
663 <        if (parse_bcmd(command, &channel, &pointer, &i, &i)) {
664 <                if (chan_mode[channel] == CHMOD_DIRECT) {
665 <                        buf_ptr[channel] = chan_buf[channel] + pointer;
666 <                        buf_len[channel] = 256 - pointer;
667 <                        set_error(ERR_OK);
668 <                } else
669 <                        set_error(ERR_NOCHANNEL);
822 <        } else
823 <                set_error(ERR_SYNTAX30);
661 >        error_len = len;
662 >        if (adr >= 0x300 && adr < 0x1000) {
663 >                // Read from RAM
664 >                error_ptr = (char *)ram + (adr & 0x7ff);
665 >        } else {
666 >                unsupp_cmd();
667 >                memset(error_buf, 0, len);
668 >                error_ptr = error_buf;
669 >        }
670   }
671  
672 <
673 < /*
828 < *  Parse block command parameters
829 < *  true: OK, false: error
830 < */
831 <
832 < bool D64Drive::parse_bcmd(char *cmd, int *arg1, int *arg2, int *arg3, int *arg4)
672 > // M-W<adr low><adr high><number><data...>
673 > void D64Drive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p)
674   {
675 <        int i;
676 <
677 <        if (*cmd == ':') cmd++;
678 <
679 <        // Read four parameters separated by space, cursor right or comma
680 <        while (*cmd == ' ' || *cmd == 0x1d || *cmd == 0x2c) cmd++;
681 <        if (!*cmd) return false;
682 <
683 <        i = 0;
843 <        while (*cmd >= 0x30 && *cmd < 0x40) {
844 <                i *= 10;
845 <                i += *cmd++ & 0x0f;
846 <        }
847 <        *arg1 = i & 0xff;
848 <
849 <        while (*cmd == ' ' || *cmd == 0x1d || *cmd == 0x2c) cmd++;
850 <        if (!*cmd) return false;
851 <
852 <        i = 0;
853 <        while (*cmd >= 0x30 && *cmd < 0x40) {
854 <                i *= 10;
855 <                i += *cmd++ & 0x0f;
856 <        }
857 <        *arg2 = i & 0xff;
858 <
859 <        while (*cmd == ' ' || *cmd == 0x1d || *cmd == 0x2c) cmd++;
860 <        if (!*cmd) return false;
861 <
862 <        i = 0;
863 <        while (*cmd >= 0x30 && *cmd < 0x40) {
864 <                i *= 10;
865 <                i += *cmd++ & 0x0f;
866 <        }
867 <        *arg3 = i & 0xff;
868 <
869 <        while (*cmd == ' ' || *cmd == 0x1d || *cmd == 0x2c) cmd++;
870 <        if (!*cmd) return false;
871 <
872 <        i = 0;
873 <        while (*cmd >= 0x30 && *cmd < 0x40) {
874 <                i *= 10;
875 <                i += *cmd++ & 0x0f;
675 >        while (len) {
676 >                if (adr >= 0x300 && adr < 0x1000) {
677 >                        // Write to RAM
678 >                        ram[adr & 0x7ff] = *p;
679 >                } else if (adr < 0xc000) {
680 >                        unsupp_cmd();
681 >                        return;
682 >                }
683 >                len--; adr++; p++;
684          }
877        *arg4 = i & 0xff;
878
879        return true;
685   }
686  
687 <
688 < /*
884 < *  Execute 'G' command
885 < */
886 <
887 < void D64Drive::chd64_cmd(char *d64name)
687 > // INITIALIZE
688 > void D64Drive::initialize_cmd(void)
689   {
690 <        char str[NAMEBUF_LENGTH];
890 <        char *p = str;
891 <
892 <        // Convert .d64 file name
893 <        for (int i=0; i<NAMEBUF_LENGTH && (*p++ = conv_from_64(*d64name++, false)); i++) ;
894 <
690 >        // Close all channels and re-read BAM
691          close_all_channels();
896
897        // G:. resets the .d64 file name to its original setting
898        if (str[0] == '.' && str[1] == 0)
899                open_close_d64_file(orig_d64_name);
900        else
901                open_close_d64_file(str);
902
903        // Read BAM
692          read_sector(18, 0, (uint8 *)bam);
693   }
694  
# Line 1022 | Line 810 | int D64Drive::offset_from_ts(int track,
810  
811          return (sector_offset[track] + sector) << 8;
812   }
1025
1026
1027 /*
1028 *  Conversion PETSCII->ASCII
1029 */
1030
1031 uint8 D64Drive::conv_from_64(uint8 c, bool map_slash)
1032 {
1033        if ((c >= 'A') && (c <= 'Z') || (c >= 'a') && (c <= 'z'))
1034                return c ^ 0x20;
1035        if ((c >= 0xc1) && (c <= 0xda))
1036                return c ^ 0x80;
1037        if ((c == '/') && map_slash && ThePrefs.MapSlash)
1038                return '\\';
1039        return c;
1040 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines