Пример #1
0
/*
    FIXME: partition support
*/
int vdrive_bam_alloc_first_free_sector(vdrive_t *vdrive,
                                       unsigned int *track,
                                       unsigned int *sector)
{
    unsigned int s, d, max_tracks;
    int t;

    max_tracks = vdrive_calculate_disk_half(vdrive);

    for (d = 0; d <= max_tracks; d++) {
        int max_sector;
        t = vdrive->Bam_Track - d;
#ifdef DEBUG_DRIVE
        log_error(LOG_ERR, "Allocate first free sector on track %d.", t);
#endif
        if (d && t >= 1) {
            max_sector = vdrive_get_max_sectors(vdrive, t);
            for (s = 0; s < (unsigned int)max_sector; s++) {
                if (vdrive_bam_allocate_sector(vdrive, t, s)) {
                    *track = t;
                    *sector = s;
#ifdef DEBUG_DRIVE
                    log_error(LOG_ERR,
                              "Allocate first free sector: %d,%d.", t, s);
#endif
                    return 0;
                }
            }
        }
        t = vdrive->Bam_Track + d;
#ifdef DEBUG_DRIVE
        log_error(LOG_ERR, "Allocate first free sector on track %d.", t);
#endif
        if (t <= (int)(vdrive->num_tracks)) {
            max_sector = vdrive_get_max_sectors(vdrive, t);
            if (d) {
                s = 0;
            } else if (vdrive->image_format == VDRIVE_IMAGE_FORMAT_4000) {
                s = 64; /* after root directory */
            } else {
                s = max_sector; /* skip bam track */
            }
            for (; s < (unsigned int)max_sector; s++) {
                if (vdrive_bam_allocate_sector(vdrive, t, s)) {
                    *track = t;
                    *sector = s;
#ifdef DEBUG_DRIVE
                    log_error(LOG_ERR,
                              "Allocate first free sector: %d,%d.", t, s);
#endif
                    return 0;
                }
            }
        }
    }
    return -1;
}
Пример #2
0
static int vdrive_bam_alloc_up(vdrive_t *vdrive,
                               unsigned int *track, unsigned int *sector)
{
    unsigned int max_sector, t, s;

    for (t = *track; t <= vdrive->num_tracks; t++) {
        max_sector = vdrive_get_max_sectors(vdrive, t);
        for (s = 0; s < max_sector; s++) {
            if (vdrive_bam_allocate_sector(vdrive, t, s)) {
                *track = t;
                *sector = s;
                return 0;
            }
        }
    }
    return -1;
}
Пример #3
0
BYTE *vdrive_dir_find_next_slot(vdrive_dir_context_t *dir)
{
    static BYTE return_slot[32];
    vdrive_t *vdrive = dir->vdrive;

#ifdef DEBUG_DRIVE
    log_debug("DIR: vdrive_dir_find_next_slot start (t:%d/s:%d) #%d", dir->track, dir->sector, dir->slot);
#endif
    /*
     * Loop all directory blocks starting from track 18, sector 1 (1541).
     */

    do {
        /*
         * Load next(first) directory block ?
         */

        dir->slot++;

        if (dir->slot >= 8) {
            int status;

            /* end of current directory? */
            if (dir->buffer[0] == 0) {
                break;
            }

            dir->slot = 0;
            dir->track = (unsigned int)dir->buffer[0];
            dir->sector = (unsigned int)dir->buffer[1];

            status = vdrive_read_sector(vdrive, dir->buffer, dir->track, dir->sector);
            if (status != 0) {
                return NULL; /* error */
            }
        }
        if (vdrive_dir_name_match(&dir->buffer[dir->slot * 32],
                                  dir->find_nslot, dir->find_length,
                                  dir->find_type)) {
            memcpy(return_slot, &dir->buffer[dir->slot * 32], 32);
            return return_slot;
        }
    } while (1);

#ifdef DEBUG_DRIVE
    log_debug("DIR: vdrive_dir_find_next_slot (t:%d/s:%d) #%d", dir->track, dir->sector, dir->slot);
#endif

    /*
     * If length < 0, create new directory-entry if possible
     */
    if (dir->find_length < 0) {
        int i, sector;
        BYTE *dirbuf;

        sector = dir->sector + vdrive_dir_get_interleave(vdrive->image_format);

        for (i = 0; i < vdrive_get_max_sectors(vdrive, dir->track); i++) {
            dirbuf = find_next_directory_sector(dir, dir->track, sector);
            if (dirbuf != NULL) {
                return dirbuf;
            }

            sector++;
            if (sector >= vdrive_get_max_sectors(vdrive, dir->track)) {
                sector = 0;
            }
        }
    }
    return NULL;
}
Пример #4
0
/*
    FIXME: partition support
*/
int vdrive_bam_alloc_next_free_sector(vdrive_t *vdrive,
                                      unsigned int *track,
                                      unsigned int *sector)
{
    unsigned int max_sector, i, t, s;

    if (*track == vdrive->Bam_Track) {
        if (vdrive->image_format != VDRIVE_IMAGE_FORMAT_4000 || *sector < 64) {
            return -1;
        }
    }

    /* Calculate the next sector for the current interleave */
    s = *sector + vdrive_bam_get_interleave(vdrive->image_format);
    t = *track;
    max_sector = vdrive_get_max_sectors(vdrive, t);
    if (s >= max_sector) {
        s -= max_sector;
        if (s != 0) {
            s--;
        }
    }
    /* Look for a sector on the same track */
    for (i = 0; i < max_sector; i++) {
        if (vdrive->image_format == VDRIVE_IMAGE_FORMAT_4000 && *track == vdrive->Bam_Track && s < 64) {
            s = 64;
        }
        if (vdrive_bam_allocate_sector(vdrive, t, s)) {
            *track = t;
            *sector = s;
            return 0;
        }
        s++;
        if (s >= max_sector) {
            s = 0;
        }
    }
    if (vdrive->image_format == VDRIVE_IMAGE_FORMAT_4000 && *track == vdrive->Bam_Track) {
        (*track)++;
    }

    /* Look for a sector on a close track */
    *sector = 0;
    if (*track < vdrive->Dir_Track) {
        if (vdrive_bam_alloc_down(vdrive, track, sector) == 0) {
            return 0;
        }
        *track = vdrive->Dir_Track - 1;
        if (vdrive_bam_alloc_down(vdrive, track, sector) == 0) {
            return 0;
        }
        *track = vdrive->Dir_Track + 1;
        if (vdrive_bam_alloc_up(vdrive, track, sector) == 0) {
            return 0;
        }
    } else {
        if (vdrive_bam_alloc_up(vdrive, track, sector) == 0) {
            return 0;
        }
        *track = vdrive->Dir_Track + 1;
        if (vdrive_bam_alloc_up(vdrive, track, sector) == 0) {
            return 0;
        }
        *track = vdrive->Dir_Track - 1;
        if (vdrive_bam_alloc_down(vdrive, track, sector) == 0) {
            return 0;
        }
    }
    return -1;
}
Пример #5
0
/*
    FIXME: partition support
 */
int vdrive_command_validate(vdrive_t *vdrive)
{
    unsigned int t, s;
    int status, max_sector;
    BYTE *b, oldbam[BAM_MAXSIZE];

    status = vdrive_command_initialize(vdrive);

    if (status != CBMDOS_IPE_OK)
        return status;
    if (vdrive->image->read_only || VDRIVE_IMAGE_FORMAT_4000_TEST)
        return CBMDOS_IPE_WRITE_PROTECT_ON;

    memcpy(oldbam, vdrive->bam, vdrive->bam_size);

    vdrive_bam_clear_all(vdrive->image_format, vdrive->bam);

    for (t = 1; t <= vdrive->num_tracks; t++) {
        max_sector = vdrive_get_max_sectors(vdrive, t);
        for (s = 0; s < (unsigned int)max_sector; s++) {
            vdrive_bam_free_sector(vdrive->image_format, vdrive->bam, t, s);
        }
    }

    /* First, map out the header (BAM) and the directory, themselves. */
    status = vdrive_bam_allocate_chain(vdrive, vdrive->Bam_Track,
                                       vdrive->Bam_Sector);

    if (status != CBMDOS_IPE_OK) {
        memcpy(vdrive->bam, oldbam, vdrive->bam_size);
        return status;
    }

    switch (vdrive->image_format) {
    case VDRIVE_IMAGE_FORMAT_1571:
        /* Map the opposite side of the directory cylinder. */
        max_sector = vdrive_get_max_sectors(vdrive, 53);
        for (s = 0; s < (unsigned int)max_sector; s++) {
            vdrive_bam_allocate_sector(vdrive->image_format, vdrive->bam, 53, s);
        }
        break;
    case VDRIVE_IMAGE_FORMAT_1581:
        /* Map the BAM sectors. */
        vdrive_bam_allocate_sector(vdrive->image_format, vdrive->bam,
                                   vdrive->Bam_Track, vdrive->Bam_Sector + 1);
        vdrive_bam_allocate_sector(vdrive->image_format, vdrive->bam,
                                   vdrive->Bam_Track, vdrive->Bam_Sector + 2);
        break;
    case VDRIVE_IMAGE_FORMAT_4000:
        /* Map the boot sector. */
        vdrive_bam_allocate_sector(vdrive->image_format, vdrive->bam, 1, 0);

        /* Map the BAM sectors. */
        for (s = 2; s < 34; s++)
            vdrive_bam_allocate_sector(vdrive->image_format, vdrive->bam, 1, s);
        break;
    }

    vdrive_dir_find_first_slot(vdrive, "*", 1, 0);

    while ((b = vdrive_dir_find_next_slot(vdrive))) {
        char *filetype = (char *)
        &vdrive->Dir_buffer[vdrive->SlotNumber * 32 + SLOT_TYPE_OFFSET];

        if (*filetype & CBMDOS_FT_CLOSED) {
            status = vdrive_bam_allocate_chain(vdrive, b[SLOT_FIRST_TRACK],
                                               b[SLOT_FIRST_SECTOR]);
            if (status != CBMDOS_IPE_OK) {
                memcpy(vdrive->bam, oldbam, vdrive->bam_size);
                return status;
            }
            /* The real drive always validates side sectors even if the file
               type is not REL.  */
            status = vdrive_bam_allocate_chain(vdrive, b[SLOT_SIDE_TRACK],
                                               b[SLOT_SIDE_SECTOR]);
            if (status != CBMDOS_IPE_OK) {
                memcpy(vdrive->bam, oldbam, vdrive->bam_size);
                return status;
            }
        } else {
            /* Delete an unclosed file. */
            *filetype = CBMDOS_FT_DEL;
            if (vdrive_write_sector(vdrive, vdrive->Dir_buffer,
                vdrive->Curr_track, vdrive->Curr_sector) < 0)
                return CBMDOS_IPE_WRITE_ERROR_VER;
        }
    }

    /* Write back BAM only if validate was successful.  */
    vdrive_bam_write_bam(vdrive);
    return status;
}
Пример #6
0
BYTE *vdrive_dir_find_next_slot(vdrive_t *vdrive)
{
    static BYTE return_slot[32];

#ifdef DEBUG_DRIVE
    log_debug("DIR: vdrive_dir_find_next_slot start (t:%d/s:%d) #%d", vdrive->Curr_track, vdrive->Curr_sector, vdrive->SlotNumber);
#endif
    /*
     * Loop all directory blocks starting from track 18, sector 1 (1541).
     */

    do {
        /*
         * Load next(first) directory block ?
         */

        vdrive->SlotNumber++;

        if (vdrive->SlotNumber >= 8) {
            int status;

            /* end of current directory? */
            if (vdrive->Dir_buffer[0] == 0) {
                break;
            }

            vdrive->SlotNumber = 0;
            vdrive->Curr_track  = (int)vdrive->Dir_buffer[0];
            vdrive->Curr_sector = (int)vdrive->Dir_buffer[1];

            status = disk_image_read_sector(vdrive->image, vdrive->Dir_buffer,
                                            vdrive->Curr_track,
                                            vdrive->Curr_sector);
            if (status != 0) {
                return NULL; /* error */
            }
        }
        if (vdrive_dir_name_match(&vdrive->Dir_buffer[vdrive->SlotNumber * 32],
                                  vdrive->find_nslot, vdrive->find_length,
                                  vdrive->find_type)) {
            memcpy(return_slot, &vdrive->Dir_buffer[vdrive->SlotNumber * 32], 32);
            return return_slot;
        }
    } while (1);

#ifdef DEBUG_DRIVE
    log_debug("DIR: vdrive_dir_find_next_slot (t:%d/s:%d) #%d", vdrive->Curr_track, vdrive->Curr_sector, vdrive->SlotNumber);
#endif

    /*
     * If length < 0, create new directory-entry if possible
     */
    if (vdrive->find_length < 0) {
        int i, sector;
        BYTE *dirbuf;

        sector = vdrive->Curr_sector + vdrive_dir_get_interleave(vdrive->image_format);

        for (i = 0; i < vdrive_get_max_sectors(vdrive, vdrive->Curr_track); i++) {

            dirbuf = find_next_directory_sector(vdrive, vdrive->Curr_track, sector);
            if (dirbuf != NULL) {
                return dirbuf;
            }

            sector++;
            if (sector >= vdrive_get_max_sectors(vdrive, vdrive->Curr_track)) {
                sector = 0;
            }
        }
    }
    return NULL;
}