Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

d64copy/main.c

00001 /*
00002  *      This program is free software; you can redistribute it and/or
00003  *      modify it under the terms of the GNU General Public License
00004  *      as published by the Free Software Foundation; either version
00005  *      2 of the License, or (at your option) any later version.
00006  *
00007  *  Copyright 1999-2001 Michael Klein <michael(dot)klein(at)puffin(dot)lb(dot)shuttle(dot)de>
00008 */
00009 
00010 #ifdef SAVE_RCSID
00011 static char *rcsid =
00012     "@(#) $Id: main.c,v 1.16 2006/04/06 16:50:13 trikalio Exp $";
00013 #endif
00014 
00015 #include "opencbm.h"
00016 #include "d64copy.h"
00017 
00018 #include "arch.h"
00019 
00020 #include <getopt.h>
00021 #include <stdarg.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <signal.h>
00025 #include <string.h>
00026 
00027 
00028 /* setable via command line */
00029 static int verbosity = 1;
00030 static int no_progress = 0;
00031 
00032 /* other globals */
00033 static CBM_FILE fd_cbm;
00034 
00035 
00036 static int is_cbm(char *name)
00037 {
00038     return((strcmp(name, "8" ) == 0) || (strcmp(name, "9" ) == 0) ||
00039            (strcmp(name, "10") == 0) || (strcmp(name, "11") == 0) );
00040 }
00041 
00042 
00043 static void help()
00044 {
00045     printf(
00046 "Usage: d64copy [OPTION]... [SOURCE] [TARGET]\n"
00047 "Copy .d64 disk images to a CBM-1541 or compatible drive and vice versa\n"
00048 "\n"
00049 "Options:\n"
00050 "  -h, --help               display this help and exit\n"
00051 "  -V, --version            display version information and exit\n"
00052 "  -q, --quiet              quiet output\n"
00053 "  -v, --verbose            control verbosity (repeatedly, up to 3 times)\n"
00054 "  -n, --no-progress        do not display progress information\n"
00055 "\n"
00056 "  -s, --start-track=TRACK  set start track\n"
00057 "  -e, --end-track=TRACK    set end track (start <= end <= 42/70)\n"
00058 "\n"
00059 "  -t, --transfer=TRANSFER  set transfermode; valid modes:\n"
00060 "                             auto (default)\n"
00061 "                             original       (slowest)\n"
00062 "                             serial1 or s1\n"
00063 "                             serial2 or s2\n"
00064 "                             parallel       (fastest)\n"
00065 "                           (can be abbreviated, if unambiguous)\n"
00066 "                           `original' and `serial1' should work in any case;\n"
00067 "                           `serial2' won't work if more than one device is\n"
00068 "                           connected to the IEC bus;\n"
00069 "                           `parallel' needs a XP1541/XP1571 cable in addition\n"
00070 "                           to the serial one.\n"
00071 "                           `auto' tries to determine the best option.\n"
00072 "\n"
00073 "  -i, --interleave=VALUE   set interleave value; ignored when reading with\n"
00074 "                           warp mode; default values are:\n"
00075 "\n"
00076 "                             original     16\n"
00077 "\n"
00078 "                                       turbo r/w   warp write\n"
00079 "                             serial1       4            6\n"
00080 "                             serial2      13           12\n"
00081 "                             parallel      7            4\n"
00082 "\n"
00083 "                           INTERLEAVE is ignored when reading with warp mode;\n"
00084 "                           if data transfer is very slow, increasing this\n"
00085 "                           value may help.\n"
00086 "\n"
00087 "  -w, --warp               enable warp mode; this is not possible if\n"
00088 "                           TRANSFER is set to `original'\n"
00089 "                           This is the default if transfer is not `original`.\n"
00090 "\n"
00091 "      --no-warp            disable warp mode; this is the default if\n"
00092 "                           TRANSFER is set to `original'.\n"
00093 "\n"
00094 "  -b, --bam-only           BAM-only copy; only allocated blocks are copied;\n"
00095 "                           for extended tracks (36-40), SpeedDOS BAM format\n"
00096 "                           is assumed. Use with caution.\n"
00097 "\n"
00098 "  -B, --bam-save           save BAM-only copy; this is like the `-bī option\n"
00099 "                           but copies always the entire directory track.\n"
00100 "\n"
00101 "  -d, --drive-type=TYPE    specify drive type:\n"
00102 "                             0 or 1541 = 1541\n"
00103 "                             1 or 1571 = 1570/1571\n"
00104 "\n"
00105 "  -r, --retry-count=COUNT  set retry count\n"
00106 "\n"
00107 "  -E, --error-map=WHEN     control whether the error map is appended.\n"
00108 "                           possible values for WHEN are (abbreviations\n"
00109 "                           available):\n"
00110 "                             always\n"
00111 "                             on_errors     (default)\n"
00112 "                             never\n"
00113 "\n"
00114 "  -2, --two-sided          two-sided disk transfer (.d71): Requires 1571.\n"
00115 "                           Warp mode is not available for .d71 images.\n"
00116 "\n"
00117 );
00118 }
00119 
00120 static void hint(char *s)
00121 {
00122     fprintf(stderr, "Try `%s' --help for more information.\n", s);
00123 }
00124 
00125 static void ARCH_SIGNALDECL reset(int dummy)
00126 {
00127     fprintf(stderr, "\nSIGINT caught X-(  Resetting IEC bus...\n");
00128     arch_sleep(1);
00129     d64copy_cleanup();
00130     cbm_reset(fd_cbm);
00131     cbm_driver_close(fd_cbm);
00132     exit(1);
00133 }
00134 
00135 
00136 static void my_message_cb(int severity, const char *format, ...)
00137 {
00138     va_list args;
00139 
00140     static const char *severities[4] =
00141     {
00142         "Fatal",
00143         "Warning",
00144         "Info",
00145         "Debug"
00146     };
00147 
00148     if(verbosity >= severity)
00149     {
00150         fprintf(stderr, "[%s] ", severities[severity]);
00151         va_start(args, format);
00152         vfprintf(stderr, format, args);
00153         va_end(args);
00154         fprintf(stderr, "\n");
00155     }
00156 }
00157 
00158 static int my_status_cb(d64copy_status status)
00159 {
00160     static char trackmap[MAX_SECTORS+1];
00161     static int last_track;
00162     char *s;
00163     char *d;
00164 
00165     static const char bs2char[] =
00166     {
00167         ' ', '.', '-', '?', '*'
00168     };
00169 
00170     if(status.track == 0)
00171     {
00172         last_track = 0;
00173         return 0;
00174     }
00175 
00176     if(no_progress)
00177     {
00178         return 0;
00179     }
00180 
00181     if(last_track != status.track)
00182     {
00183         if(last_track)
00184         {
00185             printf("\r%2d: %-24s               \n", last_track, trackmap);
00186         }
00187 
00188         for(s = status.bam[status.track-1], d = trackmap; *s; s++, d++)
00189         {
00190             *d = bs2char[(int)*s];
00191         }
00192         *d = '\0';
00193         last_track = status.track;
00194     }
00195 
00196     trackmap[status.sector] = 
00197         bs2char[(status.read_result || 
00198                  status.write_result) ? bs_error : bs_copied];
00199 
00200     printf("\r%2d: %-24s%3d%%  %4d/%d", status.track, trackmap,
00201            100 * status.sectors_processed / status.total_sectors,
00202            status.sectors_processed, status.total_sectors);
00203 
00204     fflush(stdout);
00205     return 0;
00206 }
00207 
00208 
00209 int ARCH_MAINDECL main(int argc, char *argv[])
00210 {
00211     d64copy_settings *settings = d64copy_get_default_settings();
00212 
00213     char *tm = NULL;
00214     char *src_arg;
00215     char *dst_arg;
00216 
00217     int  c;
00218     int  rv = 1;
00219     int  l;
00220 
00221     int src_is_cbm;
00222     int dst_is_cbm;
00223 
00224     struct option longopts[] =
00225     {
00226         { "help"       , no_argument      , NULL, 'h' },
00227         { "version"    , no_argument      , NULL, 'V' },
00228         { "warp"       , no_argument      , NULL, 'w' },
00229         { "no-warp"    , no_argument      , &settings->warp, 0 },
00230         { "quiet"      , no_argument      , NULL, 'q' },
00231         { "verbose"    , no_argument      , NULL, 'v' },
00232         { "no-progress", no_argument      , NULL, 'n' },
00233         { "interleave" , required_argument, NULL, 'i' },
00234         { "start-track", required_argument, NULL, 's' },
00235         { "end-track"  , required_argument, NULL, 'e' },
00236         { "transfer"   , required_argument, NULL, 't' },
00237         { "bam-only"   , no_argument      , NULL, 'b' },
00238         { "bam-save"   , no_argument      , NULL, 'B' },
00239         { "drive-type" , required_argument, NULL, 'd' },
00240         { "retry-count", required_argument, NULL, 'r' },
00241         { "two-sided"  , no_argument      , NULL, '2' },
00242         { "error-map"  , required_argument, NULL, 'E' },
00243         { NULL         , 0                , NULL, 0   }
00244     };
00245 
00246     const char shortopts[] ="hVwqbBt:i:s:e:d:r:2vnE:";
00247 
00248     while((c=getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
00249     {
00250         switch(c)
00251         {
00252             case 'h': help();
00253                       return 0;
00254             case 'V': printf("d64copy %s\n", OPENCBM_VERSION);
00255                       return 0;
00256             case 'w': settings->warp = 1;
00257                       break;
00258             case 'q': if(verbosity > 0) verbosity--;
00259                       break;
00260             case 'v': verbosity++;
00261                       break;
00262             case 'n': no_progress = 1;
00263                       break;
00264             case 'i': settings->interleave = arch_atoc(optarg);
00265                       break;
00266             case 's': settings->start_track = atoi(optarg);
00267                       break;
00268             case 'e': settings->end_track = atoi(optarg);
00269                       break;
00270             case 't': tm = optarg;
00271                       break;
00272             case 'b': settings->bam_mode = bm_allocated;
00273                       break;
00274             case 'B': settings->bam_mode = bm_save;
00275                       break;
00276             case 'd': if(strcmp(optarg, "1541") == 0)
00277                       {
00278                           settings->drive_type = cbm_dt_cbm1541;
00279                       }
00280                       else if(strcmp(optarg, "1571") == 0)
00281                       {
00282                           settings->drive_type = cbm_dt_cbm1571;
00283                       }
00284                       else if(strcmp(optarg, "1570") == 0)
00285                       {
00286                           settings->drive_type = cbm_dt_cbm1570;
00287                       }
00288                       else
00289                       {
00290                           settings->drive_type = atoi(optarg) != 0 ?
00291                               cbm_dt_cbm1571 : cbm_dt_cbm1541;
00292                       }
00293                       break;
00294             case 'r': settings->retries = atoi(optarg);
00295                       break;
00296             case '2': settings->two_sided = 1;
00297                       break;
00298             case 'E': l = strlen(optarg);
00299                       if(strncmp(optarg, "always", l) == 0)
00300                       {
00301                           settings->error_mode = em_always;
00302                       }
00303                       else if(strncmp(optarg, "on_errors", l) == 0)
00304                       {
00305                           settings->error_mode = em_on_error;
00306                       }
00307                       else if(strncmp(optarg, "never", l) == 0)
00308                       {
00309                           settings->error_mode = em_never;
00310                       }
00311                       else
00312                       {
00313                           hint(argv[0]);
00314                           return 1;
00315                       }
00316                       break;
00317             case 0:   break; // needed for --no-warp
00318             default : hint(argv[0]);
00319                       return 1;
00320         }
00321     }
00322 
00323     settings->transfer_mode = d64copy_get_transfer_mode_index(tm);
00324     if(settings->transfer_mode < 0)
00325     {
00326         char *modes = d64copy_get_transfer_modes();
00327         char *m;
00328 
00329         fprintf(stderr, "Unknown transfer mode: %s\nAvailable modes:\n", tm);
00330 
00331         for(m = modes; *m; m+=(strlen(m)+1))
00332         {
00333             fprintf(stderr, "  %s\n", m);
00334         }
00335 
00336         free(modes);
00337         return 1;
00338     }
00339 
00340     my_message_cb(3, "transfer mode is %d", settings->transfer_mode );
00341 
00342     if(optind + 2 != argc)
00343     {
00344         fprintf(stderr, "Usage: %s [OPTION]... [SOURCE] [TARGET]\n", argv[0]);
00345         hint(argv[0]);
00346         return 1;
00347     }
00348 
00349     src_arg = argv[optind];
00350     dst_arg = argv[optind+1];
00351 
00352     src_is_cbm = is_cbm(src_arg);
00353     dst_is_cbm = is_cbm(dst_arg);
00354 
00355     if(src_is_cbm == dst_is_cbm)
00356     {
00357         my_message_cb(0, "either source or target must be a CBM drive");
00358         return 1;
00359     }
00360 
00361     if(cbm_driver_open(&fd_cbm, 0) == 0)
00362     {
00363         /*
00364          * If the user specified auto transfer mode, find out
00365          * which transfer mode to use.
00366          */
00367         settings->transfer_mode = 
00368             d64copy_check_auto_transfer_mode(fd_cbm,
00369                 settings->transfer_mode,
00370                 atoi(src_is_cbm ? src_arg : dst_arg));
00371 
00372         my_message_cb(3, "decided to use transfer mode %d", settings->transfer_mode );
00373 
00374         signal(SIGINT, reset);
00375 
00376         if(src_is_cbm)
00377         {
00378             rv = d64copy_read_image(fd_cbm, settings, atoi(src_arg), dst_arg,
00379                     my_message_cb, my_status_cb);
00380         }
00381         else
00382         {
00383             rv = d64copy_write_image(fd_cbm, settings, src_arg, atoi(dst_arg),
00384                     my_message_cb, my_status_cb);
00385         }
00386 
00387         if(!no_progress && rv >= 0)
00388         {
00389             printf("\n%d blocks copied.\n", rv);
00390         }
00391 
00392         cbm_driver_close(fd_cbm);
00393         rv = 0;
00394     }
00395     else
00396     {
00397         arch_error(0, arch_get_errno(), "%s", cbm_get_driver_name(0));
00398     }
00399 
00400     free(settings);
00401     
00402     return rv;
00403 }

Generated on Sun Apr 30 18:45:55 2006 for opencbm by  doxygen 1.4.2