コード例 #1
0
int vdrive_bam_allocate_chain(vdrive_t *vdrive, unsigned int t, unsigned int s)
{
    BYTE tmp[256];
    int rc;

    while (t) {
        /* Check for illegal track or sector.  */
        if (disk_image_check_sector(vdrive->image, t, s) < 0) {
            vdrive_command_set_error(vdrive, CBMDOS_IPE_ILLEGAL_TRACK_OR_SECTOR,
                                     s, t);
            return CBMDOS_IPE_ILLEGAL_TRACK_OR_SECTOR;
        }
        if (!vdrive_bam_allocate_sector(vdrive, t, s)) {
            /* The real drive does not seem to catch this error.  */
            vdrive_command_set_error(vdrive, CBMDOS_IPE_NO_BLOCK, s, t);
            return CBMDOS_IPE_NO_BLOCK;
        }
        rc = vdrive_read_sector(vdrive, tmp, t, s);
        if (rc > 0) {
            return rc;
        }
        if (rc < 0) {
            return CBMDOS_IPE_NOT_READY;
        }

        t = (int)tmp[0];
        s = (int)tmp[1];
    }
    return CBMDOS_IPE_OK;
}
コード例 #2
0
/*
   read first dir buffer into Dir_buffer
*/
void vdrive_dir_find_first_slot(vdrive_t *vdrive, const char *name,
                                int length, unsigned int type,
                                vdrive_dir_context_t *dir)
{
    if (length > 0) {
        BYTE *nslot;

        nslot = cbmdos_dir_slot_create(name, length);
        memcpy(dir->find_nslot, nslot, CBMDOS_SLOT_NAME_LENGTH);
        lib_free(nslot);
    }

    dir->vdrive = vdrive;
    dir->find_length = length;
    dir->find_type = type;

    dir->track = vdrive->Header_Track;
    dir->sector = vdrive->Header_Sector;
    dir->slot = 7;

    vdrive_read_sector(vdrive, dir->buffer, dir->track, dir->sector);

    dir->buffer[0] = vdrive->Dir_Track;
    dir->buffer[1] = vdrive->Dir_Sector;

#ifdef DEBUG_DRIVE
    log_debug("DIR: vdrive_dir_find_first_slot (curr t:%d/s:%d dir t:%d/s:%d)",
              dir->track, dir->sector, vdrive->Dir_Track, vdrive->Dir_Sector);
#endif
}
コード例 #3
0
ファイル: vdrive-command.c プロジェクト: bobsummerwill/VICE
/*
    CMD style subdir support (using DIR filetype)
*/
static int vdrive_command_chdir(vdrive_t *vdrive, BYTE *name, int length)
{
    int status, rc;
    BYTE *slot, buffer[256];
    cbmdos_cmd_parse_t cmd_parse;

    cmd_parse.cmd = name;
    cmd_parse.cmdlength = length;
    cmd_parse.readmode = 0;

    rc = cbmdos_command_parse(&cmd_parse);

    if (rc != SERIAL_OK) {
        status = CBMDOS_IPE_NO_NAME;
    } else {
/*#ifdef DEBUG_DRIVE*/
        log_debug("chdir name='%s', len=%d (%d), type= %d.",
                  cmd_parse.parsecmd, cmd_parse.parselength,
                  length, cmd_parse.filetype);
/*#endif*/

        vdrive_dir_find_first_slot(vdrive, cmd_parse.parsecmd,
                                   cmd_parse.parselength, CBMDOS_FT_DIR);

        slot = vdrive_dir_find_next_slot(vdrive);

        if (slot) {
            slot = &vdrive->Dir_buffer[vdrive->SlotNumber * 32];
            rc = vdrive_read_sector(vdrive, buffer,
                                        slot[SLOT_FIRST_TRACK],
                                        slot[SLOT_FIRST_SECTOR]);
            if (rc > 0) {
                return rc;
            }
            if (rc < 0) {
                return CBMDOS_IPE_NOT_READY;
            }

            vdrive->Header_Track = slot[SLOT_FIRST_TRACK];
            vdrive->Header_Sector = slot[SLOT_FIRST_SECTOR];
            vdrive->Dir_Track = buffer[0];
            vdrive->Dir_Sector = buffer[1];
            status = CBMDOS_IPE_OK;
        } else {
            status = CBMDOS_IPE_PATH_NOT_FOUND;
        }

        vdrive_command_set_error(vdrive, status, 0, 0);
    }

    lib_free(cmd_parse.parsecmd);

    return status;
}
コード例 #4
0
static int iec_read_sequential(vdrive_t *vdrive, BYTE *data,
                               unsigned int secondary)
{
    bufferinfo_t *p = &(vdrive->buffers[secondary]);
    int status;
    unsigned int track, sector;

    if (p->readmode != CBMDOS_FAM_READ) {
        *data = 0xc7;
        return SERIAL_ERROR;
    }

    *data = p->buffer[p->bufptr];
    if (p->length != 0) {
        if (p->bufptr == p->length) {
            p->bufptr = 0xff;
        }
    }
    p->bufptr = (p->bufptr + 1) & 0xff;
    if (p->bufptr) {
        return SERIAL_OK;
    }
    if (p->length) {
        p->readmode = CBMDOS_FAM_EOF;
        return SERIAL_EOF;
    }

    switch (p->mode) {
        case BUFFER_SEQUENTIAL:

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

            status = vdrive_read_sector(vdrive, p->buffer, track, sector);
            p->length = p->buffer[0] ? 0 : p->buffer[1];
            vdrive_set_last_read(track, sector, p->buffer);

            if (status == 0) {
                p->bufptr = 2;
            } else {
                p->readmode = CBMDOS_FAM_EOF;
            }
            break;
        case BUFFER_DIRECTORY_READ:
            p->length = vdrive_dir_next_directory(vdrive, p);
            p->bufptr = 0;
            break;
    }
    return SERIAL_OK;
}
コード例 #5
0
int vdrive_iec_update_dirent(vdrive_t *vdrive, unsigned int channel)
{
    bufferinfo_t *p = &(vdrive->buffers[channel]);

    /* Read in the track/sector where the directory entry lies. */
    vdrive_read_sector(vdrive, p->dir.buffer, p->dir.track, p->dir.sector);

    /* Copy over our new slot. */
    memcpy(&(p->dir.buffer[p->dir.slot * 32 + 2]), p->slot + 2, 30);

    /* Write it back. */
    vdrive_write_sector(vdrive, p->dir.buffer, p->dir.track, p->dir.sector);

    return 0;
}
コード例 #6
0
static int iec_open_read_sequential(vdrive_t *vdrive, unsigned int secondary, unsigned int track, unsigned int sector)
{
    int status;
    bufferinfo_t *p = &(vdrive->buffers[secondary]);

    vdrive_alloc_buffer(p, BUFFER_SEQUENTIAL);
    p->bufptr = 2;

    status = vdrive_read_sector(vdrive, p->buffer, track, sector);
    p->length = p->buffer[0] ? 0 : p->buffer[1];

    vdrive_set_last_read(track, sector, p->buffer);

    if (status != 0) {
        vdrive_iec_close(vdrive, secondary);
        return SERIAL_ERROR;
    }
    return SERIAL_OK;
}
コード例 #7
0
void vdrive_dir_free_chain(vdrive_t *vdrive, int t, int s)
{
    BYTE buf[256];

    while (t) {
        /* Check for illegal track or sector.  */
        if (disk_image_check_sector(vdrive->image, t, s) < 0) {
            break;
        }

        /* Check if this sector is really allocated.  */
        if (!vdrive_bam_free_sector(vdrive, t, s)) {
            break;
        }

        /* FIXME: This seems to be redundant.  AB19981124  */
        vdrive_bam_free_sector(vdrive, t, s);
        vdrive_read_sector(vdrive, buf, t, s);
        t = (int)buf[0];
        s = (int)buf[1];
    }
}
コード例 #8
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;
}
コード例 #9
0
static int iec_open_write(vdrive_t *vdrive, unsigned int secondary,
                          cbmdos_cmd_parse_t *cmd_parse, const BYTE *name)
{
    bufferinfo_t *p = &(vdrive->buffers[secondary]);
    unsigned int track, sector;
    BYTE *slot = p->slot, *e;

    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;
    }

    /* set flag for overwrite mode */
    p->needsupdate = 0;

    if (slot) {
        /* file exists */
        if (*name == '@') {
            /* replace mode: we don't want the dirent updated at all until
                close */
            /* allocate buffers */
            vdrive_alloc_buffer(p, BUFFER_SEQUENTIAL);
            p->bufptr = 2;

            /* Create our own slot, since the one passed is static */
            p->slot = lib_calloc(1, 32);

            /* Copy the static on to the new one. */
            memcpy(p->slot, slot, 32);
            slot = p->slot;

            /* set flag for replace mode */
            p->needsupdate = 1;

            /* find a new track and sector when writing */
            p->track = p->sector = 0;
        } else {
            if (p->readmode == CBMDOS_FAM_APPEND) {
                /* append mode */
                /* allocate buffers */
                vdrive_alloc_buffer(p, BUFFER_SEQUENTIAL);

                /* Create our own slot, since the one passed is static */
                p->slot = lib_calloc(1, 32);

                /* Copy the static on to the new one. */
                memcpy(p->slot, slot, 32);
                slot = p->slot;

                /* set file unclosed */
                p->slot[SLOT_TYPE_OFFSET] &= 0x7f;

                /* get the starting track and sector */
                p->track = track = slot[SLOT_FIRST_TRACK];
                p->sector = sector = slot[SLOT_FIRST_SECTOR];

                /* update block count as we find the end of the file */
                /* the real drives actually don't do this, so each time you
                    append to a file, the block count increases by 1.  I think it
                    is safer to correct the block count. */
                slot[SLOT_NR_BLOCKS] = 255;
                slot[SLOT_NR_BLOCKS + 1] = 255;

                /* scan to the end of the file */
                while (track) {
                    p->track = track;
                    p->sector = sector;
                    if (vdrive_read_sector(vdrive, p->buffer, p->track, p->sector)) {
                        /* couldn't read sector, report error and leave */
                        vdrive_free_buffer(p);
                        vdrive_command_set_error(vdrive, CBMDOS_IPE_ILLEGAL_TRACK_OR_SECTOR, p->track, p->sector);
                        return SERIAL_ERROR;
                    }
                    /* setup next link */
                    track = p->buffer[0];
                    sector = p->buffer[1];

                    /* Increment block count. */
                    if (!(++slot[SLOT_NR_BLOCKS])) {
                        ++slot[SLOT_NR_BLOCKS + 1];
                    }
                }
                /* compensate if the dir link is 0 (rare possibility) */
                if (!p->track) {
                    /* Our loop didn't even execute once, set the block
                       size to 0 */
                    slot[SLOT_NR_BLOCKS] = 0;
                    slot[SLOT_NR_BLOCKS + 1] = 0;
                    /* set buffer pointer to 2 */
                    sector = 1;
                }
                /* set the buffer pointer */
                p->bufptr = sector + 1;
            } else {
                /* can't overwrite an existing file */
                vdrive_iec_close(vdrive, secondary);
                vdrive_command_set_error(vdrive, CBMDOS_IPE_FILE_EXISTS, 0, 0);
                return SERIAL_ERROR;
            }
        }
    } else {
        /* new file... */
        /* create a slot based on the opening name */
        vdrive_dir_create_slot(p, cmd_parse->parsecmd, cmd_parse->parselength,
                               cmd_parse->filetype);

        /* Write the directory entry to disk as an UNCLOSED file. */

        vdrive_dir_find_first_slot(vdrive, NULL, -1, 0, &p->dir);
        e = vdrive_dir_find_next_slot(&p->dir);

        /* If there is not space for the slot, disk is full */
        if (!e) {
            vdrive_free_buffer(p);
            vdrive_command_set_error(vdrive, CBMDOS_IPE_DISK_FULL, 0, 0);
            return SERIAL_ERROR;
        }

        /* find a new track and sector when writing */
        p->track = p->sector = 0;
    }

    if (!p->needsupdate) {
        /* copy the slot information into the sector. */
        memcpy(&p->dir.buffer[p->dir.slot * 32 + 2],
               p->slot + 2, 30);

        /* Write the sector. */
        vdrive_write_sector(vdrive, p->dir.buffer, p->dir.track, p->dir.sector);
    }

    return SERIAL_OK;
}
コード例 #10
0
ファイル: mon_drive.c プロジェクト: aerdnar/emu-ex-plus-alpha
void mon_drive_block_cmd(int op, int track, int sector, MON_ADDR addr)
{
    vdrive_t *vdrive;

    mon_evaluate_default_addr(&addr);

    vdrive = file_system_get_vdrive(8);

    if (!vdrive || vdrive->image == NULL) {
        mon_out("No disk attached\n");
        return;
    }

    if (!op) {
        BYTE readdata[256];
        int i, j, dst;
        MEMSPACE dest_mem;

        /* We ignore disk error codes here.  */
        if (vdrive_read_sector(vdrive, readdata, track, sector)
            < 0) {
            mon_out("Error reading track %d sector %d\n", track, sector);
            return;
        }

        if (mon_is_valid_addr(addr)) {
            dst = addr_location(addr);
            dest_mem = addr_memspace(addr);

            for (i = 0; i < 256; i++) {
                mon_set_mem_val(dest_mem, ADDR_LIMIT(dst + i), readdata[i]);
            }

            mon_out("Read track %d sector %d into address $%04x\n", track, sector, dst);
        } else {
            for (i = 0; i < 16; i++) {
                mon_out(">%04x", i * 16);
                for (j = 0; j < 16; j++) {
                    if ((j & 3) == 0) {
                        mon_out(" ");
                    }
                    mon_out(" %02x", readdata[i * 16 + j]);
                }
                mon_out("\n");
            }
        }
    } else {
        BYTE writedata[256];
        int i, src;
        MEMSPACE src_mem;

        src = addr_location(addr);
        src_mem = addr_memspace(addr);

        for (i = 0; i < 256; i++) {
            writedata[i] = mon_get_mem_val(src_mem, ADDR_LIMIT(src + i));
        }

        if (vdrive_write_sector(vdrive, writedata, track, sector)) {
            mon_out("Error writing track %d sector %d\n", track, sector);
            return;
        }

        mon_out("Write data from address $%04x to track %d sector %d\n",
                src, track, sector);
    }
}
コード例 #11
0
image_contents_t *diskcontents_block_read(vdrive_t *vdrive)
{
    image_contents_t *contents;
    BYTE buffer[256];
    int retval;
    image_contents_file_list_t *lp;

    machine_drive_flush();

    if (vdrive == NULL)
        return NULL;

    retval = vdrive_bam_read_bam(vdrive);

    if (retval < 0) {
        vdrive_internal_close_disk_image(vdrive);
        return NULL;
    }

    contents = image_contents_new();

    memcpy(contents->name, vdrive->bam + vdrive->bam_name,
           IMAGE_CONTENTS_NAME_LEN);
    contents->name[IMAGE_CONTENTS_NAME_LEN] = 0;

    memcpy(contents->id, vdrive->bam + vdrive->bam_id, IMAGE_CONTENTS_ID_LEN);
    contents->id[IMAGE_CONTENTS_ID_LEN] = 0;

    contents->blocks_free = (int)vdrive_bam_free_block_count(vdrive);

    vdrive->Curr_track = vdrive->Dir_Track;
    vdrive->Curr_sector = vdrive->Dir_Sector;

    lp = NULL;
    contents->file_list = NULL;

    circular_check_init();

    while (1) {
        BYTE *p;
        int j;

        retval = vdrive_read_sector(vdrive, buffer,
                                        vdrive->Curr_track,
                                        vdrive->Curr_sector);

        if (retval != 0
            || circular_check(vdrive->Curr_track, vdrive->Curr_sector)) {
            /*image_contents_destroy(contents);*/
            vdrive_internal_close_disk_image(vdrive);
            circular_check_free();
            return contents/*NULL*/;
        }

        for (p = buffer, j = 0; j < 8; j++, p += 32)
            if (p[SLOT_TYPE_OFFSET] != 0) {
                image_contents_file_list_t *new_list;
                int i;

                new_list = lib_malloc(sizeof(image_contents_file_list_t));
                new_list->size = ((int)p[SLOT_NR_BLOCKS]
                                  + ((int)p[SLOT_NR_BLOCKS + 1] << 8));

                for (i = 0; i < IMAGE_CONTENTS_FILE_NAME_LEN; i++)
                        new_list->name[i] = p[SLOT_NAME_OFFSET + i];

                new_list->name[IMAGE_CONTENTS_FILE_NAME_LEN] = 0;

                new_list->name[i] = 0;

                sprintf((char *)new_list->type, "%c%s%c",
                        (p[SLOT_TYPE_OFFSET] & CBMDOS_FT_CLOSED ? ' ' : '*'),
                        cbmdos_filetype_get(p[SLOT_TYPE_OFFSET] & 0x07),
                        (p[SLOT_TYPE_OFFSET] & CBMDOS_FT_LOCKED ? '<' : ' '));

                new_list->next = NULL;

                if (lp == NULL) {
                    new_list->prev = NULL;
                    contents->file_list = new_list;
                    lp = contents->file_list;
                } else {
                    new_list->prev = lp;
                    lp->next = new_list;
                    lp = new_list;
                }
            }

        if (buffer[0] == 0)
            break;

        vdrive->Curr_track = (int)buffer[0];
        vdrive->Curr_sector = (int)buffer[1];
    }

    vdrive_internal_close_disk_image(vdrive);
    circular_check_free();
    return contents;
}
コード例 #12
0
/* probably we should make a list with BAM blocks for each drive type... (AF)*/
int vdrive_bam_read_bam(vdrive_t *vdrive)
{
    int err = -1, i;

    switch (vdrive->image_format) {
        case VDRIVE_IMAGE_FORMAT_2040:
        case VDRIVE_IMAGE_FORMAT_1541:
            err = vdrive_read_sector(vdrive, vdrive->bam, BAM_TRACK_1541, BAM_SECTOR_1541);
            break;
        case VDRIVE_IMAGE_FORMAT_1571:
            err = vdrive_read_sector(vdrive, vdrive->bam, BAM_TRACK_1571, BAM_SECTOR_1571);
            if (err != 0) {
                break;
            }
            err = vdrive_read_sector(vdrive, vdrive->bam + 256, BAM_TRACK_1571 + 35, BAM_SECTOR_1571);
            break;
        case VDRIVE_IMAGE_FORMAT_1581:
            err = vdrive_read_sector(vdrive, vdrive->bam, BAM_TRACK_1581, BAM_SECTOR_1581);
            if (err != 0) {
                break;
            }
            err = vdrive_read_sector(vdrive, vdrive->bam + 256, BAM_TRACK_1581, BAM_SECTOR_1581 + 1);
            if (err != 0) {
                break;
            }
            err = vdrive_read_sector(vdrive, vdrive->bam + 512, BAM_TRACK_1581, BAM_SECTOR_1581 + 2);
            break;
        case VDRIVE_IMAGE_FORMAT_8050:
        case VDRIVE_IMAGE_FORMAT_8250:
            err = vdrive_read_sector(vdrive, vdrive->bam, BAM_TRACK_8050, BAM_SECTOR_8050);
            if (err != 0) {
                break;
            }
            err = vdrive_read_sector(vdrive, vdrive->bam + 256, BAM_TRACK_8050 - 1, BAM_SECTOR_8050);
            if (err != 0) {
                break;
            }
            err = vdrive_read_sector(vdrive, vdrive->bam + 512, BAM_TRACK_8050 - 1, BAM_SECTOR_8050 + 3);
            if (err != 0) {
                break;
            }

            if (vdrive->image_format == VDRIVE_IMAGE_FORMAT_8050) {
                break;
            }

            err = vdrive_read_sector(vdrive, vdrive->bam + 768, BAM_TRACK_8050 - 1, BAM_SECTOR_8050 + 6);
            if (err != 0) {
                break;
            }
            err = vdrive_read_sector(vdrive, vdrive->bam + 1024, BAM_TRACK_8050 - 1, BAM_SECTOR_8050 + 9);
            break;
        case VDRIVE_IMAGE_FORMAT_4000:
            for (i = 0; i < 33; i++) {
                err = vdrive_read_sector(vdrive, vdrive->bam + i * 256, BAM_TRACK_4000, BAM_SECTOR_4000 + i);
                if (err != 0) {
                    break;
                }
            }
            break;
        default:
            log_error(LOG_ERR, "Unknown disk type %i.  Cannot read BAM.", vdrive->image_format);
    }

    if (err < 0) {
        return CBMDOS_IPE_NOT_READY;
    }

    return err;
}
コード例 #13
0
ファイル: vdrive-command.c プロジェクト: bobsummerwill/VICE
/*
    CBM style sub partition support (using CBM filetype)

    on 1581 dos command "/dirname" enters a partition, "i" will go back to root

    FIXME: this works only for .d81
*/
static int vdrive_command_chpart(vdrive_t *vdrive, BYTE *name, int length)
{
    int status, rc;
    int ts,ss,te,len;
    BYTE *slot, buffer[256];
    cbmdos_cmd_parse_t cmd_parse;

    cmd_parse.cmd = name;
    cmd_parse.cmdlength = length;
    cmd_parse.readmode = 0;

    rc = cbmdos_command_parse(&cmd_parse);

    if (rc != SERIAL_OK) {
        status = CBMDOS_IPE_NO_NAME;
    } else {
/*#ifdef DEBUG_DRIVE*/
        log_debug("chpart name='%s', len=%d (%d), type= %d.",
                  cmd_parse.parsecmd, cmd_parse.parselength,
                  length, cmd_parse.filetype);
/*#endif*/

        vdrive_dir_find_first_slot(vdrive, cmd_parse.parsecmd,
                                   cmd_parse.parselength, CBMDOS_FT_CBM);

        slot = vdrive_dir_find_next_slot(vdrive);

        status = CBMDOS_IPE_BAD_PARTN; /* FIXME: is this correct ? */
        if (slot) {
            slot = &vdrive->Dir_buffer[vdrive->SlotNumber * 32];
            /*
            In order to use a partition as a sub-directory, it  must  adhere  to  
            the following four rules:

            1. It must start on sector 0
            2. It's size must be in multiples of 40 sectors (which means the 
               last sector is 39)
            3. It must be a minimum of 120 sectors long (3 tracks)
            4. It must not start on or cross  track 40
            */
            ts = slot[SLOT_FIRST_TRACK];
            ss = slot[SLOT_FIRST_SECTOR];
            len = slot[SLOT_NR_BLOCKS] + (slot[SLOT_NR_BLOCKS + 1] * 256);

            if ((ss == 0) && ((len % 40) == 0) && (len >= 120) && (ts != 40)) {
                te = ts + (len / 40);
                if (((ts < 40) && (te >= 40)) || (te >= (int)vdrive->num_tracks)) {
                    return CBMDOS_IPE_BAD_PARTN; /* FIXME: is this correct ? */
                }

                /* read the first BAM sector to get the DIR start 
                   The BAM track for the sub-directory exists on  the  first  
                   track  of  the partition, and has the same layout as the disk 
                   BAM on track 40.
                 */
                rc = vdrive_read_sector(vdrive, buffer, ts, 0);

                if (rc > 0) {
                    return rc;
                }
                if (rc < 0) {
                    return CBMDOS_IPE_NOT_READY;
                }

                /* more sanity checks */
                if ((buffer[0] < ts) || (buffer[1] > 39)) {
                    return CBMDOS_IPE_BAD_PARTN; /* FIXME: is this correct ? */
                }

/*#ifdef DEBUG_DRIVE*/
                log_debug("Partition Trk %d Sec %d - Trk %d len: %d", ts, ss, te, len);
/*#endif*/
                /* setup BAM location */
                vdrive->Header_Track = ts;
                vdrive->Header_Sector = 0;
                vdrive->Bam_Track = ts;
                vdrive->Bam_Sector = 0;
                /* set area for active partition */
                vdrive->Part_Start = ts;
                vdrive->Part_End = te;
                /* start of directory */
                vdrive->Dir_Track = buffer[0];
                vdrive->Dir_Sector = buffer[1];

                status = CBMDOS_IPE_OK;
            }
        }
    }

    vdrive_command_set_error(vdrive, status, 0, 0);
    lib_free(cmd_parse.parsecmd);

    return status;
}
コード例 #14
0
ファイル: vdrive-command.c プロジェクト: bobsummerwill/VICE
static int vdrive_command_block(vdrive_t *vdrive, unsigned char command,
                                char *buffer)
{
    int channel = 0, drive = 0, track = 0, sector = 0, position = 0;
    int l, rc;

#ifdef DEBUG_DRIVE
    log_debug("vdrive_command_block command:%c.", command);
#endif

    switch (command) {
      /* 1581 has u-R (shifted) and u-W (shifted) for block read/write
         without track/sector checking. */
      /* Use this for U1,UA and U2,UB also */
      case 0xd2:
      case 0xd7:
        l = vdrive_get_block_parameters(buffer, &channel, &drive, &track,
                                        &sector);

        if (l < 0) {
#ifdef DEBUG_DRIVE
            log_debug("b-R/W parsed OK. (l=%d) channel %d mode %d, "
                      "drive=%d, track=%d sector=%d.", l, channel,
                      vdrive->buffers[channel].mode, drive, track, sector);
#endif

            if (vdrive->buffers[channel].mode != BUFFER_MEMORY_BUFFER)
                return CBMDOS_IPE_NO_CHANNEL;

            if (command == 0xd7) {
                /* For write */
                if (vdrive->image->read_only || VDRIVE_IMAGE_FORMAT_4000_TEST)
                    return CBMDOS_IPE_WRITE_PROTECT_ON;
                if (vdrive_write_sector(vdrive, vdrive->buffers[channel].buffer,
                                            track, sector) < 0)
                    return CBMDOS_IPE_NOT_READY;
            } else {
                /* For read */
                rc = vdrive_read_sector(vdrive, vdrive->buffers[channel].buffer,
                                            track, sector);
                if (rc > 0)
                    return rc;
                if (rc < 0)
                    return CBMDOS_IPE_NOT_READY;
            }
            vdrive->buffers[channel].bufptr = 0;
        } else {
            log_error(vdrive_command_log, "b-R/W invalid parameter "
                      "C:%i D:%i T:%i S:%i.", channel, drive, track, sector);
            return l;
        }
        break;
      /* Old-style B-R and B-W */
      case 'R':
      case 'W':
        l = vdrive_get_block_parameters(buffer, &channel, &drive, &track,
                                        &sector);

        if (l < 0) {
#ifdef DEBUG_DRIVE
            log_debug("b-r/w parsed OK. (l=%d) channel %d mode %d, "
                      "drive=%d, track=%d sector=%d.", l, channel,
                      vdrive->buffers[channel].mode, drive, track, sector);
#endif

            if (vdrive->buffers[channel].mode != BUFFER_MEMORY_BUFFER)
                return CBMDOS_IPE_NO_CHANNEL;

            if (command == 'W') {
                /* For write */
                if (vdrive->image->read_only || VDRIVE_IMAGE_FORMAT_4000_TEST)
                    return CBMDOS_IPE_WRITE_PROTECT_ON;
                /* Update length of block based on the buffer pointer. */
                l = vdrive->buffers[channel].bufptr - 1;
                vdrive->buffers[channel].buffer[0] = ( l < 1 ? 1 : l );
                if (vdrive_write_sector(vdrive, vdrive->buffers[channel].buffer,
                                            track, sector) < 0)
                    return CBMDOS_IPE_NOT_READY;
                /* after write, buffer pointer is 1. */
                vdrive->buffers[channel].bufptr = 1;
            } else {
                /* For read */
                rc = vdrive_read_sector(vdrive, vdrive->buffers[channel].buffer,
                                            track, sector);
                /* set buffer length base on first value */
                vdrive->buffers[channel].length =
                    vdrive->buffers[channel].buffer[0] + 1;
                /* buffer pointer is 1, not 0. */
                vdrive->buffers[channel].bufptr = 1;
                if (rc > 0)
                    return rc;
                if (rc < 0)
                    return CBMDOS_IPE_NOT_READY;
            }
        } else {
            log_error(vdrive_command_log, "b-r/w invalid parameter "
                      "C:%i D:%i T:%i S:%i.", channel, drive, track, sector);
            return l;
        }
        break;
      case 'A':
      case 'F':
        l = vdrive_get_block_parameters(buffer, &drive, &track, &sector,
                                        &channel);
        if (l > 0) /* just 3 args used */
            return l;
        if (command == 'A') {
            if (!vdrive_bam_allocate_sector(vdrive->image_format, vdrive->bam,
                track, sector)) {
                /*
                 * Desired sector not free. Suggest another. XXX The 1541
                 * uses an inferior search function that only looks on
                 * higher tracks and can return sectors in the directory
                 * track.
                 */
                if (vdrive_bam_alloc_next_free_sector(vdrive, vdrive->bam,
                    (unsigned int*)&track, (unsigned int *)&sector) >= 0) {
                    /* Deallocate it and merely suggest it */
                    vdrive_bam_free_sector(vdrive->image_format, vdrive->bam,
                                           track, sector);
                } else {
                    /* Found none */
                    track = 0;
                    sector = 0;
                }
                vdrive_command_set_error(vdrive, CBMDOS_IPE_NO_BLOCK, track,
                                         sector);
                return CBMDOS_IPE_NO_BLOCK;
            }
        } else {
            vdrive_bam_free_sector(vdrive->image_format, vdrive->bam,
                                   track, sector);
        }
        break;
      case 'P':
        l = vdrive_get_block_parameters(buffer, &channel, &position, &track,
                                        &sector);
        if (l > 0) /* just 2 args used */
            return l;
        if (vdrive->buffers[channel].mode != BUFFER_MEMORY_BUFFER)
            return CBMDOS_IPE_NO_CHANNEL;
        vdrive->buffers[channel].bufptr = position;
        break;
      case 'E':
        l = vdrive_get_block_parameters(buffer, &channel, &drive, &track, &sector);
        log_warning(vdrive_command_log, "B-E: %d %d %d %d (needs TDE)", channel, drive, track, sector);
        break;
      default:
        return CBMDOS_IPE_INVAL;
    }
    return CBMDOS_IPE_OK;
}