Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}