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; }
void vdrive_close_all_channels(vdrive_t *vdrive) { unsigned int i; bufferinfo_t *p; for (i = 0; i <= 15; i++) { p = &(vdrive->buffers[i]); if (p->mode != BUFFER_NOT_IN_USE && p->mode != BUFFER_COMMAND_CHANNEL) vdrive_iec_close(vdrive, i); } }
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; }
static int iec_open_read(vdrive_t *vdrive, unsigned int secondary) { int type; unsigned int track, sector; bufferinfo_t *p = &(vdrive->buffers[secondary]); BYTE *slot = p->slot; if (!slot) { vdrive_iec_close(vdrive, secondary); vdrive_command_set_error(vdrive, CBMDOS_IPE_NOT_FOUND, 0, 0); return SERIAL_ERROR; } type = slot[SLOT_TYPE_OFFSET] & 0x07; track = (unsigned int)slot[SLOT_FIRST_TRACK]; sector = (unsigned int)slot[SLOT_FIRST_SECTOR]; /* Del, Seq, Prg, Usr (Rel not supported here). */ if (type != CBMDOS_FT_REL) return iec_open_read_sequential(vdrive, secondary, track, sector); return SERIAL_ERROR; }
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; }
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; }
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; }