static int fsimage_create_p64(disk_image_t *image) { TP64MemoryStream P64MemoryStreamInstance; TP64Image P64Image; BYTE gcr_track[7928], *gcrptr; unsigned int track, sector; fsimage_t *fsimage; int rc = -1; fsimage = image->media.fsimage; P64ImageCreate(&P64Image); for (track = 0; track < MAX_TRACKS_1541; track++) { const int raw_track_size[4] = { 6250, 6666, 7142, 7692 }; memset(&gcr_track[0], 0x55, 7928); gcrptr = &gcr_track[0]; for (sector = 0; sector < disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, track + 1); sector++) { BYTE chksum, id[2], rawdata[260]; int i; id[0] = id[1] = 0xa0; memset(rawdata, 0, 260); rawdata[0] = 7; chksum = rawdata[1]; for (i = 1; i < 256; i++) { chksum ^= rawdata[i + 1]; } rawdata[257] = chksum; gcr_convert_sector_to_GCR(rawdata, gcrptr, track + 1, sector, id[0], id[1], 0); gcrptr += 360; } P64PulseStreamConvertFromGCR(&P64Image.PulseStreams[(track + 1) << 1], (void*)&gcr_track[0], raw_track_size[disk_image_speed_map_1541(track)] << 3); } P64MemoryStreamCreate(&P64MemoryStreamInstance); P64MemoryStreamClear(&P64MemoryStreamInstance); if (P64ImageWriteToStream(&P64Image,&P64MemoryStreamInstance)) { if (fwrite(P64MemoryStreamInstance.Data, P64MemoryStreamInstance.Size, 1, fsimage->fd) < 1) { log_error(createdisk_log, "Cannot write image data."); rc = -1; } else { rc = 0; } } P64MemoryStreamDestroy(&P64MemoryStreamInstance); P64ImageDestroy(&P64Image); return rc; }
int vdrive_get_max_sectors(unsigned int type, unsigned int track) { switch (type) { case VDRIVE_IMAGE_FORMAT_1541: return disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, track); case VDRIVE_IMAGE_FORMAT_2040: return disk_image_sector_per_track(DISK_IMAGE_TYPE_D67, track); case VDRIVE_IMAGE_FORMAT_1571: return disk_image_sector_per_track(DISK_IMAGE_TYPE_D71, track); case VDRIVE_IMAGE_FORMAT_8050: return disk_image_sector_per_track(DISK_IMAGE_TYPE_D80, track); case VDRIVE_IMAGE_FORMAT_1581: return 40; case VDRIVE_IMAGE_FORMAT_8250: if (track <= NUM_TRACKS_8250 / 2) { return disk_image_sector_per_track(DISK_IMAGE_TYPE_D80, track); } else { return disk_image_sector_per_track(DISK_IMAGE_TYPE_D80, track - (NUM_TRACKS_8250 / 2)); } default: log_message(vdrive_log, "Unknown disk type %i. Cannot calculate max sectors", type); } return -1; }
int vdrive_get_max_sectors(unsigned int type, unsigned int track) { switch (type) { case VDRIVE_IMAGE_FORMAT_1541: return disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, track); case VDRIVE_IMAGE_FORMAT_2040: return disk_image_sector_per_track(DISK_IMAGE_TYPE_D67, track); case VDRIVE_IMAGE_FORMAT_1571: return disk_image_sector_per_track(DISK_IMAGE_TYPE_D71, track); case VDRIVE_IMAGE_FORMAT_8050: return disk_image_sector_per_track(DISK_IMAGE_TYPE_D80, track); case VDRIVE_IMAGE_FORMAT_1581: return 40; case VDRIVE_IMAGE_FORMAT_8250: if (track <= NUM_TRACKS_8250 / 2) return disk_image_sector_per_track(DISK_IMAGE_TYPE_D80, track); else return disk_image_sector_per_track(DISK_IMAGE_TYPE_D80, track - (NUM_TRACKS_8250 / 2)); default: #ifdef CELL_DEBUG printf("ERROR: Unknown disk type %i. Cannot calculate max sectors\n", type); #endif break; } return -1; }
static void drive_extend_disk_image(drive_t *drive) { int rc; unsigned int track, sector; BYTE buffer[256]; drive->image->tracks = EXT_TRACKS_1541; memset(buffer, 0, 256); for (track = NUM_TRACKS_1541 + 1; track <= EXT_TRACKS_1541; track++) { for (sector = 0; sector < disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, track); sector++) { rc = disk_image_write_sector(drive->image, buffer, track, sector); if (rc < 0) log_error(drive->log, "Could not update T:%d S:%d.", track, sector); } } }
static void drive_extend_disk_image(drive_t *drive) { int rc; unsigned int track, sector; BYTE buffer[256]; drive->image->tracks = EXT_TRACKS_1541; memset(buffer, 0, 256); for (track = NUM_TRACKS_1541 + 1; track <= EXT_TRACKS_1541; track++) { for (sector = 0; sector < disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, track); sector++) { rc = disk_image_write_sector(drive->image, buffer, track, sector); #ifdef CELL_DEBUG if (rc < 0) printf("ERROR: Could not update T:%d S:%d.\n", track, sector); #endif } } }
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_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; }
static int fsimage_create_gcr(disk_image_t *image) { BYTE gcr_header[12], gcr_track[7930], *gcrptr; DWORD gcr_track_p[MAX_TRACKS_1541 * 2]; DWORD gcr_speed_p[MAX_TRACKS_1541 * 2]; unsigned int track, sector; fsimage_t *fsimage; fsimage = image->media.fsimage; strcpy((char *)gcr_header, "GCR-1541"); gcr_header[8] = 0; gcr_header[9] = MAX_TRACKS_1541 * 2; gcr_header[10] = 7928 % 256; gcr_header[11] = 7928 / 256; if (fwrite((char *)gcr_header, sizeof(gcr_header), 1, fsimage->fd) < 1) { log_error(createdisk_log, "Cannot write GCR header."); return -1; } for (track = 0; track < MAX_TRACKS_1541; track++) { gcr_track_p[track * 2] = 12 + MAX_TRACKS_1541 * 16 + track * 7930; gcr_track_p[track * 2 + 1] = 0; gcr_speed_p[track * 2] = disk_image_speed_map_1541(track); gcr_speed_p[track * 2 + 1] = 0; } if (util_dword_write(fsimage->fd, gcr_track_p, util_arraysize(gcr_track_p)) < 0) { log_error(createdisk_log, "Cannot write track header."); return -1; } if (util_dword_write(fsimage->fd, gcr_speed_p, util_arraysize(gcr_speed_p)) < 0) { log_error(createdisk_log, "Cannot write speed header."); return -1; } for (track = 0; track < MAX_TRACKS_1541; track++) { const int raw_track_size[4] = { 6250, 6666, 7142, 7692 }; memset(&gcr_track[2], 0x55, 7928); gcr_track[0] = raw_track_size[disk_image_speed_map_1541(track)] % 256; gcr_track[1] = raw_track_size[disk_image_speed_map_1541(track)] / 256; gcrptr = &gcr_track[2]; for (sector = 0; sector < disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, track + 1); sector++) { BYTE chksum, id[2], rawdata[260]; int i; id[0] = id[1] = 0xa0; memset(rawdata, 0, 260); rawdata[0] = 7; chksum = rawdata[1]; for (i = 1; i < 256; i++) chksum ^= rawdata[i + 1]; rawdata[257] = chksum; gcr_convert_sector_to_GCR(rawdata, gcrptr, track + 1, sector, id[0], id[1], 0); gcrptr += 360; } if (fwrite((char *)gcr_track, sizeof(gcr_track), 1, fsimage->fd) < 1 ) { log_error(createdisk_log, "Cannot write track data."); return -1; } } return 0; }
void drive_gcr_data_writeback(drive_t *drive) { int extend; unsigned int half_track, track, sector, max_sector = 0; BYTE buffer[260], *offset; if (drive->image == NULL) { return; } half_track = drive->current_half_track; track = drive->current_half_track / 2; if (drive->image->type == DISK_IMAGE_TYPE_P64) { return; } if (!(drive->GCR_dirty_track)) { return; } if (drive->image->type == DISK_IMAGE_TYPE_G64) { BYTE *gcr_track_start_ptr; unsigned int gcr_current_track_size; gcr_current_track_size = drive->gcr->track_size[half_track - 2]; gcr_track_start_ptr = drive->gcr->data + ((half_track - 2) * drive->gcr->max_track_size); disk_image_write_half_track(drive->image, half_track, gcr_current_track_size, drive->gcr->speed_zone, gcr_track_start_ptr); drive->GCR_dirty_track = 0; return; } if (drive->image->type == DISK_IMAGE_TYPE_D64 || drive->image->type == DISK_IMAGE_TYPE_X64) { if (track > EXT_TRACKS_1541) return; max_sector = disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, track); if (track > drive->image->tracks) { switch (drive->extend_image_policy) { case DRIVE_EXTEND_NEVER: drive->ask_extend_disk_image = 1; return; case DRIVE_EXTEND_ASK: if (drive->ask_extend_disk_image == 1) { extend = ui_extend_image_dialog(); if (extend == 0) { drive->ask_extend_disk_image = 0; return; } else { drive_extend_disk_image(drive); } } else { return; } break; case DRIVE_EXTEND_ACCESS: drive->ask_extend_disk_image = 1; drive_extend_disk_image(drive); break; } } } if (drive->image->type == DISK_IMAGE_TYPE_D71) { if (track > MAX_TRACKS_1571) return; max_sector = disk_image_sector_per_track(DISK_IMAGE_TYPE_D71, track); } drive->GCR_dirty_track = 0; for (sector = 0; sector < max_sector; sector++) { offset = gcr_find_sector_header(track, sector, drive->GCR_track_start_ptr, drive->GCR_current_track_size); if (offset == NULL) { log_error(drive->log, "Could not find header of T:%d S:%d.", track, sector); } else { offset = gcr_find_sector_data(offset, drive->GCR_track_start_ptr, drive->GCR_current_track_size); if (offset == NULL) { log_error(drive->log, "Could not find data sync of T:%d S:%d.", track, sector); } else { gcr_data_writeback2(buffer, offset, track, sector, drive); } } } }
static void drive_image_read_d64_d71(drive_t *drive) { BYTE buffer[260], chksum; int i; unsigned int track, sector; if (!(drive->image)) return; buffer[258] = buffer[259] = 0; /* Since the D64/D71 format does not provide the actual track sizes or speed zones, we set them to standard values. */ if ((drive->image->type == DISK_IMAGE_TYPE_D64 || drive->image->type == DISK_IMAGE_TYPE_D67 || drive->image->type == DISK_IMAGE_TYPE_X64) && (drive->type == DRIVE_TYPE_1541 || drive->type == DRIVE_TYPE_1541II || drive->type == DRIVE_TYPE_1551 || drive->type == DRIVE_TYPE_1570 || drive->type == DRIVE_TYPE_2031)) { drive_image_init_track_size_d64(drive); } if (drive->image->type == DISK_IMAGE_TYPE_D71 || drive->type == DRIVE_TYPE_1571 || drive->type == DRIVE_TYPE_1571CR || drive->type == DRIVE_TYPE_2031) { drive_image_init_track_size_d71(drive); } drive_set_half_track(drive->current_half_track, drive); for (track = 1; track <= drive->image->tracks; track++) { BYTE *ptr; unsigned int max_sector = 0; ptr = drive->gcr->data + GCR_OFFSET(track); max_sector = disk_image_sector_per_track(drive->image->type, track); /* Clear track to avoid read errors. */ memset(ptr, 0x55, NUM_MAX_BYTES_TRACK); for (sector = 0; sector < max_sector; sector++) { int rc; ptr = drive->gcr->data + sector_offset(track, sector, max_sector, drive); rc = disk_image_read_sector(drive->image, buffer + 1, track, sector); #ifdef CELL_DEBUG if (rc < 0) { printf("ERROR: Cannot read T:%d S:%d from disk image.\n", track, sector); continue; } #endif if (rc == 21) { ptr = drive->gcr->data + GCR_OFFSET(track); memset(ptr, 0x00, NUM_MAX_BYTES_TRACK); break; } buffer[0] = (rc == 22) ? 0xff : 0x07; chksum = buffer[1]; for (i = 2; i < 257; i++) chksum ^= buffer[i]; buffer[257] = (rc == 23) ? chksum ^ 0xff : chksum; gcr_convert_sector_to_GCR(buffer, ptr, track, sector, drive->diskID1, drive->diskID2, (BYTE)(rc)); } } }
int fsimage_check_sector(disk_image_t *image, unsigned int track, unsigned int sector) { unsigned int sectors = 0, i; if (track < 1) return -1; switch (image->type) { case DISK_IMAGE_TYPE_D64: case DISK_IMAGE_TYPE_X64: if (track > MAX_TRACKS_1541 || sector >= disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, track)) return -1; for (i = 1; i < track; i++) sectors += disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, i); sectors += sector; break; case DISK_IMAGE_TYPE_D67: if (track > MAX_TRACKS_2040 || sector >= disk_image_sector_per_track(DISK_IMAGE_TYPE_D67, track)) return -1; for (i = 1; i < track; i++) sectors += disk_image_sector_per_track(DISK_IMAGE_TYPE_D67, i); sectors += sector; break; case DISK_IMAGE_TYPE_D71: if (track > MAX_TRACKS_1571) return -1; if (track > NUM_TRACKS_1541) { /* The second side */ track -= NUM_TRACKS_1541; sectors = NUM_BLOCKS_1541; } if (sector >= disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, track)) return -1; for (i = 1; i < track; i++) sectors += disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, i); sectors += sector; break; case DISK_IMAGE_TYPE_D81: if (track > MAX_TRACKS_1581 || sector >= NUM_SECTORS_1581) return -1; sectors = (track - 1) * NUM_SECTORS_1581 + sector; break; case DISK_IMAGE_TYPE_D80: if (track > MAX_TRACKS_8050 || sector >= disk_image_sector_per_track(DISK_IMAGE_TYPE_D80, track)) return -1; for (i = 1; i < track; i++) sectors += disk_image_sector_per_track(DISK_IMAGE_TYPE_D80, i); sectors += sector; break; case DISK_IMAGE_TYPE_D82: if (track > MAX_TRACKS_8250) return -1; if (track > NUM_TRACKS_8050) { /* The second side */ track -= NUM_TRACKS_8050; sectors = NUM_BLOCKS_8050; } if (sector >= disk_image_sector_per_track(DISK_IMAGE_TYPE_D80, track)) return -1; for (i = 1; i < track; i++) sectors += disk_image_sector_per_track(DISK_IMAGE_TYPE_D80, i); sectors += sector; break; case DISK_IMAGE_TYPE_G64: case DISK_IMAGE_TYPE_P64: if (track > image->tracks || track > MAX_TRACKS_1541 || sector >= disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, track)) return -1; for (i = 1; i < track; i++) sectors += disk_image_sector_per_track(DISK_IMAGE_TYPE_D64, i); sectors += sector; break; case DISK_IMAGE_TYPE_D1M: if (track > NUM_TRACKS_1000 || sector > 255 || (track == NUM_TRACKS_1000 && sector >= NUM_SYS_SECTORS_1000)) return -1; sectors = (track - 1) * 256 + sector; break; case DISK_IMAGE_TYPE_D2M: if (track > NUM_TRACKS_2000 || sector > 255 || (track == NUM_TRACKS_2000 && sector >= NUM_SYS_SECTORS_2000)) return -1; sectors = (track - 1) * 256 + sector; break; case DISK_IMAGE_TYPE_D4M: if (track > NUM_TRACKS_4000 || sector > 255 || (track == NUM_TRACKS_4000 && sector >= NUM_SYS_SECTORS_4000)) return -1; sectors = (track - 1) * 256 + sector; break; default: return -1; } return (int)(sectors); }