11 #include "d64copy_int.h"
19 static const char d64_sector_map[MAX_TRACKS+1] =
21 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
22 21, 21, 21, 21, 21, 21, 21, 19, 19, 19,
23 19, 19, 19, 19, 18, 18, 18, 18, 18, 18,
25 17, 17, 17, 17, 17, 17, 17
28 static const char d71_sector_map[D71_TRACKS+1] =
30 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
31 21, 21, 21, 21, 21, 21, 21, 19, 19, 19,
32 19, 19, 19, 19, 18, 18, 18, 18, 18, 18,
34 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
35 21, 21, 21, 21, 21, 21, 21, 19, 19, 19,
36 19, 19, 19, 19, 18, 18, 18, 18, 18, 18,
40 static const unsigned char warp_read_1541[] =
42 #include "warpread1541.inc"
45 static const unsigned char warp_write_1541[] =
47 #include "warpwrite1541.inc"
50 static const unsigned char warp_read_1571[] =
52 #include "warpread1571.inc"
55 static const unsigned char warp_write_1571[] =
57 #include "warpwrite1571.inc"
60 static const unsigned char turbo_read_1541[] =
62 #include "turboread1541.inc"
65 static const unsigned char turbo_write_1541[] =
67 #include "turbowrite1541.inc"
70 static const unsigned char turbo_read_1571[] =
72 #include "turboread1571.inc"
75 static const unsigned char turbo_write_1571[] =
77 #include "turbowrite1571.inc"
80 static const struct drive_prog
83 const unsigned char *
prog;
86 {
sizeof(turbo_read_1541), turbo_read_1541},
87 {
sizeof(turbo_write_1541), turbo_write_1541},
88 {
sizeof(warp_read_1541), warp_read_1541},
89 {
sizeof(warp_write_1541), warp_write_1541},
90 {
sizeof(turbo_read_1571), turbo_read_1571},
91 {
sizeof(turbo_write_1571), turbo_write_1571},
92 {
sizeof(warp_read_1571), warp_read_1571},
93 {
sizeof(warp_write_1571), warp_write_1571}
97 static const int default_interleave[] = { -1, 17, 4, 13, 7, -1 };
98 static const int warp_write_interleave[] = { -1, 0, 6, 12, 4, -1 };
104 static int atom_mustcleanup = 0;
108 #ifdef LIBD64COPY_DEBUG
109 volatile signed int DebugLineNumber=-1, DebugBlockCount=-1,
110 DebugByteCount=-1, DebugBitCount=-1;
111 volatile char * DebugFileName =
"";
113 void printDebugLibD64Counters(d64copy_message_cb msg_cb)
115 msg_cb( sev_info,
"file: %s"
116 "\n\tversion: " OPENCBM_VERSION
", built: " __DATE__
" " __TIME__
117 "\n\tline=%d, blocks=%d, bytes=%d, bits=%d\n",
118 DebugFileName, DebugLineNumber,
119 DebugBlockCount, DebugByteCount,
124 static int send_turbo(
CBM_FILE fd,
unsigned char drv,
int write,
int warp,
int drv_type)
126 const struct drive_prog *
prog;
128 prog = &drive_progs[drv_type * 4 + warp * 2 + write];
130 SETSTATEDEBUG((
void)0);
131 return cbm_upload(fd, drv, 0x500, prog->prog, prog->size);
135 d64copy_std_transfer,
140 static d64copy_message_cb message_cb;
141 static d64copy_status_cb status_cb;
143 int d64copy_sector_count(
int two_sided,
int track)
147 if(track >= 1 && track <= D71_TRACKS)
149 return d71_sector_map[track];
154 if(track >= 1 && track <= TOT_TRACKS)
156 return d64_sector_map[track];
171 settings->retries = 0;
172 settings->bam_mode = bm_ignore;
173 settings->interleave = -1;
174 settings->start_track = 1;
175 settings->end_track = -1;
177 settings->two_sided = 0;
178 settings->error_mode = em_on_error;
184 static int start_turbo(
CBM_FILE fd,
unsigned char drive)
186 SETSTATEDEBUG((
void)0);
193 const transfer_funcs *dst,
const void *dst_arg,
unsigned char cbm_drive)
195 unsigned char tr = 0;
196 unsigned char se = 0;
199 unsigned char scnt = 0;
200 unsigned char errors;
204 char trackmap[MAX_SECTORS+1];
206 unsigned const char *bam_ptr;
207 unsigned char bam[BLOCKSIZE];
208 unsigned char bam2[BLOCKSIZE];
209 unsigned char block[BLOCKSIZE];
210 unsigned char gcr[GCRBUFSIZE];
213 const char *sector_map;
214 const char *type_str =
"*unknown*";
216 if(settings->two_sided)
218 max_tracks = D71_TRACKS;
222 max_tracks = TOT_TRACKS;
225 if(settings->interleave != -1 &&
226 (settings->interleave < 1 || settings->interleave > 17))
229 "invalid value (%d) for interleave", settings->interleave);
233 if(settings->start_track < 1 || settings->start_track > max_tracks)
236 "invalid value (%d) for start track", settings->start_track);
240 if(settings->end_track != -1 &&
241 (settings->end_track < settings->start_track ||
242 settings->end_track > max_tracks))
245 "invalid value (%d) for end track", settings->end_track);
249 if(settings->interleave == -1)
251 settings->interleave = (dst->is_cbm_drive && settings->warp) ?
252 warp_write_interleave[settings->transfer_mode] :
253 default_interleave[settings->transfer_mode];
255 assert(settings->interleave >= 0);
261 message_cb( 2,
"Trying to identify drive type" );
262 if(
cbm_identify( fd_cbm, cbm_drive, &settings->drive_type, NULL ) )
264 message_cb( 0,
"could not identify device" );
267 switch( settings->drive_type )
275 message_cb( 0,
"1581 drives are not supported" );
278 message_cb( 1,
"Unknown drive, assuming 1541" );
284 sector_map = settings->two_sided ? d71_sector_map : d64_sector_map;
286 SETSTATEDEBUG((
void)0);
288 SETSTATEDEBUG((
void)0);
290 SETSTATEDEBUG((
void)0);
292 switch( settings->drive_type )
300 message_cb(cnt != 0 ? 0 : 2,
"drive %02d (%s): %s",
301 cbm_drive, type_str, buf );
308 if(settings->two_sided)
312 message_cb(0,
".d71 transfer requires a 1571 drive");
318 message_cb(1,
"`-w' for .d71 transfer in warp mode ignored");
321 SETSTATEDEBUG((
void)0);
325 SETSTATEDEBUG((
void)0);
326 cbm_transf = src->is_cbm_drive ? src : dst;
328 if(settings->warp && (cbm_transf->read_gcr_block == NULL))
331 message_cb(1,
"`-w' for this transfer mode ignored");
335 settings->warp = settings->warp ? 1 : 0;
337 if(cbm_transf->needs_turbo)
339 SETSTATEDEBUG((
void)0);
340 send_turbo(fd_cbm, cbm_drive, dst->is_cbm_drive, settings->warp,
344 SETSTATEDEBUG((
void)0);
345 if(src->open_disk(fd_cbm, settings, src_arg, 0,
346 start_turbo, message_cb) == 0)
348 if(settings->end_track == -1)
350 settings->end_track =
351 settings->two_sided ? D71_TRACKS : STD_TRACKS;
353 SETSTATEDEBUG((
void)0);
354 if(dst->open_disk(fd_cbm, settings, dst_arg, 1,
355 start_turbo, message_cb) != 0)
357 message_cb(0,
"can't open destination");
363 message_cb(0,
"can't open source");
367 memset(status.bam, bs_invalid, MAX_TRACKS * MAX_SECTORS);
369 if(settings->bam_mode != bm_ignore)
371 if(settings->warp && src->is_cbm_drive)
373 memset(trackmap, bs_dont_copy, sector_map[18]);
374 trackmap[0] = bs_must_copy;
376 SETSTATEDEBUG((
void)0);
377 src->send_track_map(18, trackmap, scnt);
378 SETSTATEDEBUG(DebugBlockCount=0);
379 st = src->read_gcr_block(&se, gcr);
380 SETSTATEDEBUG(DebugBlockCount=-1);
381 if(st == 0) st = gcr_decode(gcr, bam);
385 SETSTATEDEBUG(DebugBlockCount=0);
386 st = src->read_block(18, 0, bam);
387 if(settings->two_sided && (st == 0))
389 SETSTATEDEBUG(DebugBlockCount=1);
390 st = src->read_block(53, 0, bam2);
392 SETSTATEDEBUG(DebugBlockCount=-1);
396 message_cb(1,
"failed to read BAM (%d)", st);
397 settings->bam_mode = bm_ignore;
400 SETSTATEDEBUG((
void)0);
402 memset(&status, 0,
sizeof(status));
405 for(tr = 1; tr <= max_tracks; tr++)
407 if(tr < settings->start_track || tr > settings->end_track)
409 memset(status.bam[tr-1], bs_dont_copy, sector_map[tr]);
411 else if(settings->bam_mode == bm_allocated ||
412 (settings->bam_mode == bm_save && (tr % 35 != 18)))
414 for(se = 0; se < sector_map[tr]; se++)
416 if(settings->two_sided && tr > STD_TRACKS)
418 bam_ptr = &bam2[3*(tr - STD_TRACKS - 1)];
422 bam_ptr = &bam[4*tr + 1 + (tr > STD_TRACKS ? 48 : 0)];
424 if(bam_ptr[se/8]&(1<<(se&0x07)))
426 status.bam[tr-1][se] = bs_dont_copy;
430 status.bam[tr-1][se] = bs_must_copy;
431 status.total_sectors++;
437 status.total_sectors += sector_map[tr];
438 memset(status.bam[tr-1], bs_must_copy, sector_map[tr]);
442 status.settings = settings;
446 message_cb(2,
"copying tracks %d-%d (%d sectors)",
447 settings->start_track, settings->end_track, status.total_sectors);
449 SETSTATEDEBUG(DebugBlockCount=0);
450 for(tr = 1; tr <= max_tracks; tr++)
452 if(tr >= settings->start_track && tr <= settings->end_track)
454 scnt = sector_map[tr];
455 memcpy(trackmap, status.bam[tr-1], scnt);
456 if(settings->bam_mode != bm_ignore)
458 for(se = 0; se < sector_map[tr]; se++)
460 if(trackmap[se] != bs_must_copy)
467 retry_count = settings->retries;
470 errors = resend_trackmap = 0;
471 if(scnt && settings->warp && src->is_cbm_drive)
473 SETSTATEDEBUG((
void)0);
474 src->send_track_map(tr, trackmap, scnt);
480 while(scnt && !resend_trackmap)
482 if(settings->warp && src->is_cbm_drive)
484 SETSTATEDEBUG((
void)0);
485 status.read_result = src->read_gcr_block(&se, gcr);
486 if(status.read_result == 0)
488 SETSTATEDEBUG((
void)0);
489 status.read_result = gcr_decode(gcr, block);
496 for(scnt = 0; scnt < sector_map[tr]; scnt++)
498 if(NEED_SECTOR(trackmap[scnt]) && scnt != se)
500 trackmap[scnt] = bs_error;
509 while(!NEED_SECTOR(trackmap[se]))
511 if(++se >= sector_map[tr]) se = 0;
513 SETSTATEDEBUG(DebugBlockCount++);
514 status.read_result = src->read_block(tr, se, block);
517 if(settings->warp && dst->is_cbm_drive)
519 SETSTATEDEBUG((
void)0);
520 gcr_encode(block, gcr);
521 SETSTATEDEBUG(DebugBlockCount++);
522 status.write_result =
523 dst->write_block(tr, se, gcr, GCRBUFSIZE-1,
528 SETSTATEDEBUG(DebugBlockCount++);
529 status.write_result =
530 dst->write_block(tr, se, block, BLOCKSIZE,
533 SETSTATEDEBUG((
void)0);
535 if(status.read_result)
538 trackmap[se] = bs_error;
542 status.sectors_processed++;
544 message_cb( 1,
"read error: %02x/%02x: %d",
545 tr, se, status.read_result );
551 if(status.write_result)
554 trackmap[se] = bs_error;
558 status.sectors_processed++;
560 message_cb(1,
"write error: %02x/%02x: %d",
561 tr, se, status.write_result);
567 trackmap[se] = bs_copied;
569 status.sectors_processed++;
583 if(dst->is_cbm_drive || !settings->warp)
585 se += (
unsigned char) settings->interleave;
586 if(se >= sector_map[tr]) se -= sector_map[tr];
589 if(errors > 0 && settings->retries >= 0)
595 while(retry_count >= 0 && errors > 0);
598 message_cb(1,
"giving up...");
601 if(settings->two_sided)
605 if(tr + STD_TRACKS <= D71_TRACKS)
607 tr += (STD_TRACKS - 1);
610 else if(tr != D71_TRACKS)
616 SETSTATEDEBUG(DebugBlockCount=-1);
619 SETSTATEDEBUG((
void)0);
622 SETSTATEDEBUG((
void)0);
627 static struct _transfers
630 const char *name, *abbrev;
634 { &d64copy_std_transfer,
"auto",
"a%" },
635 { &d64copy_std_transfer,
"original",
"o%" },
636 { &d64copy_s1_transfer,
"serial1",
"s1" },
637 { &d64copy_s2_transfer,
"serial2",
"s2" },
638 { &d64copy_pp_transfer,
"parallel",
"p%" },
642 char *d64copy_get_transfer_modes()
644 const struct _transfers *t;
650 for(t = transfers; t->trf; t++)
652 size += (strlen(t->name) + 1);
660 for(t = transfers; t->trf; t++)
662 strcpy(dst, t->name);
663 dst += (strlen(t->name) + 1);
672 int d64copy_get_transfer_mode_index(
const char *name)
674 const struct _transfers *t;
685 tm_len = strlen(name);
686 for(i = 0, t = transfers; t->trf; i++, t++)
688 if(arch_strcasecmp(name, t->name) == 0)
693 if(t->abbrev[strlen(t->abbrev)-1] ==
'%')
695 abbrev_len = strlen(t->abbrev) - 1;
696 if(abbrev_len <= tm_len && arch_strncasecmp(t->name, name, tm_len) == 0)
703 if(strcmp(name, t->abbrev) == 0)
712 int d64copy_check_auto_transfer_mode(
CBM_FILE cbm_fd,
int auto_transfermode,
int drive)
714 int transfermode = auto_transfermode;
717 assert(strcmp(transfers[0].name,
"auto") == 0);
719 if (auto_transfermode == 0)
723 unsigned char testdrive;
729 SETSTATEDEBUG((
void)0);
737 SETSTATEDEBUG((
void)0);
738 transfermode = d64copy_get_transfer_mode_index(
"parallel");
748 for (testdrive = 4; testdrive < 31; ++testdrive)
753 if (testdrive == drive)
756 SETSTATEDEBUG((
void)0);
757 if (
cbm_identify(cbm_fd, testdrive, &device_type, NULL) == 0)
762 SETSTATEDEBUG((
void)0);
763 transfermode = d64copy_get_transfer_mode_index(
"serial1");
772 SETSTATEDEBUG((
void)0);
773 if (transfermode == 0)
774 transfermode = d64copy_get_transfer_mode_index(
"serial2");
775 SETSTATEDEBUG((
void)0);
780 SETSTATEDEBUG((
void)0);
784 int d64copy_read_image(
CBM_FILE cbm_fd,
787 const char *dst_image,
788 d64copy_message_cb msg_cb,
789 d64copy_status_cb stat_cb)
798 src = transfers[settings->transfer_mode].trf;
799 dst = &d64copy_fs_transfer;
802 atom_mustcleanup = 1;
804 SETSTATEDEBUG((
void)0);
805 ret = copy_disk(cbm_fd, settings,
806 src, (
void*)(ULONG_PTR)src_drive, dst, (
void*)dst_image, (
unsigned char) src_drive);
808 atom_mustcleanup = 0;
813 int d64copy_write_image(
CBM_FILE cbm_fd,
815 const char *src_image,
817 d64copy_message_cb msg_cb,
818 d64copy_status_cb stat_cb)
826 src = &d64copy_fs_transfer;
827 dst = transfers[settings->transfer_mode].trf;
829 SETSTATEDEBUG((
void)0);
830 return copy_disk(cbm_fd, settings,
831 src, (
void*)src_image, dst, (
void*)(ULONG_PTR)dst_drive, (
unsigned char) dst_drive);
834 void d64copy_cleanup(
void)
840 if (atom_mustcleanup)
842 atom_dst->close_disk();
843 atom_mustcleanup = 0;
int CBMAPIDECL cbm_identify_xp1541(CBM_FILE HandleDevice, unsigned char DeviceAddress, enum cbm_device_type_e *CbmDeviceType, enum cbm_cable_type_e *CableType)
Identify the cable connected to a specific floppy drive.
int CBMAPIDECL cbm_device_status(CBM_FILE HandleDevice, unsigned char DeviceAddress, void *Buffer, size_t BufferLength)
Read the drive status from a floppy.
int CBMAPIDECL cbm_exec_command(CBM_FILE HandleDevice, unsigned char DeviceAddress, const void *Command, size_t Size)
Executes a command in the floppy drive.
int CBMAPIDECL cbm_identify(CBM_FILE HandleDevice, unsigned char DeviceAddress, enum cbm_device_type_e *CbmDeviceType, const char **CbmDeviceString)
Identify the connected floppy drive.
Define makros and functions which account for differences between the different architectures.
int CBMAPIDECL cbm_upload(CBM_FILE HandleDevice, unsigned char DeviceAddress, int DriveMemAddress, const void *Program, size_t Size)
Upload a program into a floppy's drive memory.