int fsimage_gcr_read_half_track(const disk_image_t *image, unsigned int half_track, disk_track_t *raw) { WORD track_len; BYTE buf[4]; long offset; fsimage_t *fsimage; WORD max_track_length; BYTE num_half_tracks; fsimage = image->media.fsimage; raw->data = NULL; raw->size = 0; offset = fsimage_gcr_seek_half_track(fsimage, half_track, &max_track_length, &num_half_tracks); if (offset < 0) { return -1; } if (offset != 0) { if (util_fpread(fsimage->fd, buf, 2, offset) < 0) { log_error(fsimage_gcr_log, "Could not read GCR disk image."); return -1; } track_len = util_le_buf_to_word(buf); if ((track_len < 1) || (track_len > max_track_length)) { log_error(fsimage_gcr_log, "Track field length %u is not supported.", track_len); return -1; } raw->data = lib_calloc(1, track_len); raw->size = track_len; if (fread(raw->data, track_len, 1, fsimage->fd) < 1) { log_error(fsimage_gcr_log, "Could not read GCR disk image."); return -1; } } else { raw->size = disk_image_raw_track_size(image->type, half_track / 2); raw->data = lib_malloc(raw->size); memset(raw->data, 0x55, raw->size); } return 0; }
static int disk_image_check_for_gcr(disk_image_t *image) { WORD max_track_length; BYTE header[32]; fsimage_t *fsimage; fsimage = image->media.fsimage; if (util_fpread(fsimage->fd, header, sizeof (header), 0) < 0) { log_error(disk_image_probe_log, "Cannot read image header."); return 0; } if (strncmp("GCR-1541", (char*)header, 8)) { return 0; } if (header[8] != 0) { log_error(disk_image_probe_log, "Import GCR: Unknown GCR image version %i.", (int)header[8]); return 0; } if (header[9] < 1 || header[9] > MAX_GCR_TRACKS * 2) { log_error(disk_image_probe_log, "Import GCR: Invalid number of tracks (%i).", (int)header[9]); return 0; } max_track_length = util_le_buf_to_word(&header[10]); if (max_track_length > NUM_MAX_MEM_BYTES_TRACK) { log_error(disk_image_probe_log, "Too large max track length."); return 0; } image->type = DISK_IMAGE_TYPE_G64; image->tracks = header[9] / 2; image->max_half_tracks = header[9]; disk_image_check_log(image, "GCR"); return 1; }
/* The buffer pointer passed to this function points to the character following '-' in the memory command. The buffer pointer passed to the sub-functions points to the byte after the first argument (address) which is passed separately. */ static int vdrive_command_memory(vdrive_t *vdrive, BYTE *buffer, unsigned int length) { WORD addr; if (length < 5) { return CBMDOS_IPE_SYNTAX; } addr = util_le_buf_to_word(buffer + 1); switch (*buffer) { case 'W': return vdrive_command_memory_write(vdrive, buffer + 3, addr, length); case 'R': return vdrive_command_memory_read(vdrive, buffer + 3, addr, length); case 'E': return vdrive_command_memory_exec(vdrive, NULL, addr, length); default: break; } return CBMDOS_IPE_INVAL; }
static long fsimage_gcr_seek_half_track(fsimage_t *fsimage, unsigned int half_track, WORD *max_track_length, BYTE *num_half_tracks) { BYTE buf[12]; if (fsimage->fd == NULL) { log_error(fsimage_gcr_log, "Attempt to read without disk image."); return -1; } if (util_fpread(fsimage->fd, buf, 12, 0) < 0) { log_error(fsimage_gcr_log, "Could not read GCR disk image."); return -1; } if (memcmp(gcr_image_header_expected, buf, sizeof(gcr_image_header_expected)) != 0) { log_error(fsimage_gcr_log, "Unexpected GCR header found." ); return -1; } *num_half_tracks = buf[9]; if (*num_half_tracks > MAX_GCR_TRACKS) { log_error(fsimage_gcr_log, "Too many half tracks." ); return -1; } *max_track_length = util_le_buf_to_word(&buf[10]); if (*max_track_length > NUM_MAX_MEM_BYTES_TRACK) { log_error(fsimage_gcr_log, "Too large max track length."); return -1; } if (util_fpread(fsimage->fd, buf, 4, 12 + (half_track - 2) * 4) < 0) { log_error(fsimage_gcr_log, "Could not read GCR disk image."); return -1; } return util_le_buf_to_dword(buf); }