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; }
int fsimage_write_sector(disk_image_t *image, BYTE *buf, unsigned int track, unsigned int sector) { int sectors; long offset; fsimage_t *fsimage; fsimage = image->media.fsimage; if (fsimage->fd == NULL) { log_error(fsimage_log, "Attempt to write without disk image."); return -1; } if (image->read_only != 0) { log_error(fsimage_log, "Attempt to write to read-only disk image."); return -1; } sectors = disk_image_check_sector(image, track, sector); switch (image->type) { case DISK_IMAGE_TYPE_D64: case DISK_IMAGE_TYPE_D67: case DISK_IMAGE_TYPE_D71: case DISK_IMAGE_TYPE_D81: case DISK_IMAGE_TYPE_D80: case DISK_IMAGE_TYPE_D82: case DISK_IMAGE_TYPE_X64: if (sectors < 0) { log_error(fsimage_log, "Track: %i, Sector: %i out of bounds.", track, sector); return -1; } offset = sectors << 8; if (image->type == DISK_IMAGE_TYPE_X64) offset += X64_HEADER_LENGTH; fseek(fsimage->fd, offset, SEEK_SET); if (fwrite((char *)buf, 256, 1, fsimage->fd) < 1) { log_error(fsimage_log, "Error writing T:%i S:%i to disk image.", track, sector); return -1; } /* Make sure the stream is visible to other readers. */ fflush(fsimage->fd); break; case DISK_IMAGE_TYPE_G64: if (fsimage_gcr_write_sector(image, buf, track, sector) < 0) return -1; break; default: log_error(fsimage_log, "Unknown disk image. Cannot write sector."); return -1; } return 0; }
int fsimage_dxx_write_sector(disk_image_t *image, const BYTE *buf, const disk_addr_t *dadr) { int sectors; long offset; fsimage_t *fsimage; fsimage = image->media.fsimage; sectors = disk_image_check_sector(image, dadr->track, dadr->sector); if (sectors < 0) { log_error(fsimage_dxx_log, "Track: %i, Sector: %i out of bounds.", dadr->track, dadr->sector); return -1; } offset = sectors * 256; if (image->type == DISK_IMAGE_TYPE_X64) { offset += X64_HEADER_LENGTH; } if (util_fpwrite(fsimage->fd, buf, 256, offset) < 0) { log_error(fsimage_dxx_log, "Error writing T:%i S:%i to disk image.", dadr->track, dadr->sector); return -1; } if (image->gcr != NULL) { gcr_write_sector(&image->gcr->tracks[(dadr->track * 2) - 2], buf, (BYTE)dadr->sector); } if ((fsimage->error_info.map != NULL) && (fsimage->error_info.map[sectors] != CBMDOS_FDC_ERR_OK)) { offset = fsimage->error_info.len * 256 + sectors; if (image->type == DISK_IMAGE_TYPE_X64) { offset += X64_HEADER_LENGTH; } fsimage->error_info.map[sectors] = CBMDOS_FDC_ERR_OK; if (util_fpwrite(fsimage->fd, &fsimage->error_info.map[sectors], 1, offset) < 0) { log_error(fsimage_dxx_log, "Error writing T:%i S:%i error info to disk image.", dadr->track, dadr->sector); } } /* Make sure the stream is visible to other readers. */ fflush(fsimage->fd); return 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->image_format, vdrive->bam, t, s)) break; /* FIXME: This seems to be redundant. AB19981124 */ vdrive_bam_free_sector(vdrive->image_format, vdrive->bam, t, s); disk_image_read_sector(vdrive->image, buf, t, s); t = (int)buf[0]; s = (int)buf[1]; } }
int fsimage_dxx_write_half_track(disk_image_t *image, unsigned int half_track, const disk_track_t *raw) { unsigned int track, sector, max_sector = 0, error_info_created = 0; int sectors, res; long offset; BYTE *buffer; fsimage_t *fsimage = image->media.fsimage; fdc_err_t rf; track = half_track / 2; max_sector = disk_image_sector_per_track(image->type, track); sectors = disk_image_check_sector(image, track, 0); if (sectors < 0) { log_error(fsimage_dxx_log, "Track: %i out of bounds.", track); return -1; } if (track > image->tracks) { if (fsimage->error_info.map) { int newlen = sectors + max_sector; fsimage->error_info.map = lib_realloc(fsimage->error_info.map, newlen); memset(fsimage->error_info.map + fsimage->error_info.len, 0, newlen - fsimage->error_info.len); fsimage->error_info.len = newlen; fsimage->error_info.dirty = 1; } image->tracks = track; } buffer = lib_calloc(max_sector, 256); for (sector = 0; sector < max_sector; sector++) { rf = gcr_read_sector(raw, &buffer[sector * 256], (BYTE)sector); if (rf != CBMDOS_FDC_ERR_OK) { log_error(fsimage_dxx_log, "Could not find data sector of T:%d S:%d.", track, sector); if (fsimage->error_info.map == NULL) { /* create map if does not exists */ int newlen = disk_image_check_sector(image, image->tracks, 0); if (newlen >= 0) { newlen += disk_image_sector_per_track(image->type, image->tracks); fsimage->error_info.map = lib_malloc(newlen); memset(fsimage->error_info.map, (BYTE)CBMDOS_FDC_ERR_OK, newlen); fsimage->error_info.len = newlen; fsimage->error_info.dirty = 1; error_info_created = 1; } } } if (fsimage->error_info.map != NULL) { if (fsimage->error_info.map[sectors + sector] != (BYTE)rf) { fsimage->error_info.map[sectors + sector] = (BYTE)rf; fsimage->error_info.dirty = 1; } } } offset = sectors * 256; if (image->type == DISK_IMAGE_TYPE_X64) { offset += X64_HEADER_LENGTH; } if (util_fpwrite(fsimage->fd, buffer, max_sector * 256, offset) < 0) { log_error(fsimage_dxx_log, "Error writing T:%i to disk image.", track); lib_free(buffer); return -1; } lib_free(buffer); if (fsimage->error_info.map) { if (fsimage->error_info.dirty) { offset = fsimage->error_info.len * 256 + sectors; if (image->type == DISK_IMAGE_TYPE_X64) { offset += X64_HEADER_LENGTH; } fsimage->error_info.dirty = 0; if (error_info_created) { res = util_fpwrite(fsimage->fd, fsimage->error_info.map, fsimage->error_info.len, fsimage->error_info.len * 256); } else { res = util_fpwrite(fsimage->fd, fsimage->error_info.map + sectors, max_sector, offset); } if (res < 0) { log_error(fsimage_dxx_log, "Error writing T:%i error info to disk image.", track); return -1; } } } /* Make sure the stream is visible to other readers. */ fflush(fsimage->fd); return 0; }
int fsimage_dxx_read_sector(const disk_image_t *image, BYTE *buf, const disk_addr_t *dadr) { int sectors; long offset; fsimage_t *fsimage = image->media.fsimage; fdc_err_t rf; sectors = disk_image_check_sector(image, dadr->track, dadr->sector); if (sectors < 0) { log_error(fsimage_dxx_log, "Track %i, Sector %i out of bounds.", dadr->track, dadr->sector); return -1; } offset = sectors * 256; if (image->type == DISK_IMAGE_TYPE_X64) { offset += X64_HEADER_LENGTH; } if (image->gcr == NULL) { if (util_fpread(fsimage->fd, buf, 256, offset) < 0) { log_error(fsimage_dxx_log, "Error reading T:%i S:%i from disk image.", dadr->track, dadr->sector); return -1; } else { rf = fsimage->error_info.map ? fsimage->error_info.map[sectors] : CBMDOS_FDC_ERR_OK; } } else { rf = gcr_read_sector(&image->gcr->tracks[(dadr->track * 2) - 2], buf, (BYTE)dadr->sector); } switch (rf) { case CBMDOS_FDC_ERR_OK: return CBMDOS_IPE_OK; /* 0 */ case CBMDOS_FDC_ERR_HEADER: return CBMDOS_IPE_READ_ERROR_BNF; /* 20 */ case CBMDOS_FDC_ERR_SYNC: return CBMDOS_IPE_READ_ERROR_SYNC; /* 21 */ case CBMDOS_FDC_ERR_NOBLOCK: return CBMDOS_IPE_READ_ERROR_DATA; /* 22 */ case CBMDOS_FDC_ERR_DCHECK: return CBMDOS_IPE_READ_ERROR_CHK; /* 23 */ case CBMDOS_FDC_ERR_VERIFY: return CBMDOS_IPE_WRITE_ERROR_VER; /* 25 */ case CBMDOS_FDC_ERR_WPROT: return CBMDOS_IPE_WRITE_PROTECT_ON; /* 26 */ case CBMDOS_FDC_ERR_HCHECK: return CBMDOS_IPE_READ_ERROR_BCHK; /* 27 */ case CBMDOS_FDC_ERR_BLENGTH: return CBMDOS_IPE_WRITE_ERROR_BIG; /* 28 */ case CBMDOS_FDC_ERR_ID: return CBMDOS_IPE_DISK_ID_MISMATCH; /* 29 */ case CBMDOS_FDC_ERR_DRIVE: return CBMDOS_IPE_NOT_READY; /* 74 */ case CBMDOS_FDC_ERR_DECODE: return CBMDOS_IPE_READ_ERROR_GCR; /* 24 */ default: return CBMDOS_IPE_OK; } }
int fsimage_read_dxx_image(const disk_image_t *image) { BYTE buffer[256], *bam_id; int gap; unsigned int track, sector, track_size; gcr_header_t header; fdc_err_t rf; int double_sided = 0; fsimage_t *fsimage = image->media.fsimage; unsigned int max_sector; BYTE *ptr; int half_track; int sectors; long offset; if (image->type == DISK_IMAGE_TYPE_D80 || image->type == DISK_IMAGE_TYPE_D82) { sectors = disk_image_check_sector(image, BAM_TRACK_8050, BAM_SECTOR_8050); bam_id = &buffer[BAM_ID_8050]; } else { sectors = disk_image_check_sector(image, BAM_TRACK_1541, BAM_SECTOR_1541); bam_id = &buffer[BAM_ID_1541]; } bam_id[0] = bam_id[1] = 0xa0; if (sectors >= 0) { util_fpread(fsimage->fd, buffer, 256, sectors << 8); } header.id1 = bam_id[0]; header.id2 = bam_id[1]; /* check double sided images */ double_sided = (image->type == DISK_IMAGE_TYPE_D71) && !(buffer[0x03] & 0x80); for (header.track = track = 1; track <= image->max_half_tracks / 2; track++, header.track++) { half_track = track * 2 - 2; track_size = disk_image_raw_track_size(image->type, track); if (image->gcr->tracks[half_track].data == NULL) { image->gcr->tracks[half_track].data = lib_malloc(track_size); } else if (image->gcr->tracks[half_track].size != (int)track_size) { image->gcr->tracks[half_track].data = lib_realloc(image->gcr->tracks[half_track].data, track_size); } ptr = image->gcr->tracks[half_track].data; image->gcr->tracks[half_track].size = track_size; if (track <= image->tracks) { if (double_sided && track == 36) { sectors = disk_image_check_sector(image, BAM_TRACK_1571 + 35, BAM_SECTOR_1571); buffer[BAM_ID_1571] = buffer[BAM_ID_1571 + 1] = 0xa0; if (sectors >= 0) { util_fpread(fsimage->fd, buffer, 256, sectors << 8); } header.id1 = buffer[BAM_ID_1571]; /* second side, update id and track */ header.id2 = buffer[BAM_ID_1571 + 1]; header.track = 1; } gap = disk_image_gap_size(image->type, track); max_sector = disk_image_sector_per_track(image->type, track); /* Clear track to avoid read errors. */ memset(ptr, 0x55, track_size); for (sector = 0; sector < max_sector; sector++) { sectors = disk_image_check_sector(image, track, sector); offset = sectors * 256; if (image->type == DISK_IMAGE_TYPE_X64) { offset += X64_HEADER_LENGTH; } if (sectors >= 0) { rf = CBMDOS_FDC_ERR_DRIVE; if (util_fpread(fsimage->fd, buffer, 256, offset) >= 0) { if (fsimage->error_info.map != NULL) { rf = fsimage->error_info.map[sectors]; } } header.sector = sector; gcr_convert_sector_to_GCR(buffer, ptr, &header, 9, 5, rf); } ptr += SECTOR_GCR_SIZE_WITH_HEADER + 9 + gap + 5; } } else { memset(ptr, 0x55, track_size); } /* Clear odd track */ half_track++; if (image->gcr->tracks[half_track].data) { lib_free(image->gcr->tracks[half_track].data); image->gcr->tracks[half_track].data = NULL; image->gcr->tracks[half_track].size = 0; } } return 0; }
int fsimage_read_sector(disk_image_t *image, BYTE *buf, unsigned int track, unsigned int sector) { int sectors; long offset; fsimage_t *fsimage; fsimage = image->media.fsimage; if (fsimage->fd == NULL) { #ifdef CELL_DEBUG printf("ERROR: Attempt to read without disk image.\n"); #endif return 74; } switch (image->type) { case DISK_IMAGE_TYPE_D64: case DISK_IMAGE_TYPE_D67: case DISK_IMAGE_TYPE_D71: case DISK_IMAGE_TYPE_D81: case DISK_IMAGE_TYPE_D80: case DISK_IMAGE_TYPE_D82: case DISK_IMAGE_TYPE_X64: sectors = disk_image_check_sector(image, track, sector); if (sectors < 0) { #ifdef CELL_DEBUG printf("ERROR: Track %i, Sector %i out of bounds.\n", track, sector); #endif return 66; } offset = sectors << 8; if (image->type == DISK_IMAGE_TYPE_X64) offset += X64_HEADER_LENGTH; fseek(fsimage->fd, offset, SEEK_SET); if (fread((char *)buf, 256, 1, fsimage->fd) < 1) { #ifdef CELL_DEBUG printf("ERROR: Error reading T:%i S:%i from disk image.\n", track, sector); #endif return -1; } if (fsimage->error_info != NULL) { switch (fsimage->error_info[sectors]) { case 0x0: case 0x1: return CBMDOS_IPE_OK; /* 0 */ case 0x2: return CBMDOS_IPE_READ_ERROR_BNF; /* 20 */ case 0x3: return CBMDOS_IPE_READ_ERROR_SYNC; /* 21 */ case 0x4: return CBMDOS_IPE_READ_ERROR_DATA; /* 22 */ case 0x5: return CBMDOS_IPE_READ_ERROR_CHK; /* 23 */ case 0x7: return CBMDOS_IPE_WRITE_ERROR_VER; /* 25 */ case 0x8: return CBMDOS_IPE_WRITE_PROTECT_ON; /* 26 */ case 0x9: return CBMDOS_IPE_READ_ERROR_BCHK; /* 27 */ case 0xA: return CBMDOS_IPE_WRITE_ERROR_BIG; /* 28 */ case 0xB: return CBMDOS_IPE_DISK_ID_MISMATCH; /* 29 */ case 0xF: return CBMDOS_IPE_NOT_READY; /* 74 */ case 0x10: return CBMDOS_IPE_READ_ERROR_GCR; /* 24 */ default: return 0; } } break; case DISK_IMAGE_TYPE_G64: if (fsimage_gcr_read_sector(image, buf, track, sector) < 0) return -1; break; default: #ifdef CELL_DEBUG printf("ERROR: Unknown disk image type %i. Cannot read sector.", image->type); #endif return -1; } return 0; }