static int send_track_map(unsigned char tr, const char *trackmap, unsigned char count) { int i; unsigned char c; pp_write(fd_cbm, tr, count); for(i = 0; i < d64copy_sector_count(two_sided, tr); i++) { c = !NEED_SECTOR(trackmap[i]); pp_write(fd_cbm, c, c); } return 0; }
static int send_track_map(imgcopy_settings *settings, unsigned char tr, const char *trackmap, unsigned char count) { int i, size; unsigned char *data; size = imgcopy_sector_count(settings, tr); data = malloc(2+2*size); data[0] = tr; data[1] = count; /* build track map */ for(i = 0; i < size; i++) data[2+2*i] = data[2+2*i+1] = !NEED_SECTOR(trackmap[i]); write_n(data, 2*size+2); free(data); SETSTATEDEBUG((void)0); return 0; }
static int copy_disk(CBM_FILE fd_cbm, imgcopy_settings *settings, const transfer_funcs *src, const void *src_arg, const transfer_funcs *dst, const void *dst_arg, unsigned char cbm_drive) { unsigned char tr = 0; unsigned char se = 0; int st; int cnt = 0; unsigned char scnt = 0; unsigned char errors; int retry_count; int resend_trackmap; char trackmap[MAX_SECTORS+1]; char buf[40]; //unsigned const char *bam_ptr; unsigned char bam[BLOCKSIZE *5]; int bam_count; unsigned char block[BLOCKSIZE]; //unsigned char gcr[GCRBUFSIZE]; const transfer_funcs *cbm_transf = NULL; imgcopy_status status; const char *type_str = "*unknown*"; if(settings->drive_type == cbm_dt_unknown ) { message_cb( 2, "Trying to identify drive type" ); if( cbm_identify( fd_cbm, cbm_drive, &settings->drive_type, NULL ) ) { message_cb( 0, "could not identify device" ); } switch( settings->drive_type ) { case cbm_dt_cbm1541: case cbm_dt_cbm1570: case cbm_dt_cbm1571: case cbm_dt_cbm4040: message_cb( 0, "drive is not supported" ); return -1; case cbm_dt_cbm1581: case cbm_dt_cbm8050: case cbm_dt_cbm8250: case cbm_dt_sfd1001: /* fine */ break; default: message_cb( 1, "Unknown drive, assuming 8250" ); settings->drive_type = cbm_dt_cbm8250; break; } } if(settings->two_sided == -1) { // set default switch( settings->drive_type ) { case cbm_dt_cbm8250: case cbm_dt_sfd1001: settings->two_sided = 1; break; case cbm_dt_cbm8050: case cbm_dt_cbm1581: default: settings->two_sided = 0; break; } } if(imgcopy_set_image_type(settings, NULL)) { message_cb(0, "invalid imagetype for this drive type"); return -1; } if(imgcopy_sector_count(settings, 1) < 0) { message_cb(0, "invalid drive or image type"); return -1; } if(settings->interleave != -1 && (settings->interleave < 1 || settings->interleave > 24)) { message_cb(0, "invalid value (%d) for interleave", settings->interleave); return -1; } if(settings->start_track < 1 || settings->start_track > settings->max_tracks) { message_cb(0, "invalid value (%d) for start track. (MAXTRACKS=%d)", settings->start_track, settings->max_tracks); return -1; } if(settings->end_track != -1 && (settings->end_track < settings->start_track || settings->end_track > settings->max_tracks)) { message_cb(0, "invalid value (%d) for end track. (MAXTRACKS=%d)", settings->end_track, settings->max_tracks); return -1; } if(settings->interleave == -1) { switch( settings->drive_type ) { case cbm_dt_cbm1581: settings->interleave = 1; // always 1 cause track buffering break; case cbm_dt_cbm8050: case cbm_dt_cbm8250: case cbm_dt_sfd1001: default: settings->interleave = (dst->is_cbm_drive && settings->warp) ? warp_write_interleave[settings->transfer_mode] : default_interleave[settings->transfer_mode]; break; } assert(settings->interleave >= 0); } SETSTATEDEBUG((void)0); cbm_exec_command(fd_cbm, cbm_drive, "I0:", 0); SETSTATEDEBUG((void)0); cnt = cbm_device_status(fd_cbm, cbm_drive, buf, sizeof(buf)); SETSTATEDEBUG((void)0); switch( settings->drive_type ) { case cbm_dt_cbm8050: type_str = "CBM-8050"; break; case cbm_dt_cbm8250: type_str = "CBM-8250"; break; case cbm_dt_sfd1001: type_str = "SFD-1001"; break; case cbm_dt_cbm1581: type_str = "CBM-1581"; break; default: type_str = "unknown"; break; } if(cnt == 66) { // illegal track or sector :: DOS error if(settings->image_type == D80) cnt = 0; else { if(settings->image_type == D82) { //settings->image_type = D80; //imgcopy_set_image_type(settings, NULL); message_cb(1, "maybe a 8050 disk in a 8250 drive"); cnt = 0; } } } if(cnt) { // DOS error message_cb(0, "drive %02d (%s): %s", cbm_drive, type_str, buf ); return -1; } message_cb(2, "drive %02d (%s)", cbm_drive, type_str); if(settings->two_sided) { switch( settings->drive_type ) { case cbm_dt_cbm8250: case cbm_dt_sfd1001: // ok break; default: message_cb(0, "requires a two side drive"); return -1; } SETSTATEDEBUG((void)0); } switch( settings->drive_type ) { case cbm_dt_cbm1541: case cbm_dt_cbm1571: if(settings->warp && (cbm_transf->read_gcr_block == NULL)) { if(settings->warp>0) message_cb(1, "`-w' for this transfer mode ignored"); settings->warp = 0; } break; case cbm_dt_cbm1581: case cbm_dt_cbm8050: case cbm_dt_cbm8250: case cbm_dt_sfd1001: default: if(settings->warp) { if(settings->warp>0) message_cb(1, "drive type doesn't support warp mode"); settings->warp = 0; } break; } // // Check if transfer mode is allowed // if(imgcopy_check_transfer_mode(settings)) { message_cb(0, "transfer mode not allowed for this drive type"); return -1; } message_cb(2, "set transfer struc."); SETSTATEDEBUG((void)0); cbm_transf = src->is_cbm_drive ? src : dst; settings->warp = settings->warp ? 1 : 0; if(cbm_transf->needs_turbo) { int rc; message_cb(2, "sending turbo drive code ..."); SETSTATEDEBUG((void)0); // send_turbo(fd_cbm, cbm_drive, dst->is_cbm_drive, settings->warp, settings->drive_type == cbm_dt_cbm1541 ? 0 : 1); if((rc=send_turbo(settings, fd_cbm, cbm_drive, dst->is_cbm_drive)) != 0) { message_cb(0, "error while upload of drive code (rc=%d)", rc); return -1; } } SETSTATEDEBUG((void)0); message_cb(2, "open source disk."); if(src->open_disk(fd_cbm, settings, src_arg, 0, start_turbo, message_cb) == 0) { if(settings->end_track == -1) { settings->end_track = settings->max_tracks; } SETSTATEDEBUG((void)0); message_cb(2, "open destination."); if(dst->open_disk(fd_cbm, settings, dst_arg, 1, start_turbo, message_cb) != 0) { message_cb(0, "can't open destination"); return -1; } } else { message_cb(0, "can't open source"); return -1; } //message_cb(2, "set BAM buffer (%dx%d)", MAX_TRACKS, MAX_SECTORS); memset(status.bam, bs_invalid, MAX_TRACKS * MAX_SECTORS); if(settings->bam_mode != bm_ignore) { //message_cb(2, "reading BAM ..."); st = ReadBAM(settings, src, bam, &bam_count); if(st) { message_cb(1, "failed to read BAM (%d), reading whole disk", st); settings->bam_mode = bm_ignore; } } SETSTATEDEBUG((void)0); memset(&status, 0, sizeof(status)); /* setup BAM */ //message_cb(3, "setup BAM (%d tracks)", settings->max_tracks); for(tr = 1; tr <= settings->max_tracks; tr++) { int sectorCount = imgcopy_sector_count(settings, tr); //message_cb(2, "track %d, sector %d", tr, sectorCount); if(tr < settings->start_track || tr > settings->end_track) { memset(status.bam[tr-1], bs_dont_copy, sectorCount); } else if(settings->bam_mode == bm_allocated || (settings->bam_mode == bm_save && (tr != settings->cat_track && tr != settings->bam_track ))) { //message_cb(2, "offsets into BAM for track: tr=%d, se=%d", tr); /*char lbuf[100]; gets(lbuf);*/ for(se = 0; se < sectorCount; se++) { if(ChkBAM(settings, bam, tr, se)) { //printf("copy track: %d, sector: %d\n", tr, se); status.bam[tr-1][se] = bs_must_copy; status.total_sectors++; } else { //printf("don't copy track: %d, sector: %d\n", tr, se); status.bam[tr-1][se] = bs_dont_copy; } } } else { status.total_sectors += sectorCount; memset(status.bam[tr-1], bs_must_copy, sectorCount); } } status.settings = settings; status_cb(status); message_cb(2, "copying tracks %d-%d (%d sectors)", settings->start_track, settings->end_track, status.total_sectors); // // copy disk // SETSTATEDEBUG(debugLibImgBlockCount=0); for(tr = 1; tr <= settings->max_tracks; tr++) { unsigned char sectorCount = (unsigned char) imgcopy_sector_count(settings, tr); if(tr >= settings->start_track && tr <= settings->end_track) { memcpy(trackmap, status.bam[tr-1], sectorCount); retry_count = settings->retries; do { errors = resend_trackmap = 0; // calc count of blocks to copy scnt = sectorCount; if(settings->bam_mode != bm_ignore) { for(se = 0; se < sectorCount; se++) { if(trackmap[se] != bs_must_copy) { scnt--; } } } //if(tr == 77) printf("scnt=%d\n", scnt); if(scnt > 0 && settings->warp && src->is_cbm_drive) { SETSTATEDEBUG((void)0); src->send_track_map(settings, tr, trackmap, scnt); } else { se = 0; } while(scnt > 0 && !resend_trackmap) { /* if(settings->warp && src->is_cbm_drive) { SETSTATEDEBUG((void)0); status.read_result = src->read_gcr_block(&se, gcr); if(status.read_result == 0) { SETSTATEDEBUG((void)0); status.read_result = gcr_decode(gcr, block); } else { // mark all sectors not received so far // ugly errors = 0; for(scnt = 0; scnt < sector_map[tr]; scnt++) { if(NEED_SECTOR(trackmap[scnt]) && scnt != se) { trackmap[scnt] = bs_error; errors++; } } resend_trackmap = 1; } } else */ { int se_max = sectorCount; while(!NEED_SECTOR(trackmap[se])) { if(++se >= sectorCount) se = 0; if(se_max-- <= 0) break; } if(se_max-- <= 0) break; SETSTATEDEBUG(debugLibImgBlockCount++); status.read_result = src->read_block(tr, se, block); } /*if(settings->warp && dst->is_cbm_drive) { SETSTATEDEBUG((void)0); gcr_encode(block, gcr); SETSTATEDEBUG(debugLibImgBlockCount++); status.write_result = dst->write_block(tr, se, gcr, GCRBUFSIZE-1, status.read_result); } else */ { SETSTATEDEBUG(debugLibImgBlockCount++); status.write_result = dst->write_block(tr, se, block, BLOCKSIZE, status.read_result); } SETSTATEDEBUG((void)0); if(status.read_result) { /* read error */ trackmap[se] = bs_error; errors++; if(retry_count == 0) { status.sectors_processed++; /* FIXME: shall we get rid of this? */ message_cb( 1, "read error: %02x/%02x: %d", tr, se, status.read_result ); } } else { /* successfull read */ if(status.write_result) { /* write error */ trackmap[se] = bs_error; errors++; if(retry_count == 0) { status.sectors_processed++; /* FIXME: shall we get rid of this? */ message_cb(1, "write error: %02x/%02x: %d", tr, se, status.write_result); } } else { /* successfull read and write, mark sector */ trackmap[se] = bs_copied; cnt++; status.sectors_processed++; } } /* remaining sectors on this track */ if(!resend_trackmap) { scnt--; } status.track = tr; status.sector= se; status_cb(status); if(dst->is_cbm_drive || !settings->warp) { se += (unsigned char) settings->interleave; if(se >= sectorCount) se -= sectorCount; } } //if(tr == 77) printf("after while\n"); if(errors > 0) { retry_count--; scnt = errors; } } while(retry_count >= 0 && errors > 0); //if(tr == 77) printf("after do\n"); if(errors) { message_cb(1, "giving up..."); } } if(settings->two_sided) { if(tr <= D80_TRACKS) { if(tr + D80_TRACKS <= D82_TRACKS) { tr += (D80_TRACKS -1); } } else if(tr != D82_TRACKS) { tr -= D80_TRACKS; } } //message_cb(2, "track: %d, maxtrack=%d", tr, settings->max_tracks); } message_cb(2, "finished imagecopy."); SETSTATEDEBUG(debugLibImgBlockCount=-1); dst->close_disk(); SETSTATEDEBUG((void)0); src->close_disk(); SETSTATEDEBUG((void)0); return cnt; }