Exemplo n.º 1
0
/*! \brief Write/Change data to/in the configuration file

 This function searches for a specific entry in the configuration
 file and changes it if it exists. If it does not exist, a new
 entry is generated.

 \param Handle
   Handle to the opened configuration file, as obtained from
   opencbm_configuration_open().
 
 \param Section
   A string which holds the name of the section where to set the data.

 \param Entry
   A string which holds the name of the entry to set.

 \param Value
   A buffer which holds the value of the entry which is to be set.

 \return
   0 if the data could be written,
   1 otherwise 
*/
int
opencbm_configuration_set_data(opencbm_configuration_handle Handle,
                               const char Section[], const char Entry[],
                               const char Value[])
{
    unsigned int error = 1;

    do {
        char * newValue = NULL;

        opencbm_configuration_entry_t * entry =
            opencbm_configuration_find_data(Handle, Section, Entry, 1);

        if (entry == NULL) {
            break;
        }

        Handle->Changed = 1;

        newValue = cbmlibmisc_strdup(Value);

        if (newValue == NULL) {
            break;
        }

        cbmlibmisc_strfree(entry->Value);
        entry->Value = newValue;

        error = 0;

    } while (0);

    return error;
}
Exemplo n.º 2
0
/*! \brief Read data from the configuration file

 This function searches for a specific enty in the configuration
 file and returns the value found there.

 \param Handle
   Handle to the opened configuration file, as obtained from
   opencbm_configuration_open().
 
 \param Section
   A string which holds the name of the section from where to get the data.

 \param Entry
   A string which holds the name of the entry to get.

 \param ReturnBuffer
   A buffer which holds the return value on success. If the function returns
   with something different than 0, the buffer pointer to by ReturnBuffer will
   not be changed.
   Can be NULL, cf. note below.

 \return
   Returns 0 if the data entry was found. If ReturnBufferLength != 0, the
   return value is 0 only if the buffer was large enough to hold the data.

 \note
   If ReturnBuffer is NULL, this function only tests if the Entry exists
   in the given Section. In this case, this function returns 0; otherwise, it
   returns 1.
*/
int
opencbm_configuration_get_data(opencbm_configuration_handle Handle,
                               const char Section[], const char Entry[],
                               char ** ReturnBuffer)
{
    unsigned int error = 1;

    do {
        opencbm_configuration_entry_t * entry =
            opencbm_configuration_find_data(Handle, Section, Entry, 0);

        if (entry == NULL) {
            break;
        }

        /* If ReturnBufferLength is 0, we only wanted to find out if 
         * that entry existed. Thus, report "no error" and quit.
         */

        if (ReturnBuffer != 0) {

            char * p = cbmlibmisc_strdup(entry->Value);

            if (p != NULL) {
                *ReturnBuffer = p;
                error = 0;
            }
        }

    } while (0);

    return error;
}
Exemplo n.º 3
0
/*! \brief \internal allocate memory for a new configuration entry

 \param CurrentSection
   Pointer to the current section to which this entry is to be added.

 \param PreviousEntry
   Pointer to the previous entry. That is, the new entry will be added
   after this entry.
   If this is given as NULL, the new entry will be added as the first
   one.

 \param EntryName
   The name of the entry which is to be allocated. That is, this
   is the left-hand side of the equal sign.
   If this is given as NULL, there is no real entry available, but
   an (incorrect) line without an equal sign.

 \param Value
   The value of the entry. That is, this is the right-hand side of
   the equal sign (excluding the commentary).

 \param Comment
   The (optional) comment on this line. All characters (including
   whitespace and the comment delimiter '#') are included.

 \return 
   Pointer to the new configuration entry.
   NULL if we run out of memory.

 \remark
   If any of the parameters Value or Comment are given as NULL, there
   is an empty string allocated for them, anyway.
   This is not true for the parameter EntryName.
*/
static opencbm_configuration_entry_t *
entry_alloc_new(opencbm_configuration_section_t * CurrentSection,
                opencbm_configuration_entry_t * PreviousEntry,
                const char * EntryName,
                const char * Value,
                const char * Comment)
{
    opencbm_configuration_entry_t * newEntry = NULL;

    assert(CurrentSection != NULL);

    do {
        newEntry = malloc(sizeof(*newEntry));

        if (newEntry == NULL)
            break;

        memset(newEntry, 0, sizeof(*newEntry));
        newEntry->Comment = cbmlibmisc_strdup(Comment);
        newEntry->Name = cbmlibmisc_strdup(EntryName);
        newEntry->Next = NULL;

        if (Value) {
            newEntry->Value = cbmlibmisc_strdup(Value);
        }
        else {
            newEntry->Value = NULL;
        }

        if (PreviousEntry != NULL) {
            PreviousEntry->Next = newEntry;
        }
        else {
            newEntry->Next          = CurrentSection->Entries;
            CurrentSection->Entries = newEntry;
        }

    } while (0);

    return newEntry;
}
Exemplo n.º 4
0
/*! \brief \internal allocate memory for a new configuration section

 \param Configuration
   Pointer to the configuration file structure to which this
   section is to be added.

 \param PreviousSection
   Pointer to the previous section. That is, the new section will be
   added after this entry.
   If this is given as NULL, the new section will be added as the first
   one.

 \param SectionName
   The name of the section which is to be allocated. That is, this
   is the name between the brackets [...] in the configuration file.
   If this is given as NULL, this is the special "first" section,
   which is an unnamed "global" section.

 \param Comment
   The (optional) comment on this line. All characters (including
   whitespace and the comment delimiter '#') are included.

 \return 
   Pointer to the new configuration section.
   NULL if we run out of memory.

 \remark
   If Comment is given as NULL, there is an empty string allocated
   for it, anyway.
   This is not true for the parameter SectionName.
*/
static opencbm_configuration_section_t *
section_alloc_new(opencbm_configuration_t * Configuration,
                  opencbm_configuration_section_t * PreviousSection,
                  const char * const SectionName,
                  const char * const Comment)
{
    opencbm_configuration_section_t * newSection = NULL;

    do {
        newSection = malloc(sizeof(*newSection));

        if (newSection == NULL) {
            break;
        }

        memset(newSection, 0, sizeof(*newSection));
        newSection->Entries = NULL;
        newSection->Comment = cbmlibmisc_strdup(Comment);
        newSection->Next = NULL;

        if (SectionName) {
            newSection->Name = cbmlibmisc_strdup(SectionName);
        }
        else {
            newSection->Name = NULL;
        }

        if (PreviousSection != NULL) {
            PreviousSection->Next = newSection;
        }
        else {
            newSection->Next        = Configuration->Sections;
            Configuration->Sections = newSection;
        }

    } while (0);

    return newSection;
}
Exemplo n.º 5
0
/*! \brief Open the configuration file

 Opens the configuration file so it can be used later on with
 opencbm_configuration_get_data(). If the file does not exist,
 this function fails.

 \param Filename
   The name of the configuration file to open

 \return
   Returns a handle to the configuration file which can be used
   in subsequent calls to the other configuration file functions
   for reading. Write operations are not allowed after using
   this function.

   If the configuration file does not exist, this function
   returns NULL.
*/
opencbm_configuration_handle
opencbm_configuration_open(const char * Filename)
{
    opencbm_configuration_handle handle;
    unsigned int error = 1;

    FILE * configFile = NULL;

    do {
        handle = malloc(sizeof(*handle));

        if (!handle) {
            break;
        }

        memset(handle, 0, sizeof(*handle));

        handle->Sections = NULL;

        handle->FileName = cbmlibmisc_strdup(Filename);
        handle->FileNameForWrite = cbmlibmisc_strcat(handle->FileName, ".tmp");
        handle->Changed = 0;

        if ( (handle->FileName == NULL) || (handle->FileNameForWrite == NULL)) {
            break;
        }

        configFile = fopen(handle->FileName, "rt");

        if (configFile == NULL) {
            break;
        }

        opencbm_configuration_parse_file(handle, configFile);

        fclose(configFile);

        error = 0;

    } while (0);

    if (error && handle) {
        cbmlibmisc_strfree(handle->FileName);
        cbmlibmisc_strfree(handle->FileNameForWrite);
        free(handle);
        handle = NULL;
    }

    return handle;
}
Exemplo n.º 6
0
Arquivo: main.c Projeto: bogde/OpenCBM
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;
}
Exemplo n.º 7
0
int ARCH_MAINDECL main(int argc, char *argv[])
{
    int status = 0, id_ofs = 0, name_len, i;
    CBM_FILE fd;
//    unsigned char drive, tracks = 35, bump = 1, orig = 0, show_progress = 0;
    unsigned char drive, tracks = 35, bump = 1, orig = 0x4b, show_progress = 0;
    char cmd[40], name[20], *arg;
    int erroroccured = 0;
    char *adapter = NULL;
    int option;

    struct option longopts[] =
    {
        { "help"       , no_argument      , NULL, 'h' },
        { "version"    , no_argument      , NULL, 'V' },
        { "adapter"    , required_argument, NULL, '@' },
        { "no-bump"    , no_argument      , NULL, 'n' },
        { "extended"   , no_argument      , NULL, 'x' },
//        { "original"   , no_argument      , NULL, 'o' },
{ "fill"  , required_argument, NULL, 'f' },

        { "status"     , no_argument      , NULL, 's' },
        { "progress"   , no_argument      , NULL, 'p' },

        /* undocumented */
        { "end-track"  , required_argument, NULL, 't' },
        { NULL         , 0                , NULL, 0   }
    };

//    const char shortopts[] ="hVnxospt:";
    const char shortopts[] ="hVnxf:spt:";


    while((option = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
    {
        switch(option)
        {
            case 'n': bump = 0;
                      break;
            case 'f': //orig = 0x4b;
orig=arch_atoc(optarg);
                      break;
            case 's': status = 1;
                      break;
            case 'x': tracks = 40;
                      break;
            case 'h': help();
                      return 0;
            case 'V': printf("frm_analyzer %s\n", OPENCBM_VERSION);
                      return 0;
            case 'p': show_progress = 1;
                      break;
            case 't': tracks = arch_atoc(optarg);
                      break;
            case '@': if (adapter == NULL)
                          adapter = cbmlibmisc_strdup(optarg);
                      else
                      {
                          fprintf(stderr, "--adapter/-@ given more than once.");
                          hint(argv[0]);
                          return 1;
                      }
                      break;
            default : hint(argv[0]);
                      return 1;
        }
    }

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

    arg = argv[optind++];
    drive = arch_atoc(arg);
    if(drive < 8 || drive > 11)
    {
        fprintf(stderr, "Invalid drive number (%s)\n", arg);
        return 1;
    }
    
    arg      = argv[optind++];
    name_len = 0;
    while(*arg)
    {
        unsigned char c;
        c = (unsigned char) toupper(*arg);
        if(c == ',')
        {
            if(id_ofs)
            {
                fprintf(stderr, "More than one `,' in disk name\n");
                return 1;
            }
            id_ofs = name_len;
        }
        name[name_len++] = c;
        if(name_len > 19)
        {
            fprintf(stderr, "Disk name too long\n");
            return 1;
        }
        arg++;
    }
    name[name_len] = 0;

    if(cbm_driver_open_ex(&fd, adapter) == 0)
    {
        cbm_upload(fd, drive, 0x0300, dskfrmt, sizeof(dskfrmt));
        sprintf(cmd, "M-E%c%c%c%c%c%c0:%s", 3, 3, tracks + 1, 
                orig, bump, show_progress, name);
        cbm_exec_command(fd, drive, cmd, 11+strlen(name));
#if 0
        if(show_progress)
        {
            /* do some handshake */
            cbm_iec_release(fd, IEC_CLOCK);
            for(i = 1; i <= tracks; i++)
            {
                cbm_iec_wait(fd, IEC_DATA, 1);
                cbm_iec_set(fd, IEC_CLOCK);
                cbm_iec_wait(fd, IEC_DATA, 0);
                cbm_iec_release(fd, IEC_CLOCK);

                printf("#");
                fflush(stdout);
            }
            printf("\n");
        }
#endif
        erroroccured = cbm_device_status(fd, drive, cmd, sizeof(cmd));

        if(erroroccured && status)
        {
            printf("%s\n", cmd);
        }

        if(!erroroccured && (tracks > 35))
        {
            cbm_open(fd, drive, 2, "#", 1);
            cbm_exec_command(fd, drive, "U1:2 0 18 0", 11);
            cbm_exec_command(fd, drive, "B-P2 192", 8);
            cbm_listen(fd, drive, 2);
            while(tracks > 35)
            {
                cbm_raw_write(fd, "\021\377\377\001", 4);
                tracks--;
            }
            cbm_unlisten(fd);
            cbm_exec_command(fd, drive, "U2:2 0 18 0", 11);
            cbm_close(fd, drive, 2);
        }

        if(!erroroccured && status)
        {
            cbm_device_status(fd, drive, cmd, sizeof(cmd));
            printf("%s\n", cmd);
        }
#if 1   // verbose output
        {
#if 0 // @TODO unused variables
            float RPMval;
            int sectors, virtGAPsze, remainder, trackTailGAP, flags, retry, lastTr;
            const char *vrfy;
#endif
            unsigned char data[0x100];
            if (cbm_download(fd, drive, 0x0500, data, sizeof(data)) == sizeof(data))
            {


#if 1
                // TODO, Pattern analyzer, get the lenght of the PLL synchronization period
                //
                    // search the last byte triple consisting of: 0x49, 0x24, 0x92
                    // 
                int k;
                const unsigned char pattern[]={0x49, 0x24, 0x92};
                // const unsigned char pattern[]={0xdb, 0x6d, 0xb6};

                for(k=sizeof(data)-3; k>=0; --k)
                {
                    if(data[k]==pattern[0] && data[k+1]==pattern[1] && data[k+2]==pattern[2]) break;
                }
                if(k<0)
                {
                    // no part of the written sequence was found
                    k=sizeof(data);
                }
                else
                {    
                        // now search the beginning of that "010010010010010010010010..." bit stream
                    while(k>=0 && data[k]==pattern[0] && data[k+1]==pattern[1] && data[k+2]==pattern[2])
                    {
                        k-=3;
                    }
                    k+=3;
    
                        // do single byte decreases
                    if(k>=1 && data[k-1]==pattern[2]) --k;
                    if(k>=1 && data[k-1]==pattern[1]) --k;
                    if(k>=1 && data[k-1]==pattern[0]) --k;
                }

                printf("Result with Pattern: 0x%02X / %3d, formatted on track %2d, PLL synchronization length: %3d\n", orig, orig, tracks, k);


                for (i=0; i < sizeof(data); i++)
                {
                    /*
                    if(data[i] == 0)
                    {
                        printf("\n");
                        break;
                    }
                    */
                    printf(" %02X", data[i]);
                    if((i&0x0f) == 0x0f) printf("\n");
                }
#else
                int i;
                printf("Track|Retry|sctrs|slctd|| GAP |modulo |modulo|tail| Verify  | RPM  |\n"
                       "     |     |     | GAP ||adjst|complmt| dvsr |GAP |         |      |\n"
                       "-----+-----+-----+-----++-----+-------+------+----+---------+------+\n");

                lastTr=-1;
                for (i=0; i < sizeof(data); i+=4)
                {
                    if(data[i]==0) break;    // no more data is available


                    if(data[i+3]>=0x40 && data[i]>42){
                            // logging continuation line
                        printf("     |     | debug log || $%02X | $%02X $%02X $%02X\n",
                               data[i], data[i+1], data[i+2], data[i+3]);
                        continue;    // proceed with next loop run
                        }


                    if(data[i]==lastTr) retry++;
                    else                retry=0;
                    lastTr=data[i];

                    if(data[i]>=25)            // preselect track dependent constants
                    {
                        if(data[i]>=31) sectors=17, RPMval=60000000.0f/16;
                        else            sectors=18, RPMval=60000000.0f/15;
                    }
                    else
                    {
                        if(data[i]>=18) sectors=19, RPMval=60000000.0f/14;
                        else            sectors=21, RPMval=60000000.0f/13;
                    }

                        // separate some flags
                    flags=(data[i+3]>>6)&0x03;
                    data[i+3]&=0x3f;

                    switch(flags)
                    {
                        case 0x01: vrfy="SYNC fail"; break;
                        case 0x02: vrfy="verify OK"; break;
                        case 0x03: vrfy="vrfy fail"; break;
                        default:   vrfy="   ./.   ";
                    }

                        // recalculation of the track tail GAP out of the
                        // choosen GAP for this track, the new GAP size
                        // adjustment and the complement of the remainder
                        // of the adjustment division

                    virtGAPsze=data[i+1]         -3;    // virtual GAP increase to
                        // prevent reformatting, when only one byte is missing


                    remainder=((data[i+2]==0xff) ? virtGAPsze : sectors)
                                 - data[i+3];


                    trackTailGAP=((data[i+2]==0xff) ? 0 : data[i+2]*sectors + virtGAPsze)
                                    + remainder;

                        // the following constants are nybble based (double the
                        // size of the well known constants for SYNC lengths,
                        // block header size, data block GAP and data block)
                        //
                        // (0x01&data[i+1]&sectors) is a correction term, if "half
                        // GAPs" are written and the number of sectors is odd
                        //
                    // RPMval / (sectors * (10+20+18+10 + 650 + data[i+1]) - (0x01&data[i+1]&sectors) + trackTailGAP - data[i+1])

                    RPMval = (flags != 0x01) ?
                        RPMval / (sectors * (10+20+18+10 + 650 + data[i+1]) - (0x01&data[i+1]&sectors) + trackTailGAP - data[i+1])
                        : 0;

                    printf(" %3u | ", data[i]);
                    if(retry>0) printf("%3u", retry);
                    else        printf("   ");
                   /*      " |sctrs |slctd  || GAP   |modulo   |modulo  |tail | Verify  | RPM  |\n"
                    *      " |      | GAP   ||adjst  |complmt  |        |GAP  |         |      |\n"
                    *      "-+----- +-----  ++-----  +-------  +------  +---- +---------+------+\n"
                    */
                    printf(" |  %2u | $%02X || $%02X |   $%02X |  $%02X |$%03X|%9s|%6.2f|\n",
                           sectors, data[i+1], data[i+2], data[i+3],
                           remainder, trackTailGAP, vrfy, RPMval);
                }
                printf("\n  *) Note: All GAP based numbers shown here (sedecimal values) are\n"
                         "           nybble based (4 GCR Bits) instead of GCR byte based.\n");
#endif
            }
            else
            {
Exemplo n.º 8
0
//
// main function 
//
int ARCH_MAINDECL main(int argc, char *argv[])
{
    imgcopy_settings *settings = imgcopy_get_default_settings();

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

    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' },
        { "adapter"    , required_argument, NULL, '@' },
        { "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' },
        { "one-sided"  , no_argument      , NULL, '1' },
        { "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("imgcopy %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, "8050") == 0)
                      {
                          settings->drive_type = cbm_dt_cbm8050;
                      }
                      else if(strcmp(optarg, "8250") == 0)
                      {
                          settings->drive_type = cbm_dt_cbm8250;
                      }
                      else if(strcmp(optarg, "1001") == 0)
                      {
                          settings->drive_type = cbm_dt_sfd1001;
                      }
                      else if(strcmp(optarg, "1001") == 0)
                      {
                          settings->drive_type = cbm_dt_sfd1001;
                      }
                      else 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, "1581") == 0)
                      {
                          settings->drive_type = cbm_dt_cbm1581;
                      }
                      else if(strcmp(optarg, "2031") == 0)
                      {
                          settings->drive_type = cbm_dt_cbm2031;
                      }
                      else if(strcmp(optarg, "2040") == 0)
                      {
                          settings->drive_type = cbm_dt_cbm2040;
                      }
                      else if(strcmp(optarg, "3040") == 0)
                      {
                          settings->drive_type = cbm_dt_cbm3040;
                      }
                      else if(strcmp(optarg, "4031") == 0)
                      {
                          settings->drive_type = cbm_dt_cbm4031;
                      }
                      else if(strcmp(optarg, "4040") == 0)
                      {
                          settings->drive_type = cbm_dt_cbm4040;
                      }
                      else
                      {
                          settings->drive_type = atoi(optarg) != 0 ?
                              cbm_dt_cbm8250 : cbm_dt_cbm8050;
                      }
                      break;
            case 'r': settings->retries = atoi(optarg);
                      break;
            case '1': settings->two_sided = 0;
                      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 '@': if (adapter == NULL)
                          adapter = cbmlibmisc_strdup(optarg);
                      else
                      {
                          my_message_cb(sev_fatal, "--adapter/-@ given more than once.");
                          hint(argv[0]);
                          exit(1);
                      }
                      break;
            case 0:   break; // needed for --no-warp
            default : hint(argv[0]);
                      return 1;
        }
    }

	//printf("transfermode: %s\n", tm);
	settings->transfer_mode = imgcopy_get_transfer_mode_index(tm);
	if(settings->transfer_mode < 0)
	{
	    char *modes = imgcopy_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_ex(&fd_cbm, adapter) == 0)
    {
        /*
         * If the user specified auto transfer mode, find out
         * which transfer mode to use.
         */
        settings->transfer_mode = 
            imgcopy_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 );

        arch_set_ctrlbreak_handler(reset);

        if(src_is_cbm)
        {
            rv = imgcopy_read_image(fd_cbm, settings, atoi(src_arg), dst_arg,
                    my_message_cb, my_status_cb);
        }
        else
        {
            rv = imgcopy_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_ex(adapter));
    }

    cbmlibmisc_strfree(adapter);
    free(settings);
    
    return rv;
}
Exemplo n.º 9
0
/*! \brief \internal Parse the configuration file

 This function parses the configuration file and records its contents
 into the internal opencbm_configuration_handle structure.

 \param Handle
   Handle to the configuration file.

 \param ConfigFile
   Pointer to an opened FILE structure for the file to be read.

 \return 
   0 if the parsing succeeded,
   1 otherwise.
*/
static int
opencbm_configuration_parse_file(opencbm_configuration_handle Handle, FILE * ConfigFile)
{
    int error = 1;

    do {
        opencbm_configuration_section_t * currentSection = NULL;
        opencbm_configuration_entry_t   * previousEntry  = NULL;
        char                            * line           = NULL;

        /* First, check if we successfully opened the configuration file */

        if (Handle == NULL)
            break;

        assert(ConfigFile != NULL);

        /* Seek to the beginning of the file */

        fseek(ConfigFile, 0, SEEK_SET);


        Handle->Sections = section_alloc_new(Handle, NULL, NULL, "");
        if (Handle->Sections == NULL) {
            break;
        }

        currentSection = Handle->Sections;

        /* Now, search section after section */

        do {
            char * comment = NULL;

            if (line) {
                cbmlibmisc_strfree(line);
            }

            line = configuration_read_line(Handle, &comment, ConfigFile);

            /* assume an error, if not cleared later */

            error = 1;

            if (line == NULL && comment == NULL) {

                /* The end of the file has been reached */

                error = 0;
                break;
            }

            /* Check if we found a new section */

            if (line && (line[0] == '['))
            {
                char * sectionName = NULL;
                char * p;

                sectionName = cbmlibmisc_strdup(&line[1]);
                if (sectionName == NULL)
                    break;

                p = strrchr(sectionName, ']');

                /* This is tricky. If the current line has no closing bracket,
                 * we will ignore this. Thus, this function will "correct"
                 * this error. Note that this correction can be performed in
                 * an incorrect way. However, changes are higher the user
                 * will recognise this change and find out that he has done
                 * something wrong.
                 */
                if (p != 0) {
                    *p = 0;
                }

                /* a new section starts */

                currentSection = section_alloc_new(Handle, currentSection, sectionName, comment);
                cbmlibmisc_strfree(sectionName);

                if (currentSection == NULL) {
                    break;
                }

                /* make sure to add the new entries to this section, not after
                 * the last entry of the previous section
                 */
                previousEntry = NULL;

                error = 0;
            }
            else {
                char * entryName = NULL;
                char * value = NULL;

                /* this line is (still) part of the current section */

                if (line) {
                    char * p;

                    /* process the entry */

                    p = strchr(line, '=');

                    if (p == NULL) {

                        /* the line is not formatted correctly. It is no real entry! */

                        value = cbmlibmisc_strdup(line);
                    }
                    else {
                        /* split the line into entry name and value */

                        *p = 0;
                        entryName = cbmlibmisc_strdup(line);
                        value = cbmlibmisc_strdup(p+1);
                    }
                }

                previousEntry = entry_alloc_new(currentSection, previousEntry,
                    entryName, value, comment);

                cbmlibmisc_strfree(entryName);
                cbmlibmisc_strfree(value);
                cbmlibmisc_strfree(comment);
                comment = NULL;

                if (previousEntry == NULL) {
                    break;
                }

                error = 0;
            }

            cbmlibmisc_strfree(comment);

        } while ( ! error);

        if (line) {
            cbmlibmisc_strfree(line);
        }

    } while (0);

    return error;
}
Exemplo n.º 10
0
/*! \brief \internal Read a complete line from a file
 @@@@@
*/
static char *
read_a_complete_line(FILE * File)
{
    char * buffer = NULL;
    char * addbuffer = NULL;

    unsigned int error = 1;

    do {
        unsigned int bufferLength;

        addbuffer = cbmlibmisc_stralloc(ASSUMED_MAX_LINE_LENGTH);

        if (addbuffer == NULL) {
            break;
        }

        if (fgets(addbuffer, ASSUMED_MAX_LINE_LENGTH, File) == NULL) {

            /* error or EOF, quit */

            error = ferror(File) ? 1 : 0;
            break;
        }

        /* add the addbuffer to the buffer */

        if (buffer == NULL) {
            buffer = addbuffer;
            addbuffer = NULL;
        }
        else {
            char * tmpbuffer = cbmlibmisc_strcat(buffer, addbuffer);

            cbmlibmisc_strfree(addbuffer);
            addbuffer = NULL;

            cbmlibmisc_strfree(buffer);

            buffer = tmpbuffer;

            if (tmpbuffer == NULL) {
                break;
            }

        }

        /* If there is a newline, the line is complete */

        bufferLength = strlen(buffer);

        if ( (bufferLength > 0) && buffer[bufferLength - 1] == '\n')
        {
            buffer[bufferLength - 1] = 0;

            error = 0;
            break;
        }
    } while (1);

    if (error) {
        cbmlibmisc_strfree(buffer);
        buffer = NULL;
    }
    else {

        if (buffer == NULL) {
            buffer = cbmlibmisc_strdup("");
        }
    }

    cbmlibmisc_strfree(addbuffer);

    return buffer;
}
Exemplo n.º 11
0
int ARCH_MAINDECL main(int argc, char *argv[])
{
    int status = 0, id_ofs = 0, name_len;
    CBM_FILE fd;
    unsigned char drive, starttrack = 1, endtrack = 35, bump = 1, orig = 0;
    unsigned char verify = 0, demagnetize = 0, retries = 7;
    char cmd[40], name[20], *arg;
    struct FormatParameters parmBlock;
    int berror = 0;
    char *adapter = NULL;
    int option;

    struct option longopts[] =
    {
        { "help"       , no_argument      , NULL, 'h' },
        { "version"    , no_argument      , NULL, 'V' },
        { "adapter"    , required_argument, NULL, '@' },
        { "no-bump"    , no_argument      , NULL, 'n' },
        { "extended"   , no_argument      , NULL, 'x' },
        { "original"   , no_argument      , NULL, 'o' },
        { "status"     , no_argument      , NULL, 's' },
        { "verify"     , no_argument      , NULL, 'v' },
        { "clear"      , no_argument      , NULL, 'c' },
        { "retries"    , required_argument, NULL, 'r' },

        /* undocumented */
        { "fillpattern", required_argument, NULL, 'f' },
        { "begin-track", required_argument, NULL, 'b' },
        { "end-track"  , required_argument, NULL, 'e' },
        { NULL         , 0                , NULL, 0   }
    };

    const char shortopts[] ="hVnxosvcr:f:b:e:@:";

    while((option = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
    {
        switch(option)
        {
            case 'n': bump = 0;
                      break;
            case 'o': orig = 0x4b;
                      break;
            case 's': status = 1;
                      break;
            case 'x': starttrack =  1;
                      endtrack   = 40;
                      break;
            case 'h': help();
                      return 0;
#ifdef CBMFORNG
            case 'V': printf("cbmforng %s\n", OPENCBM_VERSION);
#else
            case 'V': printf("cbmformat %s\n", OPENCBM_VERSION);
#endif
                      return 0;
            case 'v': verify = 1;
                      break;
            case 'c': demagnetize = 1;
                      break;
            case 'r': retries = arch_atoc(optarg);
                      if(retries<1)       retries= 1;
                      else if(retries>63) retries=63;
                      break;

            case 'f': orig = arch_atoc(optarg);
                      break;
            case 'b': starttrack = arch_atoc(optarg);
                      break;
            case 'e': endtrack = arch_atoc(optarg);
                      break;
            case '@': if (adapter == NULL)
                          adapter = cbmlibmisc_strdup(optarg);
                      else
                      {
                          fprintf(stderr, "--adapter/-@ given more than once.");
                          hint(argv[0]);
                          return 1;
                      }
                      break;
            default : hint(argv[0]);
                      return 1;
        }
    }

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

    arg = argv[optind++];
    drive = arch_atoc(arg);
    if(drive < 8 || drive > 11)
    {
        fprintf(stderr, "Invalid drive number (%s)\n", arg);
        return 1;
    }
    
    arg      = argv[optind++];
    name_len = 0;
    while(*arg)
    {
        unsigned char c;
        c = (unsigned char) toupper(*arg);
        if(c == ',')
        {
            if(id_ofs)
            {
                fprintf(stderr, "More than one `,' in disk name\n");
                return 1;
            }
            id_ofs = name_len;
        }
        name[name_len++] = c;
        if(name_len > 19)
        {
            fprintf(stderr, "Disk name too long\n");
            return 1;
        }
        arg++;
    }
    name[name_len] = 0;

    if(name_len - id_ofs != 3)
    {
        fprintf(stderr, "Missing `,' in disk name or ID field not equal to two characters\n");
        return 1;
    }

    if(cbm_driver_open_ex(&fd, adapter) == 0)
    {
        cbm_upload(fd, drive, 0x0300, dskfrmt, sizeof(dskfrmt));


        prepareFmtPattern(&parmBlock, orig, endtrack, name[id_ofs+1], name[id_ofs+2]);
        parmBlock.P_STRCK=starttrack;   // start track parameter
        parmBlock.P_ETRCK=endtrack+1;   // end track parameter
        parmBlock.P_RETRY=(retries & ~0xC0) | (bump?0x40:0xC0);
                                        // number of retries (per disk, not per track)
        parmBlock.P_DOBMP=bump;         // flag, if an initial head bump should be done
        parmBlock.P_DEMAG=demagnetize;  // flag, if the disk should be demagnetized
        parmBlock.P_VRIFY=verify;       // flag, if the disk should be verified

#if 0       // for checking the generated format patterns
{
    int j,k;
    for(j=0;j<34;j+=5)
    {
        for(k=0;k<5;k++)
        {
            printf(" $%02X", ((char *)(&parmBlock))[j+k]&0xFF);
        }
        printf("\n");
    }
    printf(" $%02X\n", ((char *)(&parmBlock))[j]&0xFF);
}
#endif
        cbm_upload(fd, drive, 0x0200 - sizeof(parmBlock), ((char *)(&parmBlock)), sizeof(parmBlock));

        sprintf(cmd, "M-E%c%c0:%s", 3, 3, name);
        cbm_exec_command(fd, drive, cmd, 7+name_len);
        berror = cbm_device_status(fd, drive, cmd, sizeof(cmd));

        if(berror && status)
        {
            printf("%s\n", cmd);
        }

#if defined(DebugFormat) && DebugFormat!=0  // verbose output
        {
            float RPMval;
            int sectors, virtGAPsze, remainder, trackTailGAP, flags, retry = 0, lastTr;
            const char *vrfy;
            unsigned char data[0x100];

                // in case of an error, get the logging buffer from 0x0700 instead of 0x0500
            if (cbm_download(fd, drive, berror?0x0700:0x0500, data, sizeof(data)) == sizeof(data))
            {
                int i;
                printf("Track|Retry|sctrs|slctd|| GAP |modulo |modulo|tail| Verify  | RPM  |\n"
                       "     |     |     | GAP ||adjst|complmt| dvsr |GAP |         |      |\n"
                       "-----+-----+-----+-----++-----+-------+------+----+---------+------+\n");

                lastTr=-1;
                for (i=0; i < sizeof(data); i+=4)
                {
                    if(data[i]==0) break;   // no more data is available

                    if(data[i]==lastTr) retry++;
                    else                retry=0;
                    lastTr=data[i];

                    if(data[i]>=25)         // preselect track dependent constants
                    {
                        if(data[i]>=31) sectors=17, RPMval=60000000.0f/16;
                        else            sectors=18, RPMval=60000000.0f/15;
                    }
                    else
                    {
                        if(data[i]>=18) sectors=19, RPMval=60000000.0f/14;
                        else            sectors=21, RPMval=60000000.0f/13;
                    }

                        // separate some flags
                    flags=(data[i+3]>>6)&0x03;
                    data[i+3]&=0x3f;

                    switch(flags)
                    {
                        case 0x01: vrfy="SYNC fail"; break;
                        case 0x02: vrfy="   OK    "; break;
                        case 0x03: vrfy="vrfy fail"; break;
                        default:   vrfy="   ./.   ";
                    }

                        // recalculation of the track tail GAP out of the
                        // choosen GAP for this track, the new GAP size
                        // adjustment and the complement of the remainder
                        // of the adjustment division

                    virtGAPsze=data[i+1]        -5; // virtual GAP increase to
                        // prevent reformatting, when only one byte is missing
                        // and other offset compensations


                    remainder=((data[i+2]==0xff) ? virtGAPsze : sectors)
                                 - data[i+3];


                    trackTailGAP=((data[i+2]==0xff) ? 0 : data[i+2]*sectors + virtGAPsze)
                                 + remainder;

                        // the following constants are nybble based (double the
                        // size of the well known constants for SYNC lengths,
                        // block header size, data block GAP and data block)
                        //
                        // (0x01&data[i+1]&sectors) is a correction term, if "half
                        // GAPs" are written and the number of sectors is odd
                        //
                    // RPMval / (sectors * (10+20+18+10 + 650 + data[i+1]) - (0x01&data[i+1]&sectors) + trackTailGAP - data[i+1])

                    RPMval = (flags != 0x01) ?
                        RPMval / (sectors * (10+20+18+10 + 650 + data[i+1]) - (0x01&data[i+1]&sectors) + trackTailGAP - data[i+1])
                        : 0;

                    printf(" %3u | ", data[i]);
                    if(retry>0) printf("%3u", retry);
                    else        printf("   ");

                   /*      " |sctrs |slctd   || GAP    |modulo    |modulo   |tail | Verify  | RPM  |\n"
                    *      " |      | GAP    ||adjst   |complmt   |         | GAP |         |      |\n"
                    *      "-+----- +-----   ++-----   +-------   +------   +---- +---------+------+\n"
                    */
                    printf(" |  %2u |$%02X.%d||$%02X.%d| $%02X.%d | $%02X.%d|$%03X|%9s|%6.2f|\n",
                           sectors,
                           data[i+1]>>1,                       (data[i+1]<<3)&8,            // selected GAP
                           (((signed char)data[i+2])>>1)&0xFF, (data[i+2]<<3)&8,            // GAP adjust
                           data[i+3]>>1,                       (data[i+3]<<3)&8,            // modulo complement
                           remainder>>1,                       (remainder<<3)&8,            // modulo
                           (trackTailGAP>>1) + 1,                                           // track tail GAP (with roundup)
                           vrfy, RPMval);
                }
                printf("\n  *) Note: The fractional parts of all the GAP based numbers shown here\n"
                         "           (sedecimal values) are given due to nybble based calculations.\n");
            }
            else
            {
Exemplo n.º 12
0
int ARCH_MAINDECL
main(int argc, char *argv[])
{
    int status = 0;
    char cmd[40];
    unsigned char job = 1, begintrack = 1, endtrack = 35, retries = 5;
    char c, *arg;
    char *adapter = NULL;
    int sector = 0, berror = 0;

    struct option longopts[] =
    {
        { "help"       , no_argument      , NULL, 'h' },
        { "version"    , no_argument      , NULL, 'V' },
        { "adapter"    , required_argument, NULL, '@' },
        { "job"        , no_argument      , NULL, 'j' },
        { "retries"    , required_argument, NULL, 'r' },
        { "extended"   , no_argument      , NULL, 'x' },
        { "retries"    , required_argument, NULL, 'r' },
        { "begin-track", required_argument, NULL, 'b' },
        { "end-track"  , required_argument, NULL, 'e' },
        { "sector"     , required_argument, NULL, 'c' },
/*
        { "quiet"      , no_argument      , NULL, 'q' },
        { "verbose"    , no_argument      , NULL, 'v' },
        { "no-progress", no_argument      , NULL, 'n' },
*/
        { NULL         , 0                , NULL, 0   }
    };

    // const char shortopts[] ="hVj:sr:xb:e:c:qvn";
    const char shortopts[] ="hVj:sxr:b:e:c:@:";


    while((c=(unsigned char)getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
    {
        switch(c)
        {
            case 'h': help();
                      return 0;
            case 'V': printf("cbmrpm41 Version %s\n", OPENCBM_VERSION ", built on " __DATE__ " at " __TIME__ "\n");
                      return 0;
            case 'j': job = arch_atoc(optarg);
                      break;
            case 's': status = 1;
                      break;
            case 'x': begintrack = 1;
                      endtrack = 40;
                      break;

            case 'r': retries = arch_atoc(optarg);
                      if(retries<1)       retries =  1;
                      else if(retries>63) retries = 63;
                      break;
            case 'b': begintrack = arch_atoc(optarg);
                      break;
            case 'e': endtrack = arch_atoc(optarg);
                      break;
            case 'c': sector = atoi(optarg);
                      break;
            case '@': if (adapter == NULL)
                          adapter = cbmlibmisc_strdup(optarg);
                      else
                      {
                          fprintf(stderr, "--adapter/-@ given more than once.");
                          help();
                          return 0;
                      }
                      break;
            default : hint(argv[0]);
                      return 1;
        }
    }

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

    arg = argv[optind++];
    drive = arch_atoc(arg);
    if(drive < 8 || drive > 11)
    {
        fprintf(stderr, "Invalid drive number (%s)\n", arg);
        return 1;
    }
    if(begintrack < 1)
    {
        fprintf(stderr, "Beginning track is less than 1, it should be 1 or greater.\n");
        return 1;
    }
    if(endtrack > 42)
    {
        fprintf(stderr, "Ending track is greater than 42, it should be 42 or less.\n");
        return 1;
    }
    if(begintrack > endtrack)
    {
        fprintf(stderr, "Beginning track is greater than ending track, it should be less or equal.");
        return 1;
    }
    if(sector < 0)
    {
        fprintf(stderr, "Sector numbers less than zero are not allowed.");
        return 1;
    }


    SETSTATEDEBUG((void)0);
    printf("Please remove any diskettes used with production data on it. Insert a freshly\n"
           "formatted disk into drive %d; you can format a disk with e.g. the command:\n\n"
           "        cbmforng -o -v %d freshdisk,fd\n\n"
           "If you desperately need to examine a production disk or even an original\n"
           "diskette, then please protect the disk with a write protect adhesive label.\n\n"
           "Press <Enter>, when ready or press <CTRL>-C to abort.\r", drive, drive);
    getchar();

    if(cbm_driver_open_ex(&fd, adapter) == 0) do
    {
        arch_set_ctrlbreak_handler(handle_CTRL_C);

        SETSTATEDEBUG((void)0);
        if( cbm_upload(fd, drive, sizeof(cbmDev_StartAddress), cbmrpm41, sizeof(cbmrpm41))
            != sizeof(cbmrpm41)) break;

        // location of the new U vector user commands table
        sprintf(cmd, "%c%c", UcmdTblAddr & 0xFF, UcmdTblAddr >> 8);
        // install the new U vector table
        SETSTATEDEBUG((void)0);
        if( cbm_upload(fd, drive, sizeof(cbmDev_UxCMDtVector), cmd, 2)
            != 2) break;

        // execute Ux command behind the symbolic name Init23_BitTimersStd
        SETSTATEDEBUG((void)0);
        if( cbm_sendUxCommand(fd, drive, Init23_BitTimersStd)
            != 0) break;

        // read disk ID and initialise other parameters
        // from the currently inserted disk into the
        // drive's RAM locations
        SETSTATEDEBUG((void)0);
        if( cbm_exec_command(fd, drive, "I0", 2)
            != 0) break;

        SETSTATEDEBUG((void)0);
        berror = cbm_device_status(fd, drive, cmd, sizeof(cmd));
        if(berror && status)
        {
            printf("%s\n", cmd);
        }

        switch(job)
        {
        case 4:
            if( do_RPMadjustment (begintrack, endtrack, sector, retries)
                != 0 ) continue;    // jump to begin of do{}while(0);
            break;
        case 3:
            if( do_RPMregression (begintrack, endtrack, sector, retries)
                != 0 ) continue;    // jump to begin of do{}while(0);
            break;
        case 2:
            if( do_SKEWmeasurment(begintrack, endtrack, sector, retries)
                != 0 ) continue;    // jump to begin of do{}while(0);
            break;
        default:
            if( do_RPMmeasurment (begintrack, endtrack, sector, retries)
                != 0 ) continue;    // jump to begin of do{}while(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
    {