Пример #1
0
static int iec_close_sequential(vdrive_t *vdrive, unsigned int secondary)
{
    bufferinfo_t *p = &(vdrive->buffers[secondary]);
    unsigned int track = 0, sector = 0;

    if (p->readmode & (CBMDOS_FAM_WRITE | CBMDOS_FAM_APPEND)) {
        /*
         * Flush bytes and write slot to directory
         */

        if (vdrive->image->read_only || VDRIVE_IMAGE_FORMAT_4000_TEST) {
            vdrive_command_set_error(vdrive, CBMDOS_IPE_WRITE_PROTECT_ON, 0, 0);
            return SERIAL_ERROR;
        }

#ifdef DEBUG_DRIVE
        log_debug("DEBUG: flush.");
#endif
        /* Flush remained of file */
        iec_write_sequential(vdrive, p, p->bufptr);

        /* Set the file as closed */
        p->slot[SLOT_TYPE_OFFSET] |= 0x80; /* Closed */

        /* is this a save and replace? */
        if (p->needsupdate) {
            /* remember the original track and sector */
            track = p->slot[SLOT_FIRST_TRACK];
            sector = p->slot[SLOT_FIRST_SECTOR];
            /* move over the replacement track and sector */
            p->slot[SLOT_FIRST_TRACK] = p->slot[SLOT_REPLACE_TRACK];
            p->slot[SLOT_FIRST_SECTOR] = p->slot[SLOT_REPLACE_SECTOR];
            /* set replacement track and sector to 0 */
            p->slot[SLOT_REPLACE_TRACK] = 0;
            p->slot[SLOT_REPLACE_SECTOR] = 0;
        }

        /* Update the directory entry (block count, closed) */
        vdrive_iec_update_dirent(vdrive, secondary);

        /* if we have a track and sector saved */
        if (track) {
            /* remove the original file */
            vdrive_dir_free_chain(vdrive, track, sector);
        }

        /* Update BAM */
        vdrive_bam_write_bam(vdrive);

        /* Free up the slot */
        lib_free(p->slot);
    }
    /* Release buffers */
    vdrive_free_buffer(p);

    return SERIAL_OK;
}
Пример #2
0
static int vdrive_rel_grow(vdrive_t *vdrive, unsigned int secondary,
                           unsigned int records)
{
    bufferinfo_t *p = &(vdrive->buffers[secondary]);
    unsigned int track, sector;
    unsigned int i, j, k, l = 0;

    /* Add a sector to the rel file until we meet the required
        records. */
    while ( records >= p->record_max ) {
        l = vdrive_rel_add_sector(vdrive, secondary, &track, &sector);
        if (l) break;
    }

    /* Flush the side sectors, since they have changed */
    vdrive_rel_flush_sidesectors(vdrive, p);

    /* Update the BAM. */
    vdrive_bam_write_bam(vdrive);

    /* Update block count on file expansions. */

    /* Find the total blocks this REL file uses. */
    k = p->slot[SLOT_NR_BLOCKS] + (p->slot[SLOT_NR_BLOCKS + 1] << 8);

    /* determine the block count of the data */
    i = p->record_max * p->slot[SLOT_RECORD_LENGTH];
    j = i / 254;
    if (i % 254) j++;
    /* determine the block count of the side sectors */
    i = j / SIDE_INDEX_MAX;
    if (j % SIDE_INDEX_MAX) i++;
    /* Add another block for a super side sector */
    if (p->super_side_sector_track) i++;
    /* Sum them up */
    i = i + j;

    /* Compare with the current */
    if (i != k) {
        /* Convert to high/low */
        p->slot[SLOT_NR_BLOCKS] = i % 256;
        p->slot[SLOT_NR_BLOCKS + 1] = i / 256;
        /* Update the directory entry (block count) */
        vdrive_iec_update_dirent(vdrive, secondary);
    }

    return l;
}
Пример #3
0
void vdrive_dir_remove_slot(vdrive_t *vdrive, BYTE *slot)
{
    unsigned int tmp;
    int t, s;

    /* Find slot.  */
    for (tmp = 0; (tmp < 16) && slot[SLOT_NAME_OFFSET + tmp] != 0xa0; tmp++);

    vdrive_dir_find_first_slot(vdrive,
                               (char *)&slot[SLOT_NAME_OFFSET], tmp,
                               slot[SLOT_TYPE_OFFSET] & 0x07);

    /* If slot found, remove.  */
    if (vdrive_dir_find_next_slot(vdrive)) {

        /* Free all sector this file is using.  */
        t = (int) vdrive->Dir_buffer[vdrive->SlotNumber * 32
            + SLOT_FIRST_TRACK];
        s = (int) vdrive->Dir_buffer[vdrive->SlotNumber * 32
            + SLOT_FIRST_SECTOR];

        vdrive_dir_free_chain(vdrive, t, s);

        /* Free side sectors.  */
        t = (int) vdrive->Dir_buffer[vdrive->SlotNumber * 32
            + SLOT_SIDE_TRACK];
        s = (int) vdrive->Dir_buffer[vdrive->SlotNumber * 32
            + SLOT_SIDE_SECTOR];

        vdrive_dir_free_chain(vdrive, t, s);

        /* Update bam */
        vdrive_bam_write_bam(vdrive);

        /* Update directory entry */
        vdrive->Dir_buffer[vdrive->SlotNumber * 32 + SLOT_TYPE_OFFSET] = 0;
        disk_image_write_sector(vdrive->image, vdrive->Dir_buffer,
                                vdrive->Curr_track, vdrive->Curr_sector);
    }
}
Пример #4
0
void vdrive_dir_remove_slot(vdrive_dir_context_t *dir)
{
    int t, s;
    vdrive_t *vdrive = dir->vdrive;

    /* Free all sector this file is using.  */
    t = (int) dir->buffer[dir->slot * 32 + SLOT_FIRST_TRACK];
    s = (int) dir->buffer[dir->slot * 32 + SLOT_FIRST_SECTOR];

    vdrive_dir_free_chain(vdrive, t, s);

    /* Free side sectors.  */
    t = (int) dir->buffer[dir->slot * 32 + SLOT_SIDE_TRACK];
    s = (int) dir->buffer[dir->slot * 32 + SLOT_SIDE_SECTOR];

    vdrive_dir_free_chain(vdrive, t, s);

    /* Update bam */
    vdrive_bam_write_bam(vdrive);

    /* Update directory entry */
    dir->buffer[dir->slot * 32 + SLOT_TYPE_OFFSET] = 0;
    vdrive_write_sector(vdrive, dir->buffer, dir->track, dir->sector);
}
Пример #5
0
/*
    FIXME: partition support
 */
int vdrive_command_format(vdrive_t *vdrive, const char *disk_name)
{
    BYTE tmp[256];
    int status;
    char *name, *comma;
    BYTE id[2];

    if (!disk_name)
        return CBMDOS_IPE_SYNTAX;

    if (vdrive->image->read_only || VDRIVE_IMAGE_FORMAT_4000_TEST)
        return CBMDOS_IPE_WRITE_PROTECT_ON;

    if (vdrive->image->device == DISK_IMAGE_DEVICE_FS) {
        if (disk_image_fsimage_fd_get(vdrive->image) == NULL)
            return CBMDOS_IPE_NOT_READY;
    }

    comma = strchr(disk_name, ',');
    if (comma != NULL) {
        if (comma != disk_name) {
            name = lib_malloc(comma - disk_name + 1);
            memcpy(name, disk_name, comma - disk_name);
            name[comma - disk_name] = '\0';
        } else {
            name = lib_stralloc(" ");
        }
        if (comma[1] != '\0') {
            id[0] = comma[1];
            if (comma[2] != '\0') {
                id[1] = comma[2];
            } else {
                id[1] = ' ';
            }
        } else {
            id[1] = id[0] = ' ';
        }
    } else {
        name = lib_stralloc(disk_name);
        id[1] = id[0] = ' ';
    }

    /* Make the first dir-entry.  */
    memset(tmp, 0, 256);
    tmp[1] = 255;

    if (vdrive_write_sector(vdrive, tmp, vdrive->Dir_Track,
        vdrive->Dir_Sector) < 0) {
        lib_free(name);
        return CBMDOS_IPE_WRITE_ERROR_VER;
    }
    vdrive_bam_create_empty_bam(vdrive, name, id);
    vdrive_bam_write_bam(vdrive);

    /* Validate is called to clear the BAM.  */
    status = vdrive_command_validate(vdrive);

    lib_free(name);

    return status;
}
Пример #6
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;
}