25 #include "inputfiles.h"
27 #ifdef LIBCBMCOPY_DEBUG
28 # define DEBUG_STATEDEBUG
30 #include "statedebug.h"
36 static cbmcopy_severity_e verbosity = sev_info;
37 static int no_progress = 0;
39 static void my_message_cb(cbmcopy_severity_e severity,
40 const char *format, ...)
44 static const char *severities[4] =
52 if(verbosity >= severity)
54 fprintf(stderr,
"[%s] ", severities[severity]);
55 va_start(args, format);
56 vfprintf(stderr, format, args);
58 fprintf(stderr,
"\n");
62 static int my_status_cb(
int blocks_written)
69 switch (blocks_written%4)
71 case 3: statstr=
"\010-";
break;
72 case 2: statstr=
"\010/";
break;
73 case 1: statstr=
"\010|";
break;
74 default: statstr=
"\010.\\";
83 static void help(
const char *
prog)
86 "Usage: %s [OPTION]... [DRIVE] [FILE]...\n"
87 "Copy files to a CBM-15[478]1 or compatible drive and vice versa\n"
90 " -r, --read transfer 15x1->PC\n"
91 " (default when started as 'cbmread')\n"
92 " -w, --write transfer PC->15x1\n"
93 " (default when started as 'cbmwrite')\n"
94 " -r and -w are mutually exclusive\n"
96 " -h, --help display this help and exit\n"
97 " -V, --version display version information and exit\n"
98 " -@, --adapter=plugin:bus tell OpenCBM which backend plugin and bus to use\n"
99 " -q, --quiet quiet output\n"
100 " -v, --verbose control verbosity (repeatedly, up to 3 times)\n"
101 " -n, --no-progress do not display progress information\n"
103 " -t, --transfer=TRANSFER set transfermode; valid modes:\n"
105 " original or o (slowest)\n"
108 " parallel (fastest)\n"
109 " (can be abbreviated, if unambiguous)\n"
110 " `serial1' should work in any case;\n"
111 " `serial2' won't work if more than one device is\n"
112 " connected to the IEC bus;\n"
113 " `parallel' needs a XP1541/XP1571 cable in addition\n"
114 " to the serial one.\n"
115 " `auto' tries to determine the best option.\n"
116 " -d, --drive-type=TYPE specify drive type, one of:\n"
117 " 1541, 1570, 1571, 1581\n"
118 " -a, --address=ADDRESS override file start address\n"
119 " -o, --output=NAME specifies target name (ASCII, even for writing).\n"
121 "Options for writing:\n"
122 " -f, --file-type specify CBM file type (D,P,S,U)\n"
123 " -R, --raw skip test for PC64 (.p00) and T64 input file\n"
127 static void hint(
char *
prog)
129 printf(
"Try `%s' --help for more information.\n", prog);
132 static void ARCH_SIGNALDECL reset(
int dummy)
141 fd_cbm_local = fd_cbm;
144 fprintf(stderr,
"\nSIGINT caught X-( Resetting IEC bus...\n");
146 DEBUG_PRINTDEBUGCOUNTERS();
159 static void char_star_opt_once(
const char **arg,
160 const char *long_name,
165 my_message_cb(sev_fatal,
"%s given more than once.", long_name);
173 int ARCH_MAINDECL
main(
int argc,
char **argv)
181 unsigned char *filedata;
191 char auto_type =
'\0';
192 char output_type =
'\0';
195 char *adapter = NULL;
198 const char *tm = NULL;
199 const char *dt = NULL;
202 const char *output_name = NULL;
203 const char *address_str = NULL;
216 struct option longopts[] =
218 {
"help" , no_argument , NULL,
'h' },
219 {
"verbose" , no_argument , NULL,
'v' },
220 {
"adapter" , required_argument, NULL,
'@' },
221 {
"quiet" , no_argument , NULL,
'q' },
222 {
"version" , no_argument , NULL,
'V' },
223 {
"no-progress" , no_argument , NULL,
'n' },
224 {
"read" , no_argument , NULL,
'r' },
225 {
"write" , no_argument , NULL,
'w' },
226 {
"transfer" , required_argument, NULL,
't' },
227 {
"drive-type" , required_argument, NULL,
'd' },
228 {
"file-type" , required_argument, NULL,
'f' },
229 {
"output" , required_argument, NULL,
'o' },
230 {
"raw" , no_argument , NULL,
'R' },
231 {
"address" , no_argument , NULL,
'a' },
232 { NULL , 0 , NULL, 0 }
235 const char shortopts[] =
"hVqvrwnt:d:f:o:Ra:@:";
237 if(NULL == (tail = strrchr(argv[0],
'/')))
245 if(strcmp(tail,
"cbmread") == 0)
249 else if(strcmp(tail,
"cbmwrite") == 0)
258 settings = cbmcopy_get_default_settings();
261 while((option = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
269 printf(
"cbmcopy %s\n", OPENCBM_VERSION);
272 if(verbosity > sev_fatal)
276 if(verbosity < sev_debug)
287 my_message_cb(sev_fatal,
"-r/-w given more than once");
295 char_star_opt_once(&tm,
"--transfer", argv);
298 char_star_opt_once(&dt,
"--drive-type", argv);
301 char_star_opt_once(&output_name,
"--output", argv);
304 output_type = (char) toupper(*optarg);
310 char_star_opt_once(&address_str,
"--address", argv);
316 my_message_cb(sev_fatal,
"--adapter/-@ given more than once.");
337 my_message_cb(sev_fatal,
338 "-r or -w must be given when started as `%s'",
345 settings->transfer_mode = cbmcopy_get_transfer_mode_index(tm);
346 if(settings->transfer_mode < 0)
348 my_message_cb(sev_fatal,
"Unknown transfer mode: %s", tm);
367 for(p = types; p->str && strcmp(dt, p->str); p++)
372 my_message_cb(sev_fatal,
"Unknown drive type: %s", dt);
375 settings->drive_type = p->type;
383 if(strchr(
"DSPU", output_type) == NULL)
385 my_message_cb(sev_fatal,
"Invalid file type : %c", output_type);
390 my_message_cb(sev_warning,
"--file-type ignored");
397 address = strtol(address_str, &tail, 0);
398 if(*tail || address < 0 || address > 0xffff)
400 my_message_cb(sev_fatal,
"--address invalid: %s", address_str);
409 my_message_cb(sev_fatal,
"%s: No drive number given", argv[0]);
414 drive = (
unsigned char) strtol(argv[optind], &tail, 0);
415 if(drive < 8 || drive > 11 || *tail)
417 my_message_cb(sev_fatal,
"invalid drive: `%s'", argv[optind]);
422 num_files = argc - optind - 1;
426 my_message_cb(sev_fatal,
"%s: No files?", argv[0]);
432 if(num_files > 1 && output_name)
434 my_message_cb(sev_fatal,
"--output requires exactly one file name");
449 settings->transfer_mode =
450 cbmcopy_check_auto_transfer_mode(fd_cbm,
451 settings->transfer_mode,
456 while(++optind < argc)
458 fname = argv[optind];
463 file = fopen(fname,
"rb");
470 for(i = 1; readers[i] && !num_entries; i++)
473 readers[i]->probe( file, fname, my_message_cb );
478 if(!num_entries) num_entries = 1;
480 for(i = 0; i < num_entries; i++)
482 my_message_cb( sev_debug,
483 "processing entry %d from %s",
485 if(rd->read(file, fname, i,
486 auto_name, &auto_type,
487 &filedata, &filesize, my_message_cb ) == 0)
492 strncpy(buf, output_name, 16);
498 strncpy(buf, auto_name, 16);
502 output_type ? output_type : auto_type;
505 my_message_cb( sev_info,
506 "writing %s -> %s", fname, buf );
508 if(address >= 0 && filesize > 1)
510 filedata[0] = address % 0x100;
511 filedata[1] = address / 0x100;
513 my_message_cb( sev_debug,
514 "override address: $%02x%02x",
515 filedata[1], filedata[0] );
518 if(cbmcopy_write_file(fd, settings, drive,
527 my_message_cb( rv ? sev_warning : sev_info,
540 my_message_cb( sev_warning,
541 "error processing entry %d from %s",
548 my_message_cb( sev_warning,
549 "warning could not read %s: %s",
550 fname, arch_strerror(arch_get_errno()) );
555 strncpy(buf, fname, 16);
561 fs_name = arch_strdup(output_name);
565 tail = strrchr(fname,
',');
574 case 'd': ext =
"del";
break;
575 case 's': ext =
"seq";
break;
576 case 'u': ext =
"usr";
break;
579 fs_name = malloc(strlen(fname) + strlen(ext) + 2);
580 if(fs_name) sprintf(fs_name,
"%s.%s", fname, ext);
585 for(tail = fs_name; *tail; tail++)
587 if(*tail ==
'/') *tail =
'_';
594 my_message_cb(sev_fatal,
"Out of memory");
598 my_message_cb( sev_info,
"reading %s -> %s", buf, fs_name );
600 if(cbmcopy_read_file(fd, settings, drive, buf, strlen(buf),
601 &filedata, &filesize,
602 my_message_cb, my_status_cb) == 0)
605 my_message_cb( rv ? sev_warning : sev_info,
"%s", buf );
607 file = fopen(fs_name,
"wb");
612 if(address >= 0 && filesize > 1)
614 filedata[0] = address % 0x100;
615 filedata[1] = address / 0x100;
617 my_message_cb( sev_debug,
618 "override address: $%02x%02x",
619 filedata[1], filedata[0] );
621 if(fwrite(filedata, filesize, 1, file) != 1)
623 my_message_cb(sev_warning,
624 "could not write %s: %s",
625 fs_name, arch_strerror(arch_get_errno()));
632 my_message_cb(sev_warning,
633 "could not open %s: %s",
634 fs_name, arch_strerror(arch_get_errno()));
644 my_message_cb(sev_warning,
"error reading %s", buf);
656 my_message_cb(sev_warning,
"there was at least one error" );
char * cbmlibmisc_strdup(const char *const OldString)
Duplicate a given string.
void cbmlibmisc_strfree(const char *String)
Free a string.
int CBMAPIDECL cbm_device_status(CBM_FILE HandleDevice, unsigned char DeviceAddress, void *Buffer, size_t BufferLength)
Read the drive status from a floppy.
int ARCH_MAINDECL main(int argc, char **argv)
Initialize the xum1541 device This function tries to find and identify the xum1541 device...
int CBMAPIDECL cbm_driver_open_ex(CBM_FILE *HandleDevice, char *Adapter)
Opens the driver, extended version.
void CBMAPIDECL cbm_driver_close(CBM_FILE HandleDevice)
Closes the driver.
void arch_set_ctrlbreak_handler(ARCH_CTRLBREAK_HANDLER Handler)
Set the Ctrl+C / Ctrl+Break handler.
int CBMAPIDECL cbm_reset(CBM_FILE HandleDevice)
RESET all devices.
char *CBMAPIDECL cbm_ascii2petscii(char *Str)
Convert an null-termined ASCII string to PETSCII.
DLL interface for accessing the driver.
Define makros and functions which account for differences between the different architectures.
Some functions for string handling.