Beispiel #1
0
int ARCH_MAINDECL main(int argc, char *argv[])
{
    d64copy_settings *settings = d64copy_get_default_settings();

    char *tm = NULL;
    char *src_arg;
    char *dst_arg;

    int  c;
    int  rv = 1;
    int  l;

    int src_is_cbm;
    int dst_is_cbm;

    struct option longopts[] =
    {
        { "help"       , no_argument      , NULL, 'h' },
        { "version"    , no_argument      , NULL, 'V' },
        { "warp"       , no_argument      , NULL, 'w' },
        { "no-warp"    , no_argument      , &settings->warp, 0 },
        { "quiet"      , no_argument      , NULL, 'q' },
        { "verbose"    , no_argument      , NULL, 'v' },
        { "no-progress", no_argument      , NULL, 'n' },
        { "interleave" , required_argument, NULL, 'i' },
        { "start-track", required_argument, NULL, 's' },
        { "end-track"  , required_argument, NULL, 'e' },
        { "transfer"   , required_argument, NULL, 't' },
        { "bam-only"   , no_argument      , NULL, 'b' },
        { "bam-save"   , no_argument      , NULL, 'B' },
        { "drive-type" , required_argument, NULL, 'd' },
        { "retry-count", required_argument, NULL, 'r' },
        { "two-sided"  , no_argument      , NULL, '2' },
        { "error-map"  , required_argument, NULL, 'E' },
        { NULL         , 0                , NULL, 0   }
    };

    const char shortopts[] ="hVwqbBt:i:s:e:d:r:2vnE:";

    while((c=getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
    {
        switch(c)
        {
            case 'h': help();
                      return 0;
            case 'V': printf("d64copy %s\n", OPENCBM_VERSION);
                      return 0;
            case 'w': settings->warp = 1;
                      break;
            case 'q': if(verbosity > 0) verbosity--;
                      break;
            case 'v': verbosity++;
                      break;
            case 'n': no_progress = 1;
                      break;
            case 'i': settings->interleave = arch_atoc(optarg);
                      break;
            case 's': settings->start_track = atoi(optarg);
                      break;
            case 'e': settings->end_track = atoi(optarg);
                      break;
            case 't': tm = optarg;
                      break;
            case 'b': settings->bam_mode = bm_allocated;
                      break;
            case 'B': settings->bam_mode = bm_save;
                      break;
            case 'd': if(strcmp(optarg, "1541") == 0)
                      {
                          settings->drive_type = cbm_dt_cbm1541;
                      }
                      else if(strcmp(optarg, "1571") == 0)
                      {
                          settings->drive_type = cbm_dt_cbm1571;
                      }
                      else if(strcmp(optarg, "1570") == 0)
                      {
                          settings->drive_type = cbm_dt_cbm1570;
                      }
                      else
                      {
                          settings->drive_type = atoi(optarg) != 0 ?
                              cbm_dt_cbm1571 : cbm_dt_cbm1541;
                      }
                      break;
            case 'r': settings->retries = atoi(optarg);
                      break;
            case '2': settings->two_sided = 1;
                      break;
            case 'E': l = strlen(optarg);
                      if(strncmp(optarg, "always", l) == 0)
                      {
                          settings->error_mode = em_always;
                      }
                      else if(strncmp(optarg, "on_errors", l) == 0)
                      {
                          settings->error_mode = em_on_error;
                      }
                      else if(strncmp(optarg, "never", l) == 0)
                      {
                          settings->error_mode = em_never;
                      }
                      else
                      {
                          hint(argv[0]);
                          return 1;
                      }
                      break;
            case 0:   break; // needed for --no-warp
            default : hint(argv[0]);
                      return 1;
        }
    }

    settings->transfer_mode = d64copy_get_transfer_mode_index(tm);
    if(settings->transfer_mode < 0)
    {
        char *modes = d64copy_get_transfer_modes();
        char *m;

        fprintf(stderr, "Unknown transfer mode: %s\nAvailable modes:\n", tm);

        for(m = modes; *m; m+=(strlen(m)+1))
        {
            fprintf(stderr, "  %s\n", m);
        }

        free(modes);
        return 1;
    }

    my_message_cb(3, "transfer mode is %d", settings->transfer_mode );

    if(optind + 2 != argc)
    {
        fprintf(stderr, "Usage: %s [OPTION]... [SOURCE] [TARGET]\n", argv[0]);
        hint(argv[0]);
        return 1;
    }

    src_arg = argv[optind];
    dst_arg = argv[optind+1];

    src_is_cbm = is_cbm(src_arg);
    dst_is_cbm = is_cbm(dst_arg);

    if(src_is_cbm == dst_is_cbm)
    {
        my_message_cb(0, "either source or target must be a CBM drive");
        return 1;
    }

    if(cbm_driver_open(&fd_cbm, 0) == 0)
    {
        /*
         * If the user specified auto transfer mode, find out
         * which transfer mode to use.
         */
        settings->transfer_mode = 
            d64copy_check_auto_transfer_mode(fd_cbm,
                settings->transfer_mode,
                atoi(src_is_cbm ? src_arg : dst_arg));

        my_message_cb(3, "decided to use transfer mode %d", settings->transfer_mode );

        signal(SIGINT, reset);

        if(src_is_cbm)
        {
            rv = d64copy_read_image(fd_cbm, settings, atoi(src_arg), dst_arg,
                    my_message_cb, my_status_cb);
        }
        else
        {
            rv = d64copy_write_image(fd_cbm, settings, src_arg, atoi(dst_arg),
                    my_message_cb, my_status_cb);
        }

        if(!no_progress && rv >= 0)
        {
            printf("\n%d blocks copied.\n", rv);
        }

        cbm_driver_close(fd_cbm);
        rv = 0;
    }
    else
    {
        arch_error(0, arch_get_errno(), "%s", cbm_get_driver_name(0));
    }

    free(settings);
    
    return rv;
}
Beispiel #2
0
int ARCH_MAINDECL main(int argc, char **argv)
{
    CBM_FILE fd;
    FILE *file;
    char *fname;

    int mode;
    int c;
    unsigned char *filedata;
    size_t filesize;
    char buf[48];
    int num_entries;
    int num_files;
    int rv;
    int i;
    int write;
    cbmcopy_settings *settings;
    char auto_name[17];
    char auto_type = '\0';
    char output_type = '\0';
    char *tail;
    char *ext;
    char *adapter = NULL;

    unsigned char drive;
    const char *tm = NULL;
    const char *dt = NULL;
    int force_raw = 0;
    int address = -1;
    const char *output_name = NULL;
    const char *address_str = NULL;
    char *fs_name;

    input_reader *readers[] =
    {
        &cbmwrite_raw,   /* must be first, as it is default */
        &cbmwrite_pc64,
        &cbmwrite_t64,
        NULL
    };

    input_reader *rd;

    struct option longopts[] =
    {
        { "help"            , no_argument      , NULL, 'h' },
        { "verbose"         , no_argument      , NULL, 'v' },
        { "adapter"         , required_argument, NULL, '@' },
        { "quiet"           , no_argument      , NULL, 'q' },
        { "version"         , no_argument      , NULL, 'V' },
        { "no-progress"     , no_argument      , NULL, 'n' },
        { "read"            , no_argument      , NULL, 'r' },
        { "write"           , no_argument      , NULL, 'w' },
        { "transfer"        , required_argument, NULL, 't' },
        { "drive-type"      , required_argument, NULL, 'd' },
        { "file-type"       , required_argument, NULL, 'f' },
        { "output"          , required_argument, NULL, 'o' },
        { "raw"             , no_argument      , NULL, 'R' },
        { "address"         , no_argument      , NULL, 'a' },
        { NULL              , 0                , NULL, 0   }
    };

    const char shortopts[] ="hVqvrwnt:d:f:o:Ra:@:";

    if(NULL == (tail = strrchr(argv[0], '/')))
    {
        tail = argv[0];
    }
    else
    {
        tail++;
    }
    if(strcmp(tail, "cbmread") == 0)
    {
        mode = 'r'; /* read */
    }
    else if(strcmp(tail, "cbmwrite") == 0)
    {
        mode = 'w'; /* write */
    }
    else
    {
        mode = EOF; /* mode must be given later */
    }

    settings = cbmcopy_get_default_settings();

    /* loop over cmd line opts */
    while((c=getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
    {
        switch(c)
        {
            case 'h': /* --help */
                help(argv[0]);
                return 0;
            case 'V': /* --version */
                printf("cbmcopy %s\n", OPENCBM_VERSION);
                return 0;
            case 'q': /* -- quiet */
                if(verbosity > sev_fatal)
                    verbosity--;
                break;
            case 'v': /* --verbose */
                if(verbosity < sev_debug)
                    verbosity++;
                break;
            case 'n': /* --no-progress */
                no_progress = 1;
                break;

            case 'r': /* --read */
            case 'w': /* --write */
                if(mode != EOF)
                {
                    my_message_cb(sev_fatal, "-r/-w given more than once");
                    hint(argv[0]);
                    return 1;
                }
                mode = c;
                break;

            case 't': /* --transfer */
                char_star_opt_once(&tm, "--transfer", argv);
                break;
            case 'd': /* --drive-type */
                char_star_opt_once(&dt, "--drive-type", argv);
                break;
            case 'o': /* --output */
                char_star_opt_once(&output_name, "--output", argv);
                break;
            case 'f': /* --file-type */
                output_type = (char) toupper(*optarg);
                break;
            case 'R': /* --raw */
                force_raw = 1;
                break;
            case 'a': /* override-address */
                char_star_opt_once(&address_str, "--address", argv);
                break;
            case '@': /* choose adapter */
                if (adapter == NULL)
                    adapter = cbmlibmisc_strdup(optarg);
                else {
                    my_message_cb(sev_fatal, "--adapter/-@ given more than once.");
                    hint(argv[0]);
                    exit(1);
                }
                break;
            default : /* unknown */
                hint(argv[0]);
                return 1;
        }
    }

    /* check -r/-w */
    switch(mode)
    {
        case 'r' :
            write = 0;
            break;
        case 'w' :
            write = 1;
            break;
        default:
            my_message_cb(sev_fatal,
                          "-r or -w must be given when started as `%s'",
                          argv[0]);
            hint(argv[0]);
            return 1;
    }

    /* check transfer mode */
    settings->transfer_mode = cbmcopy_get_transfer_mode_index(tm);
    if(settings->transfer_mode < 0)
    {
        my_message_cb(sev_fatal, "Unknown transfer mode: %s", tm);
        return 1;
    }

    /* check device type */
    if(dt)
    {
        const struct
        {
            const char *str;
            enum cbm_device_type_e type;
        }
        *p, types[] =
        {
            { "1541", cbm_dt_cbm1541 }, { "1571", cbm_dt_cbm1571 },
            { "1570", cbm_dt_cbm1570 }, { "1581", cbm_dt_cbm1581 },
            { NULL  , cbm_dt_unknown }
        };

        for(p = types; p->str && strcmp(dt, p->str); p++)
            ; /* nothing */

        if(!p->str)
        {
            my_message_cb(sev_fatal, "Unknown drive type: %s", dt);
            return 1;
        }
        settings->drive_type = p->type;
    }

    /* check CBM file type */
    if(output_type)
    {
        if(write)
        {
            if(strchr("DSPU", output_type) == NULL)
            {
                my_message_cb(sev_fatal, "Invalid file type : %c", output_type);
            }
        }
        else
        {
            my_message_cb(sev_warning, "--file-type ignored");
        }
    }

    /* check load address override */
    if(address_str)
    {
        address = strtol(address_str, &tail, 0);
        if(*tail || address < 0 || address > 0xffff)
        {
            my_message_cb(sev_fatal, "--address invalid: %s", address_str);
            hint(argv[0]);
            return 1;
        }
    }

    /* first non-option is device number */
    if(optind == argc)
    {
        my_message_cb(sev_fatal, "%s: No drive number given", argv[0]);
        hint(argv[0]);
        return 1;
    }

    drive = (unsigned char) strtol(argv[optind], &tail, 0);
    if(drive < 8 || drive > 11 || *tail)
    {
        my_message_cb(sev_fatal, "invalid drive: `%s'", argv[optind]);
        return 1;
    }

    /* remaining args are file names */
    num_files = argc - optind - 1;

    if(num_files == 0)
    {
        my_message_cb(sev_fatal, "%s: No files?", argv[0]);
        hint(argv[0]);
        return 1;
    }

    /* more than one file name given, avoid -o option */
    if(num_files > 1 && output_name)
    {
        my_message_cb(sev_fatal, "--output requires exactly one file name");
        return 1;
    }

    rv = cbm_driver_open_ex( &fd, adapter );
    cbmlibmisc_strfree(adapter);

    if(0 == rv)
    {
        fd_cbm = fd;

        /*
         * If the user specified auto transfer mode, find out
         * which transfer mode to use.
         */
        settings->transfer_mode = 
            cbmcopy_check_auto_transfer_mode(fd_cbm,
                settings->transfer_mode,
                drive);

        arch_set_ctrlbreak_handler(reset);

        while(++optind < argc)
        {
            fname = argv[optind];
            if(write)
            {
                rd = readers[0];

                file = fopen(fname, "rb");
                if(file)
                {
                    num_entries = 0;
                    if(!force_raw)
                    {
                        /* try to detect file format */
                        for(i = 1; readers[i] && !num_entries; i++)
                        {
                            num_entries =
                                readers[i]->probe( file, fname, my_message_cb );
                            if(num_entries)
                                rd = readers[i];
                        }
                    }
                    if(!num_entries) num_entries = 1; /* raw file */

                    for(i = 0; i < num_entries; i++)
                    {
                        my_message_cb( sev_debug,
                                       "processing entry %d from %s",
                                       i, fname );
                        if(rd->read(file, fname, i,
                                    auto_name, &auto_type,
                                    &filedata, &filesize, my_message_cb ) == 0)
                        {
                            buf[16] = '\0';
                            if(output_name)
                            {
                                strncpy(buf, output_name, 16);
                                cbm_ascii2petscii(buf);
                            }
                            else
                            {
                                /* no charset conversion */
                                strncpy(buf, auto_name, 16);
                            }
                            strcat(buf, ",x");
                            buf[strlen(buf)-1] =
                                output_type ? output_type : auto_type;
                            strcat(buf, ",W");

                            my_message_cb( sev_info,
                                           "writing %s -> %s", fname, buf );

                            if(address >= 0 && filesize > 1)
                            {
                                filedata[0] = address % 0x100;
                                filedata[1] = address / 0x100;

                                my_message_cb( sev_debug, 
                                               "override address: $%02x%02x",
                                               filedata[1], filedata[0] );

                            }
                            if(cbmcopy_write_file(fd, settings, drive,
                                                  buf, strlen(buf),
                                                  filedata, filesize,
                                                  my_message_cb,
                                                  my_status_cb) == 0)
                            {
                                printf("\n");
                                rv = cbm_device_status( fd, drive,
                                                        buf, sizeof(buf) );
                                my_message_cb( rv ?  sev_warning : sev_info,
                                               "%s", buf );
                            }
                            else
                                printf("\n");

                            if(filedata)
                            {
                                free(filedata);
                            }
                        }
                        else
                        {
                            my_message_cb( sev_warning,
                                           "error processing entry %d from %s",
                                           i, fname );
                        }
                    }
                }
                else
                {
                    my_message_cb( sev_warning,
                                   "warning could not read %s: %s",
                                   fname, arch_strerror(arch_get_errno()) );
                }
            }
            else
            {
                strncpy(buf, fname, 16);
                buf[16] = '\0';
                cbm_ascii2petscii(buf);

                if(output_name)
                {
                    fs_name = arch_strdup(output_name);
                }
                else
                {
                    for(tail = fname; *tail && *tail != ','; tail++);

                    ext = "prg"; /* default */

                    if(*tail)
                    {
                        tail++;
                        switch(*tail)
                        {
                            case 'D': ext = "del"; break;
                            case 'S': ext = "seq"; break;
                            case 'U': ext = "usr"; break;
                        }
                    }
                    fs_name = malloc(strlen(fname) + strlen(ext) + 2);
                    if(fs_name) sprintf(fs_name, "%s.%s", fname, ext);
                }

                if(fs_name)
                {
                    for(tail = fs_name; *tail; tail++)
                    {
                        if(*tail == '/') *tail = '_';
                    }
                }
                else
                {
                    /* should not happen... */
                    cbm_driver_close( fd );
                    my_message_cb(sev_fatal, "Out of memory");
                    exit(1);
                }

                my_message_cb( sev_info, "reading %s -> %s", buf, fs_name );

                if(cbmcopy_read_file(fd, settings, drive, buf, strlen(buf),
                                     &filedata, &filesize,
                                     my_message_cb, my_status_cb) == 0)
                {
                    rv = cbm_device_status( fd, drive, buf, sizeof(buf) );
                    my_message_cb( rv ? sev_warning : sev_info, "%s", buf );

                    file = fopen(fs_name, "wb");
                    if(file)
                    {
                        if(filedata)
                        {
                            if(address >= 0 && filesize > 1)
                            {
                                filedata[0] = address % 0x100;
                                filedata[1] = address / 0x100;

                                my_message_cb( sev_debug, 
                                               "override address: $%02x%02x",
                                               filedata[1], filedata[0] );
                            }
                            if(fwrite(filedata, filesize, 1, file) != 1)
                            {
                                my_message_cb(sev_warning,
                                              "could not write %s: %s",
                                              fs_name, arch_strerror(arch_get_errno()));
                            }
                        }
                        fclose(file);
                    }
                    else
                    {
                        my_message_cb(sev_warning,
                                      "could not open %s: %s",
                                      fs_name, arch_strerror(arch_get_errno()));
                    }

                    if(filedata)
                    {
                        free(filedata);
                    }
                }
                else
                {
                    my_message_cb(sev_warning, "error reading %s", buf);
                }
                if(fs_name)
                {
                    free(fs_name);
                }
            }
        }
        cbm_driver_close( fd );

        if(rv)
        {
            my_message_cb(sev_warning, "there was at least one error" );
        }
    }

    return rv;
}
Beispiel #3
0
        if( cbm_sendUxCommand(fd, drive, ResetVIA2ShiftRegConfig)
            != 0 ) break;
        if( cbm_sendUxCommand(fd, drive,      ResetUxVectorTable)
            != 0 ) break;

        if( cbm_exec_command(fd, drive, "I", 2)
            != 0 ) break;

        if(!berror && status)
        {
            cbm_device_status(fd, drive, cmd, sizeof(cmd));
            printf("%s\n", cmd);
        }
        cbm_driver_close(fd);
        cbmlibmisc_strfree(adapter);
        return 0;
    } while(0);
    else
    {
        arch_error(0, arch_get_errno(), "%s", cbm_get_driver_name_ex(adapter));
        cbmlibmisc_strfree(adapter);
        return 1;
    }
    // if the do{}while(0) loop is exited with a break, we get here
    arch_error(0, arch_get_errno(), "%s", cbm_get_driver_name_ex(adapter));
    cbm_reset(fd);
    cbmlibmisc_strfree(adapter);
    cbm_driver_close(fd);
    return 1;
}