Пример #1
0
static int vdrive_command_copy(vdrive_t *vdrive, char *dest, int length)
{
    char *name, *files, *p, c;
    int status = 0;

    /* Split command line */
    if (!dest || !(files = (char *)memchr(++dest, '=', length)) ) {
        return CBMDOS_IPE_SYNTAX;
    }
    *files++ = 0;

#ifdef DEBUG_DRIVE
    log_debug("COPY: dest= '%s', orig= '%s'.", dest, files);
#endif

    if (vdrive_iec_open(vdrive, (BYTE *)dest, (unsigned int)strlen(dest), 1, NULL))
        return CBMDOS_IPE_FILE_EXISTS;

    name = p = files;
    while (*name) { /* Loop for given files.  */
        for (; *p && *p != ','; p++) ;
        *p = 0;

        /* Skip optional colon. */
        if ((files = strchr(name, ':')))
            name = files + 1;

#ifdef DEBUG_DRIVE
        log_debug("searching for file '%s'.", name);
#endif
        if (vdrive_iec_open(vdrive, (BYTE *)name, (unsigned int)strlen(name), 0, NULL)) {
            vdrive_iec_close(vdrive, 1);
            return CBMDOS_IPE_NOT_FOUND;
        }

        do {
            status = vdrive_iec_read(vdrive, (BYTE *)&c, 0);
            if (vdrive_iec_write(vdrive, c, 1)) {
                vdrive_iec_close(vdrive, 0); /* No space on disk.  */
                vdrive_iec_close(vdrive, 1);
                return CBMDOS_IPE_DISK_FULL;
            }
        } while (status == SERIAL_OK);

        vdrive_iec_close(vdrive, 0);
        name = p + 1; /* Next file */
    }
    vdrive_iec_close(vdrive, 1);
    return CBMDOS_IPE_OK;
}
Пример #2
0
int autostart_prg_with_disk_image(const char *file_name,
                                  fileio_info_t *fh,
                                  log_t log,
                                  const char *image_name)
{
    const int drive = 8;
    const int secondary = 1;
    autostart_prg_t *prg;
    vdrive_t *vdrive;
    int i;
    int old_tde_state;
    int file_name_size;
    BYTE data;
    unsigned int disk_image_type;
    int result, result2;

    /* identify disk image type */
    switch (drive_get_disk_drive_type(drive - 8)) {
    case DRIVE_TYPE_1540:
    case DRIVE_TYPE_1541:
    case DRIVE_TYPE_1541II:
    case DRIVE_TYPE_1551:
    case DRIVE_TYPE_1570:
    case DRIVE_TYPE_2031:
        disk_image_type = DISK_IMAGE_TYPE_D64;
        break;
    case DRIVE_TYPE_2040:
    case DRIVE_TYPE_3040:
    case DRIVE_TYPE_4040:
        disk_image_type = DISK_IMAGE_TYPE_D67;
        break;
    case DRIVE_TYPE_1571:
    case DRIVE_TYPE_1571CR:
        disk_image_type = DISK_IMAGE_TYPE_D71;
        break;
    case DRIVE_TYPE_1581:
    case DRIVE_TYPE_2000:
    case DRIVE_TYPE_4000:
        disk_image_type = DISK_IMAGE_TYPE_D81;
        break;
    case DRIVE_TYPE_8050:
        disk_image_type = DISK_IMAGE_TYPE_D80;
        break;
    case DRIVE_TYPE_8250:
    case DRIVE_TYPE_1001:
        disk_image_type = DISK_IMAGE_TYPE_D82;
        break;
    default:
        log_error(log, "No idea what disk image format to use.");
        return -1;
    }

    /* read prg file */
    prg = load_prg(file_name, fh, log);
    if (prg == NULL) {
        return -1;
    }

    /* disable TDE */
    resources_get_int("DriveTrueEmulation", &old_tde_state);
    if (old_tde_state != 0) {
        log_message(log, "Turning true drive emulation off.");
        resources_set_int("DriveTrueEmulation", 0);
    }

    do {
        result = -1;

        /* create empty image */
        if (vdrive_internal_create_format_disk_image(image_name, (char *)"AUTOSTART", disk_image_type) < 0) {
            log_error(log, "Error creating autostart disk image: %s", image_name);
            break;
        }

        /* attach disk image */
        if (file_system_attach_disk(drive, image_name) < 0) {
            log_error(log, "Could not attach disk image: %s", image_name);
            break;
        }

        /* get vdrive */
        vdrive = file_system_get_vdrive((unsigned int)drive);
        if (vdrive == NULL) {
            break;
        }

        /* get file name size */
        file_name_size = strlen((const char *)fh->name);
        if (file_name_size > 16) {
            file_name_size = 16;
        }

        /* open file on disk */
        if (vdrive_iec_open(vdrive, (const BYTE *)fh->name, file_name_size, secondary, NULL) != SERIAL_OK) {
            log_error(log, "Could not open file");
            break;
        }

        result2 = 0;
        /* write PRG data to file */
        for (i = -2; i < (int)prg->size; i++) {
            switch (i) {
            case -2:
                data = (BYTE)prg->start_addr;
                break;
            case -1:
                data = (BYTE)(prg->start_addr >> 8);
                break;
            default:
                data = prg->data[i];
                break;
            }
            if (vdrive_iec_write(vdrive, data, secondary) != SERIAL_OK) {
                log_error(log, "Could not write file");
                result2 = -1;
                break;
            }
        }

        /* close file */
        if (vdrive_iec_close(vdrive, secondary) != SERIAL_OK) {
            log_error(log, "Could not close file");
            break;
        }
        result = result2;
    } while (0);

    /* free prg file */
    free_prg(prg);

    /* re-enable TDE */
    if (old_tde_state != 0) {
        log_message(log, "Turning true drive emulation on.");
        resources_set_int("DriveTrueEmulation", old_tde_state);
    }

    /* ready */
    return result;
}
Пример #3
0
int vdrive_iec_open(vdrive_t *vdrive, const BYTE *name, unsigned int length,
                    unsigned int secondary, cbmdos_cmd_parse_t *cmd_parse_ext)
{
    bufferinfo_t *p = &(vdrive->buffers[secondary]);
    BYTE *slot; /* Current directory entry */
    int rc, status = SERIAL_OK;
    /* FIXME: This should probably be set to zero */
    cbmdos_cmd_parse_t cmd_parse_stat;
    cbmdos_cmd_parse_t *cmd_parse;
    BYTE name_stat[17];
    unsigned int opentype;

    if (cmd_parse_ext != NULL) {
        cmd_parse = cmd_parse_ext;
        memset(name_stat, 0, sizeof(name_stat));
        strncpy((char *)name_stat, cmd_parse->parsecmd, sizeof(name_stat) - 1);
        name = name_stat;
        length = (unsigned int)strlen((char *)name);
        secondary = cmd_parse->secondary;
    } else {
        cmd_parse = &cmd_parse_stat;
    }

    if (cmd_parse_ext == NULL
        && (!name || !*name) && p->mode != BUFFER_COMMAND_CHANNEL) {
        return SERIAL_NO_DEVICE;
    }

    /* No floppy in drive?   */
    if (vdrive->image == NULL
        && p->mode != BUFFER_COMMAND_CHANNEL
        && secondary != 15
        && *name != '#') {
        vdrive_command_set_error(vdrive, CBMDOS_IPE_NOT_READY, 18, 0);
        log_message(vdrive_iec_log, "Drive not ready.");
        return SERIAL_ERROR;
    }

#ifdef DEBUG_DRIVE
    log_debug("VDRIVE#%i: OPEN: Name '%s' (%d) on ch %d.",
              vdrive->unit, name, length, secondary);
#endif

    /*
     * If channel is command channel, name will be used as write. Return only
     * status of last write ...
     */
    if (p->mode == BUFFER_COMMAND_CHANNEL) {
        unsigned int n;

        for (n = 0; n < length; n++) {
            status = vdrive_iec_write(vdrive, name[n], secondary);
        }

        if (length) {
            p->readmode = CBMDOS_FAM_WRITE;
        } else {
            p->readmode = CBMDOS_FAM_READ;
        }
        return status;
    }

    /*
     * Clear error flag
     */
    vdrive_command_set_error(vdrive, CBMDOS_IPE_OK, 0, 0);

    /*
     * In use ?
     */
    if (p->mode != BUFFER_NOT_IN_USE) {
#ifdef DEBUG_DRIVE
        log_debug("Cannot open channel %d. Mode is %d.", secondary, p->mode);
#endif
        vdrive_command_set_error(vdrive, CBMDOS_IPE_NO_CHANNEL, 0, 0);
        return SERIAL_ERROR;
    }

    if (cmd_parse_ext == NULL) {
        cmd_parse->cmd = name;
        cmd_parse->cmdlength = length;
        cmd_parse->secondary = secondary;
        /* make sure this is zero, since it isn't set below */
        cmd_parse->recordlength = 0;
        cmd_parse->drive = -1;

        rc = cbmdos_command_parse(cmd_parse);

        if (rc != CBMDOS_IPE_OK) {
            status = SERIAL_ERROR;
            goto out;
        }
#ifdef DEBUG_DRIVE
        log_debug("Raw file name: `%s', length: %i.", name, length);
        log_debug("Parsed file name: `%s', reallength: %i. drive: %i",
                  cmd_parse->parsecmd, cmd_parse->parselength, cmd_parse->drive);
#endif
        if (cmd_parse->drive != -1) {
            /* a drive number was specified in the filename */
            if ((vdrive->image_format == VDRIVE_IMAGE_FORMAT_8050) ||
                (vdrive->image_format == VDRIVE_IMAGE_FORMAT_8250) ||
                (vdrive->image_format == VDRIVE_IMAGE_FORMAT_2040)) {
                /* FIXME: dual disk drives not supported */
                if (cmd_parse->drive == 0) {
                    /* FIXME: use drive 0 */
                } else if (cmd_parse->drive == 1) {
                    /* FIXME: use drive 1 */
                    /*
                        since some software gets confused when it sees the same disk in
                        both drives, we bail out with an error instead.
                    */
                    log_warning(LOG_DEFAULT, "second drive of dual disk drive is not supported");
                    vdrive_command_set_error(vdrive, CBMDOS_IPE_NOT_READY, 18, 0);
                    status = SERIAL_ERROR;
                    goto out;
                } else {
                    /* FIXME: what exactly does the drive do if drivenumber is > 1, look
                              up the file on both drives perhaps ?
                    */
                }
            } else {
                /* single disk drives seem to ignore the drive number, *except* if it
                   is 1, which will result in an error. */
                if (cmd_parse->drive == 1) {
                    vdrive_command_set_error(vdrive, CBMDOS_IPE_NOT_READY, 18, 0);
                    status = SERIAL_ERROR;
                    goto out;
                }
            }
        }
    }

    /* Limit file name to 16 chars.  */
    if (cmd_parse->parselength > 16) {
        cmd_parse->parselength = 16;
    }

    /*
     * Internal buffer ?
     */
    if (*name == '#') {
        vdrive_alloc_buffer(p, BUFFER_MEMORY_BUFFER);

        /* the pointer is actually 1 on the real drives. */
        /* this probably relates to the B-R and B-W commands. */
        /* 1541 firmware: $cb84 - open channel, $cc0f bp = 1 */
        p->bufptr = 1;
        /* we need a length to support the original B-R and B-W
           commands. */
        p->length = 256;
        status = SERIAL_OK;
        goto out;
    }

    /* Clear update flag */
    p->needsupdate = 0;

    /*
     * Directory read
     * A little-known feature of the 1541: open 1,8,2,"$" (or even 1,8,1).
     * It gives you the BAM+DIR as a sequential file, containing the data
     * just as it appears on disk.  -Olaf Seibert
     */

    if (*name == '$') {
        p->readmode = CBMDOS_FAM_READ;
        status = iec_open_read_directory(vdrive, secondary, cmd_parse);
        goto out;
    }

    /*
     * Check that there is room on directory.
     */
    if (cmd_parse->readmode == CBMDOS_FAM_READ || cmd_parse->readmode == CBMDOS_FAM_APPEND) {
        opentype = cmd_parse->filetype;
    } else {
        opentype = CBMDOS_FT_DEL;
    }

    vdrive_dir_find_first_slot(vdrive, cmd_parse->parsecmd, cmd_parse->parselength, opentype, &p->dir);

    /*
     * Find the first non-DEL entry in the directory (if it exists).
     */
    do {
        slot = vdrive_dir_find_next_slot(&p->dir);
    } while (slot && ((slot[SLOT_TYPE_OFFSET] & 0x07) == CBMDOS_FT_DEL));

    p->readmode = cmd_parse->readmode;
    p->slot = slot;

    /* Call REL function if we are creating OR opening one */
    if (cmd_parse->filetype == CBMDOS_FT_REL ||
        ( slot && (slot[SLOT_TYPE_OFFSET] & 0x07) == CBMDOS_FT_REL)) {
        /* Make sure the record length of the opening command is the same as
           the record length in the directory slot, if not DOS ERROR 50 */
        if (slot && cmd_parse->recordlength > 0 &&
            slot[SLOT_RECORD_LENGTH] != cmd_parse->recordlength) {
            vdrive_command_set_error(vdrive, CBMDOS_IPE_NO_RECORD, 0, 0);
            status = SERIAL_ERROR;
            goto out;
        }
        /* At this point the record lengths are the same (or will be), so set
            them equal. */
        if (slot) {
            cmd_parse->recordlength = slot[SLOT_RECORD_LENGTH];
        }
        status = vdrive_rel_open(vdrive, secondary, cmd_parse, name);
        goto out;
    }

    if (cmd_parse->readmode == CBMDOS_FAM_READ) {
        status = iec_open_read(vdrive, secondary);
    } else {
        status = iec_open_write(vdrive, secondary, cmd_parse, name);
    }

out:
    lib_free(cmd_parse->parsecmd);
    return status;
}
Пример #4
0
int autostart_prg_with_disk_image(const char *file_name, fileio_info_t *fh, const char *image_name)
{
	const int drive = 8;
	const int secondary = 1;
	autostart_prg_t *prg;
	vdrive_t *vdrive;
	int i;
	int old_tde_state;
	int file_name_size;
	BYTE lo,hi;

	/* read prg file */ 
	prg = load_prg(file_name, fh);
	if (prg == NULL) {
		return -1;
	}

	/* disable TDE */
	resources_get_int("DriveTrueEmulation", &old_tde_state);
	if (old_tde_state != 0)
		resources_set_int("DriveTrueEmulation", 0);

	/* create empty image */
	if (vdrive_internal_create_format_disk_image(image_name, 
				(char *)"AUTOSTART", DISK_IMAGE_TYPE_D64) <0 ) {
		//log_error(log, "Error creating autostart disk image: %s", image_name);
		free_prg(prg);
		return -1;
	}

	/* attach disk image */
	if (file_system_attach_disk(drive, image_name) < 0) {
		//log_error(log, "Could not attach disk image: %s", image_name);
		free_prg(prg);
		return -1;
	}

	/* copy file to disk */
	vdrive = file_system_get_vdrive((unsigned int)drive);
	if (vdrive == NULL) {
		free_prg(prg);
		return -1;
	}

	/* get file name size */
	file_name_size = strlen((const char *)fh->name);
	if (file_name_size > 16) {
		file_name_size = 16;
	}

	/* open file on disk */
	if (vdrive_iec_open(vdrive, (const BYTE *)fh->name,
				file_name_size, secondary, NULL) != SERIAL_OK) {
		//log_error(log, "Could not open file");
		free_prg(prg);
		return -1;
	}

	/* write start address to file */
	lo = (BYTE)(prg->start_addr & 0xff);
	hi = (BYTE)((prg->start_addr >> 8) & 0xff);
	if ((vdrive_iec_write(vdrive, lo, secondary) != SERIAL_OK) ||
			(vdrive_iec_write(vdrive, hi, secondary) != SERIAL_OK)) {
		//log_error(log, "Could not write file");
		free_prg(prg);
		return -1;
	}

	/* write PRG data to file */
	for (i = 0; i < prg->size; i++) {
		if (vdrive_iec_write(vdrive, prg->data[i], secondary) != SERIAL_OK) {
			//log_error(log, "Could not write file");
			free_prg(prg);
			return -1;
		}
	}

	/* close file */
	if (vdrive_iec_close(vdrive, secondary) != SERIAL_OK) {
		//log_error(log, "Could not close file");
		free_prg(prg);
		return -1;
	}

	/* free prg file */
	free_prg(prg);

	/* re-enable TDE */
	if (old_tde_state != 0)
		resources_set_int("DriveTrueEmulation", old_tde_state);

	/* ready */
	return 0;
}