1 /*
2 ucon64_opts.c - switches for all uCON64 options
3
4 Copyright (c) 2002 - 2005 NoisyB
5 Copyright (c) 2002 - 2005, 2015 - 2021 dbjh
6 Copyright (c) 2005 Jan-Erik Karlsson (Amiga)
7
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #ifdef _MSC_VER
27 #pragma warning(push)
28 #pragma warning(disable: 4668) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
29 #endif
30 #include <ctype.h>
31 #ifdef _MSC_VER
32 #pragma warning(pop)
33 #endif
34 #include <errno.h>
35 #ifdef _MSC_VER
36 #pragma warning(push)
37 #pragma warning(disable: 4820) // 'bytes' bytes padding added after construct 'member_name'
38 #include <io.h>
39 #pragma warning(pop)
40 #endif
41 #include <stdlib.h>
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45 #ifdef _MSC_VER
46 #pragma warning(push)
47 #pragma warning(disable: 4820) // 'bytes' bytes padding added after construct 'member_name'
48 #endif
49 #include <sys/stat.h>
50 #ifdef _MSC_VER
51 #pragma warning(pop)
52 #endif
53 #include "misc/archive.h"
54 #include "misc/file.h"
55 #include "misc/misc.h"
56 #include "misc/parallel.h"
57 #include "misc/string.h"
58 #include "misc/term.h" // to avoid MinGW warning about using ll prefix in fprintf()
59 #include "ucon64_dat.h"
60 #include "ucon64_misc.h"
61 #include "ucon64_opts.h"
62 #include "console/dc.h"
63 #include "console/gb.h"
64 #include "console/gba.h"
65 #include "console/genesis.h"
66 #include "console/lynx.h"
67 #include "console/n64.h"
68 #include "console/nds.h"
69 #include "console/neogeo.h"
70 #include "console/nes.h"
71 #include "console/pce.h"
72 #include "console/sms.h"
73 #include "console/snes.h"
74 #include "console/swan.h"
75 #include "backup/backup.h"
76 #include "backup/cd64.h"
77 #include "backup/cmc.h"
78 #include "backup/doctor64.h"
79 #include "backup/doctor64jr.h"
80 #include "backup/f2a.h"
81 #include "backup/fal.h"
82 #include "backup/gbx.h"
83 #include "backup/gd.h"
84 #include "backup/lynxit.h"
85 #include "backup/mccl.h"
86 #include "backup/mcd.h"
87 #include "backup/md-pro.h"
88 #include "backup/msg.h"
89 #include "backup/pce-pro.h"
90 #include "backup/pl.h"
91 #include "backup/quickdev16.h"
92 #include "backup/sflash.h"
93 #include "backup/smc.h"
94 #include "backup/smcic2.h"
95 #include "backup/smd.h"
96 #include "backup/smsgg-pro.h"
97 #include "backup/swc.h"
98 #include "backup/ufosd.h"
99 #include "patch/aps.h"
100 #include "patch/bsl.h"
101 #include "patch/gg.h"
102 #include "patch/ips.h"
103 #include "patch/ppf.h"
104
105
106 static int
strtoint(const char * str,int base,void * var,size_t var_size)107 strtoint (const char *str, int base, void *var, size_t var_size)
108 {
109 char *endptr;
110 int64_t value = 0;
111
112 if (var_size > sizeof value)
113 var_size = sizeof value;
114 errno = 0;
115 value = strtoll (str, &endptr, base);
116 if (errno || *endptr)
117 return -1;
118 else
119 #ifndef WORDS_BIGENDIAN
120 memcpy (var, &value, var_size);
121 #else
122 memcpy (var, ((uint8_t *) &value) + sizeof value - var_size, var_size);
123 #endif
124
125 return 0;
126 }
127
128
129 int
ucon64_switches(st_ucon64_t * p)130 ucon64_switches (st_ucon64_t *p)
131 {
132 int x = 0;
133 const char *option_arg = p->optarg;
134
135 /*
136 Handle options or switches that cause other _options_ to be ignored except
137 other options of the same class (so the order in which they were specified
138 matters).
139 We have to do this here (not in ucon64_options()) or else other options
140 might be executed before these.
141 */
142 switch (p->option)
143 {
144 /*
145 Many tools ignore other options if --help has been specified. We do the
146 same (compare with GNU tools).
147 */
148 case UCON64_HELP:
149 x = USAGE_VIEW_LONG;
150 if (option_arg)
151 {
152 if (!strcmp (option_arg, "pad"))
153 x = USAGE_VIEW_PAD;
154 else if (!strcmp (option_arg, "dat"))
155 x = USAGE_VIEW_DAT;
156 else if (!strcmp (option_arg, "patch"))
157 x = USAGE_VIEW_PATCH;
158 else if (!strcmp (option_arg, "backup"))
159 x = USAGE_VIEW_BACKUP;
160 else if (!strcmp (option_arg, "disc"))
161 x = USAGE_VIEW_DISC;
162 }
163 ucon64_usage (ucon64.argc, ucon64.argv, x);
164 exit (0);
165
166 /*
167 It's also common to exit after displaying version information.
168 On some configurations printf is a macro (Red Hat Linux 6.2 + GCC 3.2),
169 so we can't use preprocessor directives in the argument list.
170 */
171 case UCON64_VER:
172 printf ("version: %s (%s)\n"
173 "platform: %s\n",
174 UCON64_VERSION_S, __DATE__, CURRENT_OS_S);
175
176 #ifdef USE_PARALLEL
177 #ifdef USE_PPDEV
178 puts ("parallel port backup unit support: yes (ppdev)");
179 #else
180 puts ("parallel port backup unit support: yes");
181 #endif // USE_PPDEV
182 #else
183 puts ("parallel port backup unit support: no");
184 #endif
185
186 #ifdef USE_USB
187 puts ("USB port backup unit support: yes");
188 #else
189 puts ("USB port backup unit support: no");
190 #endif
191
192
193 #ifdef USE_ANSI_COLOR
194 puts ("ANSI colors enabled: yes");
195 #else
196 puts ("ANSI colors enabled: no");
197 #endif
198
199 #ifdef USE_ZLIB
200 printf ("gzip and zip support: yes, zlib %s\n",
201 ZLIB_VERSION);
202 #else
203 puts ("gzip and zip support: no");
204 #endif
205
206 printf ("configuration file %s %s\n",
207 // display the existence only for the config file (really helps solving problems)
208 access (ucon64.configfile, F_OK) ? "(not present):" : "(present): ",
209 ucon64.configfile);
210
211 #ifdef USE_DISCMAGE
212 fputs ("discmage DLL: ", stdout);
213
214 #ifdef DLOPEN
215 puts (ucon64.discmage_path);
216 #else
217 #if defined __MSDOS__
218 fputs ("discmage.dxe", stdout);
219 #elif defined __CYGWIN__ || defined _WIN32
220 fputs ("discmage.dll", stdout);
221 #elif defined __APPLE__ // Mac OS X actually
222 fputs ("libdiscmage.dylib", stdout);
223 #elif defined __unix__ || defined __BEOS__
224 fputs ("libdiscmage.so", stdout);
225 #else
226 fputs ("unknown", stdout);
227 #endif
228 puts (", dynamically linked");
229 #endif // DLOPEN
230
231 if (ucon64.discmage_enabled)
232 {
233 x = dm_get_version ();
234 printf ("discmage enabled: yes, %d.%d.%d (%s)\n",
235 (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff,
236 dm_get_version_s ());
237 }
238 else
239 puts ("discmage enabled: no");
240 #endif // USE_DISCMAGE
241
242 printf ("configuration directory: %s\n"
243 "DAT file directory: %s\n"
244 "entries in DATabase: %u\n"
245 "DATabase enabled: %s\n",
246 ucon64.configdir,
247 ucon64.datdir,
248 ucon64_dat_total_entries (),
249 ucon64.dat_enabled ? "yes" : "no");
250 exit (0);
251 break;
252
253 case UCON64_FRONTEND:
254 ucon64.frontend = 1; // used by (for example) ucon64_gauge()
255 break;
256
257 case UCON64_NBAK:
258 ucon64.backup = 0;
259 break;
260
261 case UCON64_R:
262 ucon64.recursive = 1;
263 break;
264
265 #ifdef USE_ANSI_COLOR
266 case UCON64_NCOL:
267 ucon64.ansi_color = 0;
268 break;
269 #endif
270
271 case UCON64_RIP:
272 case UCON64_MKTOC:
273 case UCON64_MKCUE:
274 case UCON64_MKSHEET:
275 case UCON64_BIN2ISO:
276 case UCON64_ISOFIX:
277 case UCON64_XCDRW:
278 case UCON64_DISC:
279 case UCON64_CDMAGE:
280 ucon64.force_disc = 1;
281 break;
282
283 case UCON64_NS:
284 ucon64.org_split = ucon64.split = 0;
285 break;
286
287 case UCON64_HD:
288 ucon64.backup_header_len = UNKNOWN_BACKUP_HEADER_LEN;
289 break;
290
291 case UCON64_HDN:
292 ucon64.backup_header_len = strtol (option_arg, NULL, 10);
293 break;
294
295 case UCON64_NHD:
296 ucon64.backup_header_len = 0;
297 break;
298
299 case UCON64_SWP: // deprecated
300 case UCON64_INT:
301 ucon64.interleaved = 1;
302 break;
303
304 case UCON64_INT2:
305 ucon64.interleaved = 2;
306 break;
307
308 case UCON64_NSWP: // deprecated
309 case UCON64_NINT:
310 ucon64.interleaved = 0;
311 break;
312
313 case UCON64_PORT:
314 #ifdef USE_USB
315 if (!strnicmp (option_arg, "usb", 3))
316 {
317 if (strlen (option_arg) >= 4)
318 ucon64.usbport = strtol (option_arg + 3, NULL, 10) + 1; // usb0 => ucon64.usbport = 1
319 else // we automatically detect the
320 ucon64.usbport = 1; // USB port in the F2A & Quickdev16 code
321
322 /*
323 We don't want to make uCON64 behave differently if --port=USB{n} is
324 specified *after* a transfer option (instead of before one), so we
325 have to reset ucon64.parport_needed here.
326 */
327 ucon64.parport_needed = 0;
328 }
329 else
330 #endif
331 ucon64.parport = (uint16_t) strtol (option_arg, NULL, 16);
332 break;
333
334 #ifdef USE_PARALLEL
335 /*
336 We detect the presence of these options here so that we can drop
337 privileges ASAP.
338 Note that the libcd64 options are not listed here. We cannot drop
339 privileges before libcd64 is initialised (after cd64_t.devopen() has been
340 called).
341 */
342 case UCON64_XFIG:
343 case UCON64_XFIGC:
344 case UCON64_XFIGS:
345 case UCON64_XIC2:
346 case UCON64_XLIT:
347 case UCON64_XMSG:
348 case UCON64_XRESET:
349 case UCON64_XSMC:
350 case UCON64_XSMCR:
351 case UCON64_XSMD:
352 case UCON64_XSMDS:
353 case UCON64_XSWC:
354 case UCON64_XSWC2:
355 case UCON64_XSWCC:
356 case UCON64_XSWCR:
357 case UCON64_XSWCS:
358 case UCON64_XV64:
359 if (!UCON64_ISSET2 (ucon64.parport_mode, parport_mode_t))
360 ucon64.parport_mode = PPMODE_SPP;
361 case UCON64_XCMC:
362 case UCON64_XCMCT:
363 case UCON64_XGD3:
364 case UCON64_XGD3R:
365 case UCON64_XGD3S:
366 case UCON64_XGD6:
367 case UCON64_XGD6R:
368 case UCON64_XGD6S:
369 case UCON64_XMCCL:
370 case UCON64_XMCD:
371 if (!UCON64_ISSET2 (ucon64.parport_mode, parport_mode_t))
372 ucon64.parport_mode = PPMODE_SPP_BIDIR;
373 case UCON64_XDJR:
374 case UCON64_XF2A: // could be for USB version
375 case UCON64_XF2AMULTI: // idem
376 case UCON64_XF2AB: // idem
377 case UCON64_XF2AC: // idem
378 case UCON64_XF2AS: // idem
379 case UCON64_XFAL:
380 case UCON64_XFALMULTI:
381 case UCON64_XFALB:
382 case UCON64_XFALC:
383 case UCON64_XFALS:
384 case UCON64_XGBX:
385 case UCON64_XGBXB:
386 case UCON64_XGBXS:
387 case UCON64_XGG:
388 case UCON64_XGGB:
389 case UCON64_XGGS:
390 case UCON64_XMD:
391 case UCON64_XMDB:
392 case UCON64_XMDS:
393 case UCON64_XPCE:
394 case UCON64_XPL:
395 case UCON64_XPLI:
396 case UCON64_XSF:
397 case UCON64_XSFS:
398 if (!UCON64_ISSET2 (ucon64.parport_mode, parport_mode_t))
399 ucon64.parport_mode = PPMODE_EPP;
400 #ifdef USE_USB
401 if (!ucon64.usbport) // no pport I/O if F2A option and USB F2A
402 #endif
403 ucon64.parport_needed = 1;
404 break;
405 #endif // USE_PARALLEL
406
407 #ifdef USE_LIBCD64
408 case UCON64_XCD64:
409 case UCON64_XCD64B:
410 case UCON64_XCD64C:
411 case UCON64_XCD64E:
412 case UCON64_XCD64F:
413 case UCON64_XCD64M:
414 case UCON64_XCD64S:
415 #ifdef USE_PARALLEL
416 if (!UCON64_ISSET2 (ucon64.parport_mode, parport_mode_t))
417 ucon64.parport_mode = PPMODE_SPP_BIDIR;
418 #endif
419 // We don't really need the parallel port. We just have to make sure that
420 // privileges aren't dropped.
421 ucon64.parport_needed = 2;
422 break;
423
424 case UCON64_XCD64P:
425 ucon64.io_mode = strtol (option_arg, NULL, 10);
426 break;
427 #endif // USE_LIBCD64
428
429 #ifdef USE_PARALLEL
430 case UCON64_XCMCM:
431 ucon64.io_mode = strtol (option_arg, NULL, 10);
432 break;
433
434 case UCON64_XFALM:
435 case UCON64_XGBXM:
436 case UCON64_XPLM:
437 ucon64.parport_mode = PPMODE_SPP_BIDIR;
438 break;
439
440 case UCON64_XSWC_IO:
441 ucon64.io_mode = strtol (option_arg, NULL, 16);
442
443 if (ucon64.io_mode & SWC_IO_ALT_ROM_SIZE)
444 puts ("WARNING: I/O mode not yet implemented");
445 #if 0 // all these constants are defined by default
446 if (ucon64.io_mode & (SWC_IO_SPC7110 | SWC_IO_SDD1 | SWC_IO_SA1 | SWC_IO_MMX2))
447 puts ("WARNING: Be sure to compile swc.c with the appropriate constants defined");
448 #endif
449
450 if (ucon64.io_mode > SWC_IO_MAX)
451 {
452 printf ("WARNING: Invalid value for MODE (0x%x), using 0\n", ucon64.io_mode);
453 ucon64.io_mode = 0;
454 }
455 else
456 {
457 printf ("I/O mode: 0x%03x", ucon64.io_mode);
458 if (ucon64.io_mode)
459 {
460 char flagstr[160];
461
462 flagstr[0] = '\0';
463 if (ucon64.io_mode & SWC_IO_FORCE_32MBIT)
464 strcat (flagstr, "force 32 Mbit dump, ");
465 if (ucon64.io_mode & SWC_IO_ALT_ROM_SIZE)
466 strcat (flagstr, "alternative ROM size method, ");
467 if (ucon64.io_mode & SWC_IO_SUPER_FX)
468 strcat (flagstr, "Super FX, ");
469 if (ucon64.io_mode & SWC_IO_SDD1)
470 strcat (flagstr, "S-DD1, ");
471 if (ucon64.io_mode & SWC_IO_SA1)
472 strcat (flagstr, "SA-1, ");
473 if (ucon64.io_mode & SWC_IO_SPC7110)
474 strcat (flagstr, "SPC7110, ");
475 if (ucon64.io_mode & SWC_IO_DX2_TRICK)
476 strcat (flagstr, "DX2 trick, ");
477 if (ucon64.io_mode & SWC_IO_MMX2)
478 strcat (flagstr, "Mega Man X 2, ");
479 if (ucon64.io_mode & SWC_IO_DUMP_BIOS)
480 strcat (flagstr, "dump BIOS, ");
481
482 if (flagstr[0])
483 flagstr[strlen (flagstr) - 2] = '\0';
484 printf (" (%s)", flagstr);
485 }
486 fputc ('\n', stdout);
487 }
488 break;
489 #endif // USE_PARALLEL
490
491 #ifdef USE_USB
492 case UCON64_XQD16:
493 case UCON64_XUFOSD:
494 /*
495 It is possible to perform USB I/O without being root. However, without
496 any configuration root privileges are required. By default uCON64 will
497 be installed setuid root (on UNIX), so we just have to make sure
498 privileges will not be dropped. One way to do that is assigning 2 to
499 ucon64.parport_needed. A more appropriate way for USB devices is using
500 ucon64.usbport.
501 */
502 if (!ucon64.usbport)
503 ucon64.usbport = 1;
504 break;
505 #endif // USE_USB
506
507 case UCON64_PATCH: // --patch and --file are the same
508 case UCON64_FILE:
509 ucon64.file = option_arg;
510 break;
511
512 case UCON64_I:
513 case UCON64_B:
514 case UCON64_A:
515 case UCON64_NA:
516 case UCON64_PPF:
517 case UCON64_NPPF:
518 case UCON64_IDPPF:
519 if (!ucon64.file || !ucon64.file[0])
520 ucon64.file = ucon64.argv[ucon64.argc - 1];
521 break;
522
523 #if 0
524 case UCON64_ROM:
525 if (option_arg)
526 ucon64.fname = option_arg;
527 break;
528 #endif
529
530 case UCON64_O:
531 {
532 char path[FILENAME_MAX];
533 int dir = 0;
534
535 if (realpath2 (option_arg, path))
536 {
537 char dir_name[FILENAME_MAX];
538 struct stat fstate;
539
540 /*
541 MinGW's stat() does not accept a trailing slash or backslash, but
542 dirname2() only recognizes a path as directory if it ends with a
543 slash or backslash.
544 */
545 strcat (path, DIR_SEPARATOR_S);
546 dirname2 (path, dir_name);
547 if (!stat (dir_name, &fstate) && S_ISDIR (fstate.st_mode))
548 {
549 // dirname2() strips trailing slashes and/or backslashes (if not
550 // the root directory of a drive).
551 snprintf (ucon64.output_path, FILENAME_MAX, "%s%s", dir_name,
552 dir_name[strlen (dir_name) - 1] != DIR_SEPARATOR ?
553 DIR_SEPARATOR_S : "");
554 ucon64.output_path[FILENAME_MAX - 1] = '\0';
555 dir = 1;
556 }
557 }
558
559 if (!dir)
560 puts ("WARNING: Argument for " OPTION_S "o must be a directory. Using current directory instead");
561 }
562 break;
563
564 case UCON64_NHI:
565 ucon64.snes_hirom = 0;
566 break;
567
568 case UCON64_HI:
569 ucon64.snes_hirom = SNES_HIROM;
570 break;
571
572 case UCON64_EROM:
573 ucon64.snes_header_base = SNES_EROM;
574 break;
575
576 case UCON64_BS:
577 ucon64.bs_dump = 1;
578 break;
579
580 case UCON64_NBS:
581 ucon64.bs_dump = 0;
582 break;
583
584 case UCON64_CTRL:
585 if (UCON64_ISSET (ucon64.controller))
586 ucon64.controller |= 1 << strtol (option_arg, NULL, 10);
587 else
588 ucon64.controller = 1 << strtol (option_arg, NULL, 10);
589 break;
590
591 case UCON64_CTRL2:
592 if (UCON64_ISSET (ucon64.controller2))
593 ucon64.controller2 |= 1 << strtol (option_arg, NULL, 10);
594 else
595 ucon64.controller2 = 1 << strtol (option_arg, NULL, 10);
596 break;
597
598 case UCON64_NTSC:
599 if (!UCON64_ISSET (ucon64.tv_standard))
600 ucon64.tv_standard = 0;
601 else if (ucon64.tv_standard == 1)
602 ucon64.tv_standard = 2; // code for NTSC/PAL (NES UNIF/iNES)
603 break;
604
605 case UCON64_PAL:
606 if (!UCON64_ISSET (ucon64.tv_standard))
607 ucon64.tv_standard = 1;
608 else if (ucon64.tv_standard == 0)
609 ucon64.tv_standard = 2; // code for NTSC/PAL (NES UNIF/iNES)
610 break;
611
612 case UCON64_BAT:
613 ucon64.battery = 1;
614 break;
615
616 case UCON64_NBAT:
617 ucon64.battery = 0;
618 break;
619
620 case UCON64_VRAM:
621 ucon64.vram = 1;
622 break;
623
624 case UCON64_NVRAM:
625 ucon64.vram = 0;
626 break;
627
628 case UCON64_MIRR:
629 ucon64.mirror = strtol (option_arg, NULL, 10);
630 break;
631
632 case UCON64_MAPR:
633 ucon64.mapr = option_arg; // pass the _string_, it can be a
634 break; // board name
635
636 case UCON64_CMNT:
637 ucon64.comment = option_arg;
638 break;
639
640 case UCON64_DUMPINFO:
641 ucon64.use_dump_info = 1;
642 ucon64.dump_info = option_arg;
643 break;
644
645 case UCON64_RANGE:
646 {
647 char buf[80], *token;
648 size_t len = strnlen (option_arg, sizeof buf - 1);
649 unsigned int offset1, offset2;
650
651 strncpy (buf, option_arg, len)[len] = '\0';
652
653 token = strtok (buf, ":");
654 if (!token)
655 {
656 fputs ("ERROR: No O1 (offset 1) specified. Specify one before a colon\n", stderr);
657 break;
658 }
659 if (strtoint (token, 16, &offset1, sizeof offset1))
660 {
661 fprintf (stderr, "ERROR: Invalid O1 (offset 1): %s\n", token);
662 break;
663 }
664
665 token = strtok (NULL, "");
666 if (!token)
667 {
668 fputs ("ERROR: No O2 (offset 2) specified. Specify one after a colon\n", stderr);
669 break;
670 }
671 if (strtoint (token, 16, &offset2, sizeof offset2))
672 {
673 fprintf (stderr, "ERROR: Invalid O2 (offset 2): %s\n", token);
674 break;
675 }
676
677 if (offset1 >= offset2)
678 {
679 fputs ("ERROR: When specifying a range O2 (offset 2) must be larger than O1 (offset 1)\n",
680 stderr);
681 break;
682 }
683
684 ucon64.range_start = offset1;
685 ucon64.range_length = offset2 - offset1 + 1;
686 }
687 break;
688
689 case UCON64_Q:
690 case UCON64_QQ: // for now -qq is equivalent to -q
691 ucon64.quiet = 1;
692 cm_verbose = 0;
693 break;
694
695 case UCON64_V:
696 ucon64.quiet = -1;
697 cm_verbose = 1;
698 break;
699
700 case UCON64_SSIZE:
701 ucon64.part_size = strtol (option_arg, NULL, 10) * MBIT;
702 break;
703
704 case UCON64_ID:
705 ucon64.id = -2; // just a value other than
706 break; // UCON64_UNKNOWN and smaller than 0
707
708 case UCON64_IDNUM:
709 ucon64.id = strtol (option_arg, NULL, 10);
710 if (ucon64.id < 0)
711 ucon64.id = 0;
712 else if (ucon64.id > 999)
713 {
714 fputs ("ERROR: NUM must be smaller than or equal to 999\n", stderr);
715 exit (1);
716 }
717 break;
718
719 case UCON64_REGION:
720 if (option_arg[1] == '\0' && toupper ((int) option_arg[0]) == 'X') // be insensitive to case
721 ucon64.region = 256;
722 else
723 ucon64.region = strtol (option_arg, NULL, 10);
724 break;
725
726 default:
727 break;
728 }
729
730 return 0;
731 }
732
733
734 static inline char *
tofunc(char * s,size_t len,int (* func)(int))735 tofunc (char *s, size_t len, int (*func) (int))
736 {
737 char *p = s;
738
739 for (; len > 0; p++, len--)
740 *p = (char) func (*p);
741
742 return s;
743 }
744
745
746 static inline int
ls_toprint(int c)747 ls_toprint (int c)
748 {
749 return isprint (c) ? c : '.';
750 }
751
752
753 static int
hexstring_to_ints(char * src,int wildcard)754 hexstring_to_ints (char *src, int wildcard)
755 {
756 int retval = 0, i = 0;
757 char *dest = src;
758 uint8_t value = 0;
759
760 for (; *src; ++src)
761 {
762 uint8_t digit;
763
764 if (*src == ' ' || *src == '\t')
765 continue;
766 else if (*src >= '0' && *src <= '9')
767 digit = *src - '0';
768 else if (*src >= 'A' && *src <= 'F')
769 digit = *src - 'A' + 10;
770 else if (*src >= 'a' && *src <= 'f')
771 digit = *src - 'a' + 10;
772 else if (wildcard && *src == '?')
773 {
774 *dest++ = *src;
775 i += i & 1 ? 1 : 2;
776 continue;
777 }
778 else
779 {
780 retval = -1;
781 break;
782 }
783 value = value << 4 | digit;
784 if (i & 1)
785 *dest++ = value;
786 i++;
787 }
788 *dest = '\0';
789
790 if (!retval)
791 retval = i / 2;
792
793 return retval;
794 }
795
796
797 static int64_t
strtoll2(const char * str)798 strtoll2 (const char *str)
799 {
800 char *endptr;
801 int64_t value = 0;
802
803 errno = 0;
804 value = strtoll (str, &endptr, 10);
805 if (errno || *endptr)
806 value = strtoll (str, NULL, 16);
807
808 return value;
809 }
810
811
812 static void
set_dump_args(const char * str,uint64_t * start,uint64_t * len)813 set_dump_args (const char *str, uint64_t *start, uint64_t *len)
814 {
815 char buf[80], *token;
816 size_t l;
817 uint64_t end;
818
819 if (!str)
820 {
821 *start = 0;
822 *len = ucon64.fsize;
823 return;
824 }
825
826 l = strnlen (str, sizeof buf - 1);
827 strncpy (buf, str, l)[l] = '\0';
828
829 token = strtok (buf, ":");
830 if (!token)
831 {
832 *start = 0;
833 *len = ucon64.fsize;
834 return;
835 }
836 *start = strtoll2 (token);
837 if (*start >= ucon64.fsize)
838 {
839 fprintf (stderr,
840 "ERROR: O1 (start) must be smaller than the file size (0x%llx)\n",
841 (long long unsigned int) ucon64.fsize);
842 exit (1);
843 }
844
845 token = strtok (NULL, "");
846 if (!token)
847 {
848 *len = ucon64.fsize - *start;
849 return;
850 }
851 end = strtoll2 (token);
852 if (end >= ucon64.fsize)
853 {
854 fprintf (stderr,
855 "ERROR: O2 (end) must be smaller than the file size (0x%llx)\n",
856 (long long unsigned int) ucon64.fsize);
857 exit (1);
858 }
859 if (*start > end)
860 {
861 fputs ("ERROR: O2 (end) must be larger than or equal to O1 (start)\n", stderr);
862 exit (1);
863 }
864 *len = end - *start + 1;
865 }
866
867
868 int
ucon64_options(st_ucon64_t * p)869 ucon64_options (st_ucon64_t *p)
870 {
871 #ifdef USE_PARALLEL
872 unsigned short enableRTS = (unsigned short) -1; // for UCON64_XSWC & UCON64_XSWC2
873 #endif
874 int value = 0, x = 0;
875 unsigned int checksum;
876 char buf[MAXBUFSIZE], src_name[FILENAME_MAX], dest_name[FILENAME_MAX],
877 *ptr = NULL, *values[UCON64_MAX_ARGS];
878 const char *option_arg = p->optarg;
879
880 strcpy (src_name, ucon64.fname);
881 strcpy (dest_name, ucon64.fname);
882
883 switch (p->option)
884 {
885 case UCON64_CRCHD: // deprecated
886 value = UNKNOWN_BACKUP_HEADER_LEN;
887 case UCON64_CRC:
888 if (!value)
889 value = ucon64.nfo ? ucon64.nfo->backup_header_len :
890 UCON64_ISSET2 (ucon64.backup_header_len, unsigned int) ?
891 ucon64.backup_header_len : 0;
892 fputs (ucon64.fname, stdout);
893 if (ucon64.fname_arch[0])
894 printf (" (%s)\n", ucon64.fname_arch);
895 else
896 fputc ('\n', stdout);
897 checksum = 0;
898 ucon64_chksum (NULL, NULL, &checksum, ucon64.fname, ucon64.fsize, value);
899 printf ("Checksum (CRC32): 0x%08x\n", checksum);
900 break;
901
902 case UCON64_SHA1:
903 value = ucon64.nfo ? ucon64.nfo->backup_header_len :
904 UCON64_ISSET2 (ucon64.backup_header_len, unsigned int) ?
905 ucon64.backup_header_len : 0;
906 fputs (ucon64.fname, stdout);
907 if (ucon64.fname_arch[0])
908 printf (" (%s)\n", ucon64.fname_arch);
909 else
910 fputc ('\n', stdout);
911 ucon64_chksum (buf, NULL, NULL, ucon64.fname, ucon64.fsize, value);
912 printf ("Checksum (SHA1): 0x%s\n", buf);
913 break;
914
915 case UCON64_MD5:
916 value = ucon64.nfo ? ucon64.nfo->backup_header_len :
917 UCON64_ISSET2 (ucon64.backup_header_len, unsigned int) ?
918 ucon64.backup_header_len : 0;
919 fputs (ucon64.fname, stdout);
920 if (ucon64.fname_arch[0])
921 printf (" (%s)\n", ucon64.fname_arch);
922 else
923 fputc ('\n', stdout);
924 ucon64_chksum (NULL, buf, NULL, ucon64.fname, ucon64.fsize, value);
925 printf ("Checksum (MD5): 0x%s\n", buf);
926 break;
927
928 case UCON64_HEX:
929 {
930 uint64_t start, len;
931 set_dump_args (option_arg, &start, &len);
932 ucon64_dump (stdout, ucon64.fname, start, len, DUMPER_HEX);
933 }
934 break;
935
936 case UCON64_BIT:
937 {
938 uint64_t start, len;
939 set_dump_args (option_arg, &start, &len);
940 ucon64_dump (stdout, ucon64.fname, start, len, DUMPER_BIT);
941 }
942 break;
943
944 case UCON64_CODE:
945 {
946 uint64_t start, len;
947 set_dump_args (option_arg, &start, &len);
948 ucon64_dump (stdout, ucon64.fname, start, len, DUMPER_CODE);
949 }
950 break;
951
952 case UCON64_PRINT:
953 {
954 uint64_t start, len;
955 set_dump_args (option_arg, &start, &len);
956 ucon64_dump (stdout, ucon64.fname, start, len, DUMPER_PRINT);
957 }
958 break;
959
960 case UCON64_C:
961 ucon64_filefile (option_arg, 0, 0, FALSE);
962 break;
963
964 case UCON64_CS:
965 ucon64_filefile (option_arg, 0, 0, TRUE);
966 break;
967
968 case UCON64_FIND:
969 ucon64_find (ucon64.fname, 0, ucon64.fsize, option_arg,
970 strlen (option_arg), MEMCMP2_WCARD ('?'));
971 break;
972
973 case UCON64_FINDR:
974 ucon64_find (ucon64.fname, 0, ucon64.fsize, option_arg,
975 strlen (option_arg), MEMCMP2_REL);
976 break;
977
978 case UCON64_FINDI:
979 ucon64_find (ucon64.fname, 0, ucon64.fsize, option_arg,
980 strlen (option_arg), MEMCMP2_WCARD ('?') | MEMCMP2_CASE);
981 break;
982
983 case UCON64_HFIND:
984 strcpy (buf, option_arg);
985 value = hexstring_to_ints (buf, 1);
986 if (value < 0)
987 {
988 fprintf (stderr, "ERROR: Invalid search string: %s\n", option_arg);
989 break;
990 }
991 ucon64_find (ucon64.fname, 0, ucon64.fsize, buf, value, MEMCMP2_WCARD ('?'));
992 break;
993
994 case UCON64_HFINDR:
995 strcpy (buf, option_arg);
996 value = hexstring_to_ints (buf, 0);
997 if (value < 0)
998 {
999 fprintf (stderr, "ERROR: Invalid search string: %s\n", option_arg);
1000 break;
1001 }
1002 ucon64_find (ucon64.fname, 0, ucon64.fsize, buf, value, MEMCMP2_REL);
1003 break;
1004
1005 case UCON64_DFIND:
1006 strcpy (buf, option_arg);
1007 value = strarg (values, buf, " ", UCON64_MAX_ARGS);
1008 for (x = 0; x < value; x++)
1009 buf[x] = values[x][0] == '?' && values[x][1] == '\0' ?
1010 '?' : (char) strtol (values[x], NULL, 10);
1011 buf[x] = '\0';
1012 ucon64_find (ucon64.fname, 0, ucon64.fsize, buf, value, MEMCMP2_WCARD ('?'));
1013 break;
1014
1015 case UCON64_DFINDR:
1016 strcpy (buf, option_arg);
1017 value = strarg (values, buf, " ", UCON64_MAX_ARGS);
1018 for (x = 0; x < value; x++)
1019 buf[x] = (char) strtol (values[x], NULL, 10);
1020 buf[x] = '\0';
1021 ucon64_find (ucon64.fname, 0, ucon64.fsize, buf, value, MEMCMP2_REL);
1022 break;
1023
1024 case UCON64_HREPLACE:
1025 {
1026 size_t len = strnlen (option_arg, sizeof buf - 1);
1027 int searchlen, replacelen;
1028 char *token, *search, *replace;
1029
1030 strncpy (buf, option_arg, len)[len] = '\0';
1031
1032 token = strtok (buf, ":");
1033 if (!token)
1034 {
1035 fputs ("ERROR: No search string specified. Specify one before a colon\n",
1036 stderr);
1037 break;
1038 }
1039 if ((search = strdup (token)) == NULL)
1040 {
1041 fprintf (stderr, ucon64_msg[BUFFER_ERROR], strlen (token) + 1);
1042 break;
1043 }
1044 searchlen = hexstring_to_ints (search, 1);
1045 if (searchlen < 0)
1046 {
1047 fprintf (stderr, "ERROR: S (search string) is invalid: %s\n", token);
1048 free (search);
1049 break;
1050 }
1051
1052 token = strtok (NULL, "");
1053 if (!token)
1054 {
1055 fputs ("ERROR: No replacement string specified. Specify one after a colon\n",
1056 stderr);
1057 free (search);
1058 break;
1059 }
1060 if ((replace = strdup (token)) == NULL)
1061 {
1062 fprintf (stderr, ucon64_msg[BUFFER_ERROR], strlen (token) + 1);
1063 free (search);
1064 break;
1065 }
1066 replacelen = hexstring_to_ints (replace, 0);
1067 if (replacelen < 0)
1068 {
1069 fprintf (stderr, "ERROR: R (replacement string) is invalid: %s\n", token);
1070 free (search);
1071 free (replace);
1072 break;
1073 }
1074
1075 ucon64_replace (ucon64.fname, 0, ucon64.fsize, search, searchlen,
1076 replace, replacelen, MEMCMP2_WCARD ('?'));
1077
1078 free (search);
1079 free (replace);
1080 }
1081 break;
1082
1083 case UCON64_PADHD: // deprecated
1084 value = UNKNOWN_BACKUP_HEADER_LEN;
1085 case UCON64_P:
1086 case UCON64_PAD:
1087 if (!value && ucon64.nfo)
1088 value = ucon64.nfo->backup_header_len;
1089 ucon64_file_handler (dest_name, src_name, 0);
1090
1091 fcopy (src_name, 0, ucon64.fsize, dest_name, "wb");
1092 if (truncate2 (dest_name, ucon64.fsize +
1093 (MBIT - ((ucon64.fsize - value) % MBIT))) == -1)
1094 {
1095 fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], dest_name); // msg is not a typo
1096 exit (1);
1097 }
1098
1099 printf (ucon64_msg[WROTE], dest_name);
1100 remove_temp_file ();
1101 break;
1102
1103 case UCON64_PADN:
1104 ucon64_file_handler (dest_name, src_name, 0);
1105
1106 fcopy (src_name, 0, ucon64.fsize, dest_name, "wb");
1107 if (truncate2 (dest_name, strtoll (option_arg, NULL, 10) +
1108 (ucon64.nfo ? ucon64.nfo->backup_header_len : 0)) == -1)
1109 {
1110 fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], dest_name); // msg is not a typo
1111 exit (1);
1112 }
1113
1114 printf (ucon64_msg[WROTE], dest_name);
1115 remove_temp_file ();
1116 break;
1117
1118 case UCON64_ISPAD:
1119 {
1120 int64_t padded = ucon64_testpad (ucon64.fname);
1121
1122 if (padded != -1)
1123 {
1124 if (!padded)
1125 puts ("Padded: No");
1126 else
1127 printf ("Padded: Maybe, %lld Byte%s (%.4f Mb)\n",
1128 (long long int) padded, padded != 1 ? "s" : "",
1129 TOMBIT_F (padded));
1130 }
1131 }
1132 break;
1133
1134 case UCON64_STRIP:
1135 ucon64_file_handler (dest_name, src_name, 0);
1136 fcopy (src_name, 0, ucon64.fsize - strtoll (option_arg, NULL, 10),
1137 dest_name, "wb");
1138 printf (ucon64_msg[WROTE], dest_name);
1139 remove_temp_file ();
1140 break;
1141
1142 case UCON64_STP:
1143 ucon64_file_handler (dest_name, src_name, 0);
1144 fcopy (src_name, 512, ucon64.fsize, dest_name, "wb");
1145 printf (ucon64_msg[WROTE], dest_name);
1146 remove_temp_file ();
1147 break;
1148
1149 case UCON64_STPN:
1150 ucon64_file_handler (dest_name, src_name, 0);
1151 fcopy (src_name, strtoll (option_arg, NULL, 10), ucon64.fsize,
1152 dest_name, "wb");
1153 printf (ucon64_msg[WROTE], dest_name);
1154 remove_temp_file ();
1155 break;
1156
1157 case UCON64_INS:
1158 ucon64_file_handler (dest_name, src_name, 0);
1159 memset (buf, 0, 512);
1160 ucon64_fwrite (buf, 0, 512, dest_name, "wb");
1161 fcopy (src_name, 0, ucon64.fsize, dest_name, "ab");
1162 printf (ucon64_msg[WROTE], dest_name);
1163 remove_temp_file ();
1164 break;
1165
1166 case UCON64_INSN:
1167 ucon64_file_handler (dest_name, src_name, 0);
1168 {
1169 FILE *file;
1170 uint64_t bytesleft = strtoll (option_arg, NULL, 10);
1171
1172 if ((file = fopen (dest_name, "wb")) == NULL)
1173 {
1174 fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], dest_name);
1175 break;
1176 }
1177 memset (buf, 0, (size_t) MIN (bytesleft, MAXBUFSIZE));
1178 while (bytesleft > 0)
1179 bytesleft -= fwrite (buf, 1, (size_t) MIN (bytesleft, MAXBUFSIZE), file);
1180 fclose (file);
1181 }
1182 fcopy (src_name, 0, ucon64.fsize, dest_name, "ab");
1183 printf (ucon64_msg[WROTE], dest_name);
1184 remove_temp_file ();
1185 break;
1186
1187 case UCON64_SPLIT:
1188 ucon64_split (strtoll (option_arg, NULL, 10));
1189 break;
1190
1191 case UCON64_A:
1192 aps_apply (ucon64.fname, ucon64.file);
1193 break;
1194
1195 case UCON64_B:
1196 bsl_apply (ucon64.fname, ucon64.file);
1197 break;
1198
1199 case UCON64_I:
1200 ips_apply (ucon64.fname, ucon64.file);
1201 break;
1202
1203 case UCON64_PPF:
1204 ppf_apply (ucon64.fname, ucon64.file);
1205 break;
1206
1207 case UCON64_MKA:
1208 aps_create (option_arg, ucon64.fname); // original, modified
1209 break;
1210
1211 case UCON64_MKI:
1212 ips_create (option_arg, ucon64.fname); // original, modified
1213 break;
1214
1215 case UCON64_MKPPF:
1216 ppf_create (option_arg, ucon64.fname); // original, modified
1217 break;
1218
1219 case UCON64_NA:
1220 aps_set_desc (ucon64.fname, option_arg);
1221 break;
1222
1223 case UCON64_NPPF:
1224 ppf_set_desc (ucon64.fname, option_arg);
1225 break;
1226
1227 case UCON64_IDPPF:
1228 ppf_set_fid (ucon64.fname, option_arg);
1229 break;
1230
1231 case UCON64_SCAN:
1232 case UCON64_LSD:
1233 if (ucon64.dat_enabled)
1234 {
1235 if (ucon64.crc32)
1236 {
1237 fputs (ucon64.fname, stdout);
1238 if (ucon64.fname_arch[0])
1239 printf (" (%s)\n", ucon64.fname_arch);
1240 else
1241 fputc ('\n', stdout);
1242 // use ucon64.fcrc32 for SNES & Genesis interleaved/N64 non-interleaved
1243 printf ("Checksum (CRC32): 0x%08x\n", ucon64.fcrc32 ?
1244 ucon64.fcrc32 : ucon64.crc32);
1245 ucon64_dat_nfo ((st_ucon64_dat_t *) ucon64.dat, 1);
1246 }
1247 }
1248 else
1249 fputs (ucon64_msg[DAT_NOT_ENABLED], stdout);
1250 break;
1251
1252 case UCON64_LSV:
1253 if (ucon64.nfo)
1254 ucon64_nfo ();
1255 break;
1256
1257 case UCON64_LS:
1258 ucon64.newline_before_rom = 0;
1259
1260 if (ucon64.nfo)
1261 ptr = ucon64.nfo->name;
1262
1263 if (ucon64.dat)
1264 {
1265 if (!ptr)
1266 ptr = ((st_ucon64_dat_t *) ucon64.dat)->name;
1267 else if (!ptr[0])
1268 ptr = ((st_ucon64_dat_t *) ucon64.dat)->name;
1269 }
1270
1271 if (ptr && ptr[0])
1272 {
1273 struct stat fstate;
1274
1275 if (stat (ucon64.fname, &fstate))
1276 break;
1277 strftime (buf, 13, "%b %d %Y", localtime (&fstate.st_mtime));
1278 printf ("%-31.31s %10u %s %s", tofunc (ptr, strlen (ptr), ls_toprint),
1279 (unsigned int) ucon64.fsize, buf, basename2 (ucon64.fname));
1280 if (ucon64.fname_arch[0])
1281 printf (" (%s)\n", ucon64.fname_arch);
1282 else
1283 fputc ('\n', stdout);
1284 }
1285 break;
1286
1287 case UCON64_RDAT:
1288 ucon64.newline_before_rom = 0;
1289 ucon64_rename (UCON64_RDAT);
1290 break;
1291
1292 case UCON64_RROM:
1293 ucon64.newline_before_rom = 0;
1294 ucon64_rename (UCON64_RROM);
1295 break;
1296
1297 case UCON64_R83:
1298 ucon64.newline_before_rom = 0;
1299 ucon64_rename (UCON64_R83);
1300 break;
1301
1302 case UCON64_RJOLIET:
1303 ucon64.newline_before_rom = 0;
1304 ucon64_rename (UCON64_RJOLIET);
1305 break;
1306
1307 case UCON64_RL:
1308 ucon64.newline_before_rom = 0;
1309 ucon64_rename (UCON64_RL);
1310 break;
1311
1312 case UCON64_RU:
1313 ucon64.newline_before_rom = 0;
1314 ucon64_rename (UCON64_RU);
1315 break;
1316
1317 #ifdef USE_DISCMAGE
1318 case UCON64_BIN2ISO:
1319 case UCON64_ISOFIX:
1320 case UCON64_RIP:
1321 case UCON64_CDMAGE:
1322 if (ucon64.discmage_enabled)
1323 {
1324 uint32_t flags = 0;
1325
1326 switch (p->option)
1327 {
1328 case UCON64_BIN2ISO:
1329 flags |= DM_2048; // DM_2048 read sectors and convert to 2048 Bytes
1330 break;
1331
1332 case UCON64_ISOFIX:
1333 flags |= DM_FIX; // DM_FIX read sectors and fix (if needed/possible)
1334 break;
1335
1336 case UCON64_CDMAGE:
1337 // flags |= DM_CDMAGE;
1338 break;
1339 }
1340
1341 ucon64.image = dm_reopen (ucon64.fname, 0, (dm_image_t *) ucon64.image);
1342 if (ucon64.image)
1343 {
1344 int track = strtol (option_arg, NULL, 10);
1345 if (track < 1)
1346 track = 1;
1347 track--; // decrement for dm_rip()
1348
1349 printf ("Writing track: %d\n\n", track + 1);
1350
1351 dm_set_gauge (&discmage_gauge);
1352 dm_rip ((dm_image_t *) ucon64.image, track, flags);
1353 fputc ('\n', stdout);
1354 }
1355 }
1356 else
1357 printf (ucon64_msg[NO_LIB], ucon64.discmage_path);
1358 break;
1359
1360 case UCON64_MKTOC:
1361 case UCON64_MKCUE:
1362 case UCON64_MKSHEET:
1363 if (ucon64.discmage_enabled && ucon64.image)
1364 {
1365 char fname[FILENAME_MAX];
1366 strcpy (fname, ((dm_image_t *) ucon64.image)->fname);
1367
1368 if (p->option == UCON64_MKTOC || p->option == UCON64_MKSHEET)
1369 {
1370 set_suffix (fname, ".toc");
1371 ucon64_file_handler (fname, NULL, 0);
1372
1373 if (!dm_toc_write ((dm_image_t *) ucon64.image))
1374 printf (ucon64_msg[WROTE], basename2 (fname));
1375 else
1376 fputs ("ERROR: Could not generate toc sheet\n", stderr);
1377 }
1378
1379 if (p->option == UCON64_MKCUE || p->option == UCON64_MKSHEET)
1380 {
1381 set_suffix (fname, ".cue");
1382 ucon64_file_handler (fname, NULL, 0);
1383
1384 if (!dm_cue_write ((dm_image_t *) ucon64.image))
1385 printf (ucon64_msg[WROTE], basename2 (fname));
1386 else
1387 fputs ("ERROR: Could not generate cue sheet\n", stderr);
1388 }
1389 }
1390 else
1391 printf (ucon64_msg[NO_LIB], ucon64.discmage_path);
1392 break;
1393
1394 case UCON64_XCDRW:
1395 if (ucon64.discmage_enabled)
1396 {
1397 // dm_set_gauge (&discmage_gauge);
1398 if (!access (ucon64.fname, F_OK))
1399 dm_disc_write ((dm_image_t *) ucon64.image);
1400 else
1401 dm_disc_read ((dm_image_t *) ucon64.image);
1402 }
1403 else
1404 printf (ucon64_msg[NO_LIB], ucon64.discmage_path);
1405 break;
1406 #endif // USE_DISCMAGE
1407
1408 case UCON64_DB:
1409 if (ucon64.quiet > -1)
1410 {
1411 if (ucon64.dat_enabled)
1412 {
1413 ucon64_dat_view (ucon64.console, 0);
1414 printf ("TIP: %s " OPTION_LONG_S "db " OPTION_LONG_S "nes"
1415 " would show only information about known NES ROMs\n",
1416 basename2 (ucon64.argv[0]));
1417 }
1418 else
1419 fputs (ucon64_msg[DAT_NOT_ENABLED], stdout);
1420 break;
1421 }
1422
1423 case UCON64_DBV:
1424 if (ucon64.dat_enabled)
1425 {
1426 ucon64_dat_view (ucon64.console, 1);
1427 printf ("TIP: %s " OPTION_LONG_S "dbv " OPTION_LONG_S "nes"
1428 " would show only information about known NES ROMs\n",
1429 basename2 (ucon64.argv[0]));
1430 }
1431 else
1432 fputs (ucon64_msg[DAT_NOT_ENABLED], stdout);
1433 break;
1434
1435 case UCON64_DBS:
1436 if (ucon64.dat_enabled)
1437 {
1438 ucon64.crc32 = 0;
1439 sscanf (option_arg, "%x", &ucon64.crc32);
1440
1441 if ((ucon64.dat = ucon64_dat_search (ucon64.crc32)) == NULL)
1442 {
1443 printf (ucon64_msg[DAT_NOT_FOUND], ucon64.crc32);
1444 printf ("TIP: Be sure to install the right DAT files in %s\n",
1445 ucon64.datdir);
1446 }
1447 else
1448 {
1449 ucon64_dat_nfo ((st_ucon64_dat_t *) ucon64.dat, 1);
1450 printf ("\n"
1451 "TIP: %s " OPTION_LONG_S "dbs" OPTARG_S "0x%08x " OPTION_LONG_S
1452 "nes would search only for a NES ROM\n",
1453 basename2 (ucon64.argv[0]), ucon64.crc32);
1454 }
1455 }
1456 else
1457 fputs (ucon64_msg[DAT_NOT_ENABLED], stdout);
1458 break;
1459
1460 case UCON64_MKDAT:
1461 ucon64.newline_before_rom = 0;
1462 ucon64_create_dat (option_arg, ucon64.fname,
1463 ucon64.nfo ? ucon64.nfo->backup_header_len : 0);
1464 break;
1465
1466 case UCON64_MULTI:
1467 switch (ucon64.console)
1468 {
1469 case UCON64_GBA:
1470 gba_multi (strtol (option_arg, NULL, 10) * MBIT, NULL);
1471 break;
1472 case UCON64_GEN:
1473 genesis_multi (strtol (option_arg, NULL, 10) * MBIT);
1474 break;
1475 case UCON64_PCE:
1476 pce_multi (strtol (option_arg, NULL, 10) * MBIT);
1477 break;
1478 case UCON64_SMS: // Sega Master System *and* Game Gear
1479 sms_multi (strtol (option_arg, NULL, 10) * MBIT);
1480 break;
1481 case UCON64_SNES:
1482 snes_multi (strtol (option_arg, NULL, 10) * MBIT);
1483 break;
1484 default:
1485 return -1;
1486 }
1487 break;
1488
1489 case UCON64_E:
1490 ucon64_e ();
1491 break;
1492
1493 case UCON64_1991:
1494 genesis_1991 (ucon64.nfo);
1495 break;
1496
1497 case UCON64_B0:
1498 lynx_b0 (ucon64.nfo, option_arg);
1499 break;
1500
1501 case UCON64_B1:
1502 lynx_b1 (ucon64.nfo, option_arg);
1503 break;
1504
1505 case UCON64_BIN:
1506 genesis_bin (ucon64.nfo);
1507 break;
1508
1509 case UCON64_BIOS:
1510 neogeo_bios (option_arg);
1511 break;
1512
1513 case UCON64_BOT:
1514 n64_bot (ucon64.nfo, option_arg);
1515 break;
1516
1517 case UCON64_CHK:
1518 switch (ucon64.console)
1519 {
1520 case UCON64_GB:
1521 gb_chk (ucon64.nfo);
1522 break;
1523 case UCON64_GBA:
1524 gba_chk (ucon64.nfo);
1525 break;
1526 case UCON64_GEN:
1527 genesis_chk (ucon64.nfo);
1528 break;
1529 case UCON64_N64:
1530 n64_chk (ucon64.nfo);
1531 break;
1532 case UCON64_SMS:
1533 sms_chk (ucon64.nfo);
1534 break;
1535 case UCON64_SNES:
1536 snes_chk (ucon64.nfo);
1537 break;
1538 case UCON64_SWAN:
1539 swan_chk (ucon64.nfo);
1540 break;
1541 case UCON64_NDS:
1542 nds_chk (ucon64.nfo);
1543 break;
1544 default:
1545 // the next msg has already been printed
1546 // fputs (ucon64_msg[CONSOLE_ERROR], stderr);
1547 return -1;
1548 }
1549 break;
1550
1551 case UCON64_COL:
1552 snes_col (option_arg);
1553 break;
1554
1555 case UCON64_CRP:
1556 gba_crp (ucon64.nfo, option_arg);
1557 break;
1558
1559 case UCON64_DBUH:
1560 snes_backup_header_info (ucon64.nfo);
1561 break;
1562
1563 case UCON64_SWAP:
1564 case UCON64_DINT:
1565 switch (ucon64.console)
1566 {
1567 case UCON64_NES:
1568 nes_dint ();
1569 break;
1570 case UCON64_PCE:
1571 pce_swap (ucon64.nfo);
1572 break;
1573 case UCON64_SNES:
1574 snes_dint (ucon64.nfo);
1575 break;
1576 default: // Nintendo 64
1577 puts ("Converting file...");
1578 ucon64_file_handler (dest_name, NULL, 0);
1579 fcopy (src_name, 0, ucon64.fsize, dest_name, "wb");
1580 ucon64_fbswap16 (dest_name, 0, ucon64.fsize);
1581 printf (ucon64_msg[WROTE], dest_name);
1582 break;
1583 }
1584 break;
1585
1586 case UCON64_SWAP2:
1587 // --swap2 is currently used only for Nintendo 64
1588 puts ("Converting file...");
1589 ucon64_file_handler (dest_name, NULL, 0);
1590 fcopy (src_name, 0, ucon64.fsize, dest_name, "wb");
1591 ucon64_fwswap32 (dest_name, 0, ucon64.fsize);
1592 printf (ucon64_msg[WROTE], dest_name);
1593 break;
1594
1595 case UCON64_DMIRR:
1596 snes_demirror (ucon64.nfo);
1597 break;
1598
1599 case UCON64_DNSRT:
1600 snes_densrt (ucon64.nfo);
1601 break;
1602
1603 case UCON64_F:
1604 switch (ucon64.console)
1605 {
1606 case UCON64_GEN:
1607 genesis_f (ucon64.nfo);
1608 break;
1609 case UCON64_N64:
1610 n64_f (ucon64.nfo);
1611 break;
1612 case UCON64_PCE:
1613 pce_f (ucon64.nfo);
1614 break;
1615 case UCON64_SNES:
1616 snes_f (ucon64.nfo);
1617 break;
1618 default:
1619 // the next msg has already been printed
1620 // fputs (ucon64_msg[CONSOLE_ERROR], stderr);
1621 return -1;
1622 }
1623 break;
1624
1625 case UCON64_FDS:
1626 nes_fds ();
1627 break;
1628
1629 case UCON64_FDSL:
1630 nes_fdsl (ucon64.nfo, NULL);
1631 break;
1632
1633 case UCON64_FFE:
1634 nes_ffe (ucon64.nfo);
1635 break;
1636
1637 case UCON64_FIG:
1638 snes_fig (ucon64.nfo);
1639 break;
1640
1641 case UCON64_FIGS:
1642 snes_figs (ucon64.nfo);
1643 break;
1644
1645 case UCON64_GBX:
1646 gb_gbx (ucon64.nfo);
1647 break;
1648
1649 case UCON64_GD3:
1650 snes_gd3 (ucon64.nfo);
1651 break;
1652
1653 case UCON64_GD3S:
1654 snes_gd3s (ucon64.nfo);
1655 break;
1656
1657 case UCON64_GG:
1658 switch (ucon64.console)
1659 {
1660 case UCON64_GB:
1661 case UCON64_GEN:
1662 case UCON64_NES:
1663 case UCON64_SMS:
1664 case UCON64_SNES:
1665 // ROM images for SNES (GD3) and Genesis (SMD) can be interleaved
1666 if (ucon64.nfo->interleaved)
1667 fputs ("ERROR: This ROM seems to be interleaved, but uCON64 will only apply a Game\n"
1668 " Genie patch to non-interleaved ROMs. Convert to a non-interleaved\n"
1669 " format\n", stderr);
1670 else if (ucon64.console == UCON64_NES &&
1671 nes_get_file_type () != INES && nes_get_file_type () != FFE)
1672 fputs ("ERROR: This NES ROM is in a format that uCON64 cannot apply a Game Genie patch\n"
1673 " to. Convert to iNES\n", stderr);
1674 else
1675 gg_apply (ucon64.nfo, option_arg);
1676 break;
1677 default:
1678 fputs ("ERROR: Cannot apply Game Genie code for this ROM/console\n", stderr);
1679 // the next msg has already been printed
1680 // fputs (ucon64_msg[CONSOLE_ERROR], stderr);
1681 return -1;
1682 }
1683 break;
1684
1685 case UCON64_GGD:
1686 gg_display (ucon64.nfo, option_arg);
1687 break;
1688
1689 case UCON64_GGE:
1690 gg_display (ucon64.nfo, option_arg);
1691 break;
1692
1693 case UCON64_GP2BMP:
1694 gb_gp2bmp ();
1695 break;
1696
1697 case UCON64_IC2:
1698 snes_ic2 (ucon64.nfo);
1699 break;
1700
1701 case UCON64_INES:
1702 nes_ines ();
1703 break;
1704
1705 case UCON64_INESHD:
1706 nes_ineshd (ucon64.nfo);
1707 break;
1708
1709 case UCON64_PARSE:
1710 dc_parse (option_arg);
1711 break;
1712
1713 case UCON64_MKIP:
1714 dc_mkip ();
1715 break;
1716
1717 case UCON64_J:
1718 switch (ucon64.console)
1719 {
1720 case UCON64_GEN:
1721 genesis_j (ucon64.nfo);
1722 break;
1723 case UCON64_NES:
1724 nes_j (NULL);
1725 break;
1726 case UCON64_SNES:
1727 snes_j (ucon64.nfo);
1728 break;
1729 default:
1730 // the next msg has already been printed
1731 // fputs (ucon64_msg[CONSOLE_ERROR], stderr);
1732 return -1;
1733 }
1734 break;
1735
1736 case UCON64_K:
1737 snes_k (ucon64.nfo);
1738 break;
1739
1740 case UCON64_L:
1741 snes_l (ucon64.nfo);
1742 break;
1743
1744 case UCON64_LNX:
1745 lynx_lnx (ucon64.nfo);
1746 break;
1747
1748 case UCON64_LOGO:
1749 switch (ucon64.console)
1750 {
1751 case UCON64_GB:
1752 gb_logo (ucon64.nfo);
1753 break;
1754 case UCON64_GBA:
1755 gba_logo (ucon64.nfo);
1756 break;
1757 case UCON64_NDS:
1758 nds_logo (ucon64.nfo);
1759 break;
1760 default:
1761 // the next msg has already been printed
1762 // fputs (ucon64_msg[CONSOLE_ERROR], stderr);
1763 return -1;
1764 }
1765 break;
1766
1767 case UCON64_LSRAM:
1768 n64_sram (ucon64.nfo, option_arg);
1769 break;
1770
1771 case UCON64_LYX:
1772 lynx_lyx (ucon64.nfo);
1773 break;
1774
1775 case UCON64_MGD:
1776 switch (ucon64.console)
1777 {
1778 case UCON64_GB:
1779 gb_mgd (ucon64.nfo);
1780 break;
1781 case UCON64_GEN:
1782 genesis_mgd (ucon64.nfo);
1783 break;
1784 case UCON64_NG:
1785 neogeo_mgd ();
1786 break;
1787 case UCON64_PCE:
1788 pce_mgd (ucon64.nfo);
1789 break;
1790 case UCON64_SMS:
1791 sms_mgd (ucon64.nfo, UCON64_SMS);
1792 break;
1793 case UCON64_SNES:
1794 snes_mgd (ucon64.nfo);
1795 break;
1796 default:
1797 // the next msg has already been printed
1798 // fputs (ucon64_msg[CONSOLE_ERROR], stderr);
1799 return -1;
1800 }
1801 break;
1802
1803 case UCON64_MGDGG:
1804 sms_mgd (ucon64.nfo, UCON64_GAMEGEAR);
1805 break;
1806
1807 case UCON64_MGH:
1808 switch (ucon64.console)
1809 {
1810 case UCON64_GEN:
1811 genesis_mgh (ucon64.nfo);
1812 break;
1813 case UCON64_SNES:
1814 snes_mgh (ucon64.nfo);
1815 break;
1816 default:
1817 // the next msg has already been printed
1818 // fputs (ucon64_msg[CONSOLE_ERROR], stderr);
1819 return -1;
1820 }
1821 break;
1822
1823 case UCON64_MKSRM:
1824 snes_create_sram ();
1825 break;
1826
1827 case UCON64_MSG:
1828 pce_msg (ucon64.nfo);
1829 break;
1830
1831 case UCON64_N:
1832 switch (ucon64.console)
1833 {
1834 case UCON64_GB:
1835 gb_n (ucon64.nfo, option_arg);
1836 break;
1837 case UCON64_GBA:
1838 gba_n (ucon64.nfo, option_arg);
1839 break;
1840 case UCON64_GEN:
1841 genesis_n (ucon64.nfo, option_arg);
1842 break;
1843 case UCON64_LYNX:
1844 lynx_n (ucon64.nfo, option_arg);
1845 break;
1846 case UCON64_N64:
1847 n64_n (ucon64.nfo, option_arg);
1848 break;
1849 case UCON64_NES:
1850 nes_n (option_arg);
1851 break;
1852 case UCON64_SNES:
1853 snes_n (ucon64.nfo, option_arg);
1854 break;
1855 case UCON64_NDS:
1856 nds_n (ucon64.nfo, option_arg);
1857 break;
1858 default:
1859 // the next msg has already been printed
1860 // fputs (ucon64_msg[CONSOLE_ERROR], stderr);
1861 return -1;
1862 }
1863 break;
1864
1865 case UCON64_N2:
1866 genesis_n2 (ucon64.nfo, option_arg);
1867 break;
1868
1869 case UCON64_N2GB:
1870 gb_n2gb (ucon64.nfo, option_arg);
1871 break;
1872
1873 case UCON64_NROT:
1874 lynx_nrot (ucon64.nfo);
1875 break;
1876
1877 case UCON64_PASOFAMI:
1878 nes_pasofami ();
1879 break;
1880
1881 case UCON64_PATTERN:
1882 ucon64_pattern (option_arg);
1883 break;
1884
1885 case UCON64_POKE:
1886 {
1887 size_t len = strnlen (option_arg, sizeof buf - 1);
1888 char *token;
1889 uint64_t offset;
1890
1891 strncpy (buf, option_arg, len)[len] = '\0';
1892
1893 token = strtok (buf, ":");
1894 if (!token)
1895 {
1896 fputs ("ERROR: No offset specified. Specify one before a colon\n", stderr);
1897 break;
1898 }
1899 if (strtoint (token, 16, &offset, sizeof offset))
1900 {
1901 fprintf (stderr, "ERROR: Invalid offset: %s\n", token);
1902 break;
1903 }
1904
1905 token = strtok (NULL, "");
1906 if (!token)
1907 {
1908 fputs ("ERROR: No value specified. Specify one after a colon\n", stderr);
1909 break;
1910 }
1911 if (strtoint (token, 16, &value, sizeof value) ||
1912 (unsigned int) value > 255)
1913 {
1914 fprintf (stderr, "ERROR: Invalid value: %s\n", token);
1915 break;
1916 }
1917
1918 if (offset >= ucon64.fsize)
1919 {
1920 fprintf (stderr, "ERROR: Offset 0x%016llx is too large for file size\n",
1921 (long long unsigned int) offset);
1922 break;
1923 }
1924
1925 ucon64_file_handler (dest_name, src_name, 0);
1926 fcopy (src_name, 0, ucon64.fsize, dest_name, "wb");
1927
1928 fputc ('\n', stdout);
1929 buf[0] = (char) ucon64_fgetc (dest_name, offset);
1930 dumper (stdout, buf, 1, offset, DUMPER_HEX);
1931
1932 ucon64_fputc (dest_name, offset, value, "r+b");
1933
1934 buf[0] = (char) value;
1935 dumper (stdout, buf, 1, offset, DUMPER_HEX);
1936 fputc ('\n', stdout);
1937
1938 printf (ucon64_msg[WROTE], dest_name);
1939 remove_temp_file ();
1940 }
1941 break;
1942
1943 case UCON64_ROTL:
1944 lynx_rotl (ucon64.nfo);
1945 break;
1946
1947 case UCON64_ROTR:
1948 lynx_rotr (ucon64.nfo);
1949 break;
1950
1951 case UCON64_S:
1952 switch (ucon64.console)
1953 {
1954 case UCON64_GEN:
1955 genesis_s (ucon64.nfo);
1956 break;
1957 case UCON64_NES:
1958 nes_s ();
1959 break;
1960 case UCON64_NG:
1961 neogeo_s ();
1962 break;
1963 case UCON64_SNES:
1964 snes_s (ucon64.nfo);
1965 break;
1966 default:
1967 // the next msg has already been printed
1968 // fputs (ucon64_msg[CONSOLE_ERROR], stderr);
1969 return -1;
1970 }
1971 break;
1972
1973 case UCON64_SAM:
1974 neogeo_sam (option_arg);
1975 break;
1976
1977 case UCON64_SCR:
1978 dc_scramble ();
1979 break;
1980
1981 case UCON64_SGB:
1982 gb_sgb (ucon64.nfo);
1983 break;
1984
1985 case UCON64_SMC:
1986 snes_smc (ucon64.nfo);
1987 break;
1988
1989 case UCON64_SMD:
1990 switch (ucon64.console)
1991 {
1992 case UCON64_GEN:
1993 genesis_smd (ucon64.nfo);
1994 break;
1995 case UCON64_SMS:
1996 sms_smd (ucon64.nfo);
1997 break;
1998 default:
1999 return -1;
2000 }
2001 break;
2002
2003 case UCON64_SMDS:
2004 switch (ucon64.console)
2005 {
2006 case UCON64_GEN:
2007 genesis_smds ();
2008 break;
2009 case UCON64_SMS:
2010 sms_smds ();
2011 break;
2012 default:
2013 return -1;
2014 }
2015 break;
2016
2017 case UCON64_SMGH:
2018 switch (ucon64.console)
2019 {
2020 case UCON64_GEN:
2021 genesis_smgh (ucon64.nfo);
2022 break;
2023 case UCON64_SNES:
2024 snes_smgh (ucon64.nfo);
2025 break;
2026 default:
2027 // the next msg has already been printed
2028 // fputs (ucon64_msg[CONSOLE_ERROR], stderr);
2029 return -1;
2030 }
2031 break;
2032
2033 case UCON64_SMINI2SRM:
2034 snes_smini2srm ();
2035 break;
2036
2037 #ifdef USE_ZLIB
2038 case UCON64_SMINIS:
2039 snes_sminis (ucon64.nfo, option_arg);
2040 break;
2041 #endif
2042
2043 case UCON64_SRAM:
2044 gba_sram ();
2045 break;
2046
2047 case UCON64_SC:
2048 gba_sc ();
2049 break;
2050
2051 case UCON64_SSC:
2052 gb_ssc (ucon64.nfo);
2053 break;
2054
2055 case UCON64_SWC:
2056 snes_swc (ucon64.nfo);
2057 break;
2058
2059 case UCON64_SWCS:
2060 snes_swcs (ucon64.nfo);
2061 break;
2062
2063 case UCON64_UFO:
2064 snes_ufo (ucon64.nfo);
2065 break;
2066
2067 case UCON64_UFOS:
2068 snes_ufos (ucon64.nfo);
2069 break;
2070
2071 case UCON64_UFOSD:
2072 snes_ufosd (ucon64.nfo);
2073 break;
2074
2075 case UCON64_UFOSDS:
2076 snes_ufosds (ucon64.nfo);
2077 break;
2078
2079 case UCON64_UNIF:
2080 nes_unif ();
2081 break;
2082
2083 case UCON64_UNSCR:
2084 dc_unscramble ();
2085 break;
2086
2087 case UCON64_USMS:
2088 n64_usms (ucon64.nfo, option_arg);
2089 break;
2090
2091 case UCON64_V64:
2092 n64_v64 (ucon64.nfo);
2093 break;
2094
2095 /*
2096 It doesn't make sense to continue after executing a (send) backup option
2097 ("multizip"). Don't return, but use break instead. ucon64_execute_options()
2098 checks if an option was used that should stop uCON64.
2099 */
2100 #ifdef USE_LIBCD64
2101 case UCON64_XCD64:
2102 if (access (ucon64.fname, F_OK) != 0)
2103 cd64_read_rom (ucon64.fname, 64);
2104 else
2105 cd64_write_rom (ucon64.fname);
2106 fputc ('\n', stdout);
2107 break;
2108
2109 case UCON64_XCD64C:
2110 if (!access (ucon64.fname, F_OK) && ucon64.backup)
2111 printf ("Wrote backup to %s\n", mkbak (ucon64.fname, BAK_MOVE));
2112 cd64_read_rom (ucon64.fname, strtol (option_arg, NULL, 10));
2113 fputc ('\n', stdout);
2114 break;
2115
2116 case UCON64_XCD64B:
2117 cd64_write_bootemu (ucon64.fname);
2118 fputc ('\n', stdout);
2119 break;
2120
2121 case UCON64_XCD64S:
2122 if (access (ucon64.fname, F_OK) != 0)
2123 cd64_read_sram (ucon64.fname);
2124 else
2125 cd64_write_sram (ucon64.fname);
2126 fputc ('\n', stdout);
2127 break;
2128
2129 case UCON64_XCD64F:
2130 if (access (ucon64.fname, F_OK) != 0)
2131 cd64_read_flashram (ucon64.fname);
2132 else
2133 cd64_write_flashram (ucon64.fname);
2134 fputc ('\n', stdout);
2135 break;
2136
2137 case UCON64_XCD64E:
2138 if (access (ucon64.fname, F_OK) != 0)
2139 cd64_read_eeprom (ucon64.fname);
2140 else
2141 cd64_write_eeprom (ucon64.fname);
2142 fputc ('\n', stdout);
2143 break;
2144
2145 case UCON64_XCD64M:
2146 if (access (ucon64.fname, F_OK) != 0)
2147 cd64_read_mempack (ucon64.fname, strtol (option_arg, NULL, 10));
2148 else
2149 cd64_write_mempack (ucon64.fname, strtol (option_arg, NULL, 10));
2150 fputc ('\n', stdout);
2151 break;
2152 #endif // USE_LIBCD64
2153
2154 #ifdef USE_PARALLEL
2155 case UCON64_XRESET:
2156 parport_print_info ();
2157 fputs ("Resetting parallel port...", stdout);
2158 outportb (ucon64.parport + PARPORT_DATA, 0);
2159 // Strobe, Auto Linefeed and Select Printer are hardware inverted, so we
2160 // have to write a 1 to bring the associated pins in a low state (0V).
2161 outportb (ucon64.parport + PARPORT_CONTROL,
2162 (inportb (ucon64.parport + PARPORT_CONTROL) & 0xf0) | 0x0b);
2163 puts ("done");
2164 break;
2165
2166 case UCON64_XCMC:
2167 if (!access (ucon64.fname, F_OK) && ucon64.backup)
2168 printf ("Wrote backup to %s\n", mkbak (ucon64.fname, BAK_MOVE));
2169 cmc_read_rom (ucon64.fname, ucon64.parport, ucon64.io_mode); // ucon64.io_mode contains speed value
2170 fputc ('\n', stdout);
2171 break;
2172
2173 case UCON64_XCMCT:
2174 cmc_test (strtol (option_arg, NULL, 10), ucon64.parport, ucon64.io_mode);
2175 fputc ('\n', stdout);
2176 break;
2177
2178 case UCON64_XDJR:
2179 if (access (ucon64.fname, F_OK) != 0)
2180 {
2181 doctor64jr_read (ucon64.fname, ucon64.parport);
2182 fputc ('\n', stdout);
2183 }
2184 else
2185 {
2186 if (!ucon64.nfo->interleaved)
2187 fputs ("ERROR: This ROM does not seem to be interleaved, but the Doctor V64 Junior only\n"
2188 " supports interleaved ROMs. Convert to a Doctor V64 compatible format\n",
2189 stderr);
2190 else
2191 {
2192 doctor64jr_write (ucon64.fname, ucon64.parport);
2193 fputc ('\n', stdout);
2194 }
2195 }
2196 break;
2197
2198 case UCON64_XFAL:
2199 if (access (ucon64.fname, F_OK) != 0)
2200 fal_read_rom (ucon64.fname, ucon64.parport, 32);
2201 else
2202 fal_write_rom (ucon64.fname, ucon64.parport);
2203 fputc ('\n', stdout);
2204 break;
2205
2206 case UCON64_XFALMULTI:
2207 tmpnam2 (src_name, NULL);
2208 ucon64.temp_file = src_name;
2209 register_func (remove_temp_file);
2210 // gba_multi() calls ucon64_file_handler() so the directory part will be
2211 // stripped from src_name. The directory should be used though.
2212 if (!ucon64.output_path[0])
2213 {
2214 dirname2 (src_name, ucon64.output_path);
2215 if (ucon64.output_path[strlen (ucon64.output_path) - 1] != DIR_SEPARATOR)
2216 strcat (ucon64.output_path, DIR_SEPARATOR_S);
2217 }
2218 if (gba_multi (strtol (option_arg, NULL, 10) * MBIT, src_name) == 0)
2219 { // don't try to start a transfer if there was a problem
2220 fputc ('\n', stdout);
2221 ucon64.fsize = fsizeof (src_name);
2222 fal_write_rom (src_name, ucon64.parport);
2223 }
2224
2225 unregister_func (remove_temp_file);
2226 remove_temp_file ();
2227 fputc ('\n', stdout);
2228 break;
2229
2230 case UCON64_XFALC:
2231 if (!access (ucon64.fname, F_OK) && ucon64.backup)
2232 printf ("Wrote backup to %s\n", mkbak (ucon64.fname, BAK_MOVE));
2233 fal_read_rom (ucon64.fname, ucon64.parport,
2234 strtol (option_arg, NULL, 10));
2235 fputc ('\n', stdout);
2236 break;
2237
2238 case UCON64_XFALS:
2239 if (access (ucon64.fname, F_OK) != 0)
2240 fal_read_sram (ucon64.fname, ucon64.parport, UCON64_UNKNOWN);
2241 else
2242 fal_write_sram (ucon64.fname, ucon64.parport, UCON64_UNKNOWN);
2243 fputc ('\n', stdout);
2244 break;
2245
2246 case UCON64_XFALB:
2247 if (access (ucon64.fname, F_OK) != 0)
2248 fal_read_sram (ucon64.fname, ucon64.parport,
2249 strtol (option_arg, NULL, 10));
2250 else
2251 fal_write_sram (ucon64.fname, ucon64.parport,
2252 strtol (option_arg, NULL, 10));
2253 fputc ('\n', stdout);
2254 break;
2255
2256 case UCON64_XFIG:
2257 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump cartridge
2258 {
2259 fig_read_rom (ucon64.fname, ucon64.parport);
2260 fputc ('\n', stdout);
2261 }
2262 else
2263 {
2264 if (!ucon64.nfo->backup_header_len)
2265 fputs ("ERROR: This ROM has no header. Convert to a FIG compatible format\n",
2266 stderr);
2267 else if (ucon64.nfo->interleaved)
2268 fputs ("ERROR: This ROM seems to be interleaved, but the FIG does not support\n"
2269 " interleaved ROMs. Convert to a FIG compatible format\n",
2270 stderr);
2271 else // file exists => send it to the copier
2272 {
2273 fig_write_rom (ucon64.fname, ucon64.parport);
2274 fputc ('\n', stdout);
2275 }
2276 }
2277 break;
2278
2279 case UCON64_XFIGS:
2280 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump SRAM contents
2281 fig_read_sram (ucon64.fname, ucon64.parport);
2282 else // file exists => restore SRAM
2283 fig_write_sram (ucon64.fname, ucon64.parport);
2284 fputc ('\n', stdout);
2285 break;
2286
2287 case UCON64_XFIGC:
2288 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump cart SRAM contents
2289 fig_read_cart_sram (ucon64.fname, ucon64.parport);
2290 else // file exists => restore SRAM
2291 fig_write_cart_sram (ucon64.fname, ucon64.parport);
2292 fputc ('\n', stdout);
2293 break;
2294
2295 case UCON64_XGBX:
2296 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump cartridge/flash card
2297 gbx_read_rom (ucon64.fname, ucon64.parport);
2298 else // file exists => send it to the programmer
2299 gbx_write_rom (ucon64.fname, ucon64.parport);
2300 fputc ('\n', stdout);
2301 break;
2302
2303 case UCON64_XGBXS:
2304 if (access (ucon64.fname, F_OK) != 0)
2305 gbx_read_sram (ucon64.fname, ucon64.parport, -1);
2306 else
2307 gbx_write_sram (ucon64.fname, ucon64.parport, -1);
2308 fputc ('\n', stdout);
2309 break;
2310
2311 case UCON64_XGBXB:
2312 if (access (ucon64.fname, F_OK) != 0)
2313 gbx_read_sram (ucon64.fname, ucon64.parport,
2314 strtol (option_arg, NULL, 10));
2315 else
2316 gbx_write_sram (ucon64.fname, ucon64.parport,
2317 strtol (option_arg, NULL, 10));
2318 fputc ('\n', stdout);
2319 break;
2320
2321 case UCON64_XGD3:
2322 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump cartridge
2323 {
2324 gd3_read_rom (ucon64.fname, ucon64.parport); // dumping is not yet supported
2325 fputc ('\n', stdout);
2326 }
2327 else
2328 {
2329 if (!ucon64.nfo->backup_header_len)
2330 fputs ("ERROR: This ROM has no header. Convert to a Game Doctor compatible format\n",
2331 stderr);
2332 else // file exists => send it to the copier
2333 {
2334 gd3_write_rom (ucon64.fname, ucon64.parport, ucon64.nfo);
2335 fputc ('\n', stdout);
2336 }
2337 }
2338 break;
2339
2340 case UCON64_XGD3S:
2341 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump SRAM contents
2342 gd3_read_sram (ucon64.fname, ucon64.parport); // dumping is not yet supported
2343 else // file exists => restore SRAM
2344 gd3_write_sram (ucon64.fname, ucon64.parport);
2345 fputc ('\n', stdout);
2346 break;
2347
2348 case UCON64_XGD3R:
2349 if (access (ucon64.fname, F_OK) != 0)
2350 gd3_read_saver (ucon64.fname, ucon64.parport);
2351 else
2352 gd3_write_saver (ucon64.fname, ucon64.parport);
2353 fputc ('\n', stdout);
2354 break;
2355
2356 case UCON64_XGD6:
2357 if (access (ucon64.fname, F_OK) != 0)
2358 {
2359 gd6_read_rom (ucon64.fname, ucon64.parport);
2360 fputc ('\n', stdout);
2361 }
2362 else
2363 {
2364 if (!ucon64.nfo->backup_header_len)
2365 fputs ("ERROR: This ROM has no header. Convert to a Game Doctor compatible format\n",
2366 stderr);
2367 else
2368 {
2369 gd6_write_rom (ucon64.fname, ucon64.parport, ucon64.nfo);
2370 fputc ('\n', stdout);
2371 }
2372 }
2373 break;
2374
2375 case UCON64_XGD6S:
2376 if (access (ucon64.fname, F_OK) != 0)
2377 gd6_read_sram (ucon64.fname, ucon64.parport);
2378 else
2379 gd6_write_sram (ucon64.fname, ucon64.parport);
2380 fputc ('\n', stdout);
2381 break;
2382
2383 case UCON64_XGD6R:
2384 if (access (ucon64.fname, F_OK) != 0)
2385 gd6_read_saver (ucon64.fname, ucon64.parport);
2386 else
2387 gd6_write_saver (ucon64.fname, ucon64.parport);
2388 fputc ('\n', stdout);
2389 break;
2390
2391 case UCON64_XGG:
2392 if (access (ucon64.fname, F_OK) != 0)
2393 {
2394 smsgg_read_rom (ucon64.fname, ucon64.parport, 32 * MBIT);
2395 fputc ('\n', stdout);
2396 }
2397 else
2398 {
2399 if (ucon64.nfo->backup_header_len)
2400 fputs ("ERROR: This ROM has a header. Remove it with " OPTION_LONG_S "stp or " OPTION_LONG_S "mgd\n",
2401 stderr);
2402 else if (ucon64.nfo->interleaved)
2403 fputs ("ERROR: This ROM seems to be interleaved, but uCON64 does not support\n"
2404 " sending interleaved ROMs to the SMS-PRO/GG-PRO. Convert ROM with " OPTION_LONG_S "mgd\n",
2405 stderr);
2406 else
2407 {
2408 smsgg_write_rom (ucon64.fname, ucon64.parport);
2409 fputc ('\n', stdout);
2410 }
2411 }
2412 break;
2413
2414 case UCON64_XGGS:
2415 if (access (ucon64.fname, F_OK) != 0)
2416 smsgg_read_sram (ucon64.fname, ucon64.parport, -1);
2417 else
2418 smsgg_write_sram (ucon64.fname, ucon64.parport, -1);
2419 fputc ('\n', stdout);
2420 break;
2421
2422 case UCON64_XGGB:
2423 if (access (ucon64.fname, F_OK) != 0)
2424 smsgg_read_sram (ucon64.fname, ucon64.parport,
2425 strtol (option_arg, NULL, 10));
2426 else
2427 smsgg_write_sram (ucon64.fname, ucon64.parport,
2428 strtol (option_arg, NULL, 10));
2429 fputc ('\n', stdout);
2430 break;
2431
2432 case UCON64_XIC2:
2433 smcic2_write_rom (ucon64.fname, ucon64.parport);
2434 fputc ('\n', stdout);
2435 break;
2436
2437 case UCON64_XLIT:
2438 if (!access (ucon64.fname, F_OK) && ucon64.backup)
2439 printf ("Wrote backup to %s\n", mkbak (ucon64.fname, BAK_MOVE));
2440 lynxit_read_rom (ucon64.fname, ucon64.parport);
2441 break;
2442
2443 case UCON64_XMCCL:
2444 if (!access (ucon64.fname, F_OK) && ucon64.backup)
2445 printf ("Wrote backup to %s\n", mkbak (ucon64.fname, BAK_MOVE));
2446 mccl_read (ucon64.fname, ucon64.parport);
2447 break;
2448
2449 case UCON64_XMCD:
2450 if (!access (ucon64.fname, F_OK) && ucon64.backup)
2451 printf ("Wrote backup to %s\n", mkbak (ucon64.fname, BAK_MOVE));
2452 mcd_read_rom (ucon64.fname, ucon64.parport);
2453 fputc ('\n', stdout);
2454 break;
2455
2456 case UCON64_XMD:
2457 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump flash card
2458 {
2459 md_read_rom (ucon64.fname, ucon64.parport, 64 * MBIT); // reads 32 Mbit if Sharp card
2460 fputc ('\n', stdout);
2461 }
2462 else // file exists => send it to the MD-PRO
2463 {
2464 if (ucon64.nfo->backup_header_len) // binary with header is possible
2465 fputs ("ERROR: This ROM has a header. Remove it with " OPTION_LONG_S "stp or " OPTION_LONG_S "bin\n",
2466 stderr);
2467 else if (genesis_get_copier_type () != BIN)
2468 fputs ("ERROR: This ROM is not in binary/BIN/RAW format. uCON64 only supports sending\n"
2469 " binary files to the MD-PRO. Convert ROM with " OPTION_LONG_S "bin\n",
2470 stderr);
2471 else
2472 {
2473 md_write_rom (ucon64.fname, ucon64.parport);
2474 fputc ('\n', stdout);
2475 }
2476 }
2477 break;
2478
2479 case UCON64_XMDS:
2480 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump SRAM contents
2481 md_read_sram (ucon64.fname, ucon64.parport, -1);
2482 else // file exists => restore SRAM
2483 md_write_sram (ucon64.fname, ucon64.parport, -1);
2484 fputc ('\n', stdout);
2485 break;
2486
2487 case UCON64_XMDB:
2488 if (access (ucon64.fname, F_OK) != 0)
2489 md_read_sram (ucon64.fname, ucon64.parport,
2490 strtol (option_arg, NULL, 10));
2491 else
2492 md_write_sram (ucon64.fname, ucon64.parport,
2493 strtol (option_arg, NULL, 10));
2494 fputc ('\n', stdout);
2495 break;
2496
2497 case UCON64_XMSG:
2498 if (access (ucon64.fname, F_OK) != 0)
2499 {
2500 msg_read_rom (ucon64.fname, ucon64.parport);
2501 fputc ('\n', stdout);
2502 }
2503 else
2504 {
2505 if (!ucon64.nfo->backup_header_len)
2506 fputs ("ERROR: This ROM has no header. Convert to an MSG compatible format\n",
2507 stderr);
2508 else if (ucon64.nfo->interleaved)
2509 fputs ("ERROR: This ROM seems to be bit-swapped, but the MSG does not support\n"
2510 " bit-swapped ROMs. Convert to an MSG compatible format\n",
2511 stderr);
2512 else
2513 {
2514 msg_write_rom (ucon64.fname, ucon64.parport);
2515 fputc ('\n', stdout);
2516 }
2517 }
2518 break;
2519
2520 case UCON64_XPCE:
2521 if (access (ucon64.fname, F_OK) != 0)
2522 pce_read_rom (ucon64.fname, ucon64.parport, 32 * MBIT);
2523 else
2524 pce_write_rom (ucon64.fname, ucon64.parport);
2525 fputc ('\n', stdout);
2526 break;
2527
2528 case UCON64_XPL:
2529 if (access (ucon64.fname, F_OK) != 0)
2530 pl_read_rom (ucon64.fname, ucon64.parport);
2531 else
2532 pl_write_rom (ucon64.fname, ucon64.parport);
2533 fputc ('\n', stdout);
2534 break;
2535
2536 case UCON64_XPLI:
2537 pl_info (ucon64.parport);
2538 fputc ('\n', stdout);
2539 break;
2540
2541 case UCON64_XSF:
2542 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump flash card
2543 sf_read_rom (ucon64.fname, ucon64.parport, 64 * MBIT);
2544 else // file exists => send it to the Super Flash
2545 sf_write_rom (ucon64.fname, ucon64.parport);
2546 fputc ('\n', stdout);
2547 break;
2548
2549 case UCON64_XSFS:
2550 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump SRAM contents
2551 sf_read_sram (ucon64.fname, ucon64.parport);
2552 else // file exists => restore SRAM
2553 sf_write_sram (ucon64.fname, ucon64.parport);
2554 fputc ('\n', stdout);
2555 break;
2556
2557 case UCON64_XSMC: // we don't use WF_NO_ROM => no need to check for file
2558 if (!ucon64.nfo->backup_header_len)
2559 fputs ("ERROR: This ROM has no header. Convert to an SMC compatible format with " OPTION_LONG_S "ffe\n",
2560 stderr);
2561 else
2562 {
2563 smc_write_rom (ucon64.fname, ucon64.parport);
2564 fputc ('\n', stdout);
2565 }
2566 break;
2567
2568 case UCON64_XSMCR:
2569 if (access (ucon64.fname, F_OK) != 0)
2570 smc_read_rts (ucon64.fname, ucon64.parport);
2571 else
2572 smc_write_rts (ucon64.fname, ucon64.parport);
2573 fputc ('\n', stdout);
2574 break;
2575
2576 case UCON64_XSMD:
2577 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump cartridge
2578 {
2579 smd_read_rom (ucon64.fname, ucon64.parport);
2580 fputc ('\n', stdout);
2581 }
2582 else // file exists => send it to the copier
2583 {
2584 if (!ucon64.nfo->backup_header_len)
2585 fputs ("ERROR: This ROM has no header. Convert to an SMD compatible format\n",
2586 stderr);
2587 else if (!ucon64.nfo->interleaved)
2588 fputs ("ERROR: This ROM does not seem to be interleaved, but the SMD only supports\n"
2589 " interleaved ROMs. Convert to an SMD compatible format\n",
2590 stderr);
2591 else
2592 {
2593 smd_write_rom (ucon64.fname, ucon64.parport);
2594 fputc ('\n', stdout);
2595 }
2596 }
2597 break;
2598
2599 case UCON64_XSMDS:
2600 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump SRAM contents
2601 smd_read_sram (ucon64.fname, ucon64.parport);
2602 else // file exists => restore SRAM
2603 smd_write_sram (ucon64.fname, ucon64.parport);
2604 fputc ('\n', stdout);
2605 break;
2606
2607 case UCON64_XSWC:
2608 enableRTS = 0; // falling through
2609 case UCON64_XSWC2:
2610 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump cartridge
2611 {
2612 swc_read_rom (ucon64.fname, ucon64.parport, ucon64.io_mode);
2613 fputc ('\n', stdout);
2614 }
2615 else
2616 {
2617 if (!ucon64.nfo->backup_header_len)
2618 fputs ("ERROR: This ROM has no header. Convert to an SWC compatible format\n",
2619 stderr);
2620 else if (ucon64.nfo->interleaved)
2621 fputs ("ERROR: This ROM seems to be interleaved, but the SWC does not support\n"
2622 " interleaved ROMs. Convert to an SWC compatible format\n",
2623 stderr);
2624 else
2625 {
2626 if (enableRTS != 0)
2627 enableRTS = 1;
2628 // file exists => send it to the copier
2629 swc_write_rom (ucon64.fname, ucon64.parport, enableRTS);
2630 fputc ('\n', stdout);
2631 }
2632 }
2633 break;
2634
2635 case UCON64_XSWCS:
2636 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump SRAM contents
2637 swc_read_sram (ucon64.fname, ucon64.parport);
2638 else // file exists => restore SRAM
2639 swc_write_sram (ucon64.fname, ucon64.parport);
2640 fputc ('\n', stdout);
2641 break;
2642
2643 case UCON64_XSWCC:
2644 if (access (ucon64.fname, F_OK) != 0) // file does not exist => dump SRAM contents
2645 swc_read_cart_sram (ucon64.fname, ucon64.parport, ucon64.io_mode);
2646 else // file exists => restore SRAM
2647 swc_write_cart_sram (ucon64.fname, ucon64.parport, ucon64.io_mode);
2648 fputc ('\n', stdout);
2649 break;
2650
2651 case UCON64_XSWCR:
2652 if (access (ucon64.fname, F_OK) != 0)
2653 swc_read_rts (ucon64.fname, ucon64.parport);
2654 else
2655 swc_write_rts (ucon64.fname, ucon64.parport);
2656 fputc ('\n', stdout);
2657 break;
2658
2659 case UCON64_XV64:
2660 if (access (ucon64.fname, F_OK) != 0)
2661 {
2662 doctor64_read (ucon64.fname, ucon64.parport);
2663 fputc ('\n', stdout);
2664 }
2665 else
2666 {
2667 if (!ucon64.nfo->interleaved)
2668 fputs ("ERROR: This ROM does not seem to be interleaved, but the Doctor V64 only\n"
2669 " supports interleaved ROMs. Convert to a Doctor V64 compatible format\n",
2670 stderr);
2671 else
2672 {
2673 doctor64_write (ucon64.fname, ucon64.nfo->backup_header_len,
2674 (int) ucon64.fsize, ucon64.parport);
2675 fputc ('\n', stdout);
2676 }
2677 }
2678 break;
2679 #endif // USE_PARALLEL
2680
2681 #if defined USE_PARALLEL || defined USE_USB
2682 case UCON64_XF2A:
2683 if (access (ucon64.fname, F_OK) != 0)
2684 f2a_read_rom (ucon64.fname, 32);
2685 else
2686 f2a_write_rom (ucon64.fname, UCON64_UNKNOWN);
2687 fputc ('\n', stdout);
2688 break;
2689
2690 case UCON64_XF2AMULTI:
2691 f2a_write_rom (NULL, strtol (option_arg, NULL, 10) * MBIT);
2692 fputc ('\n', stdout);
2693 break;
2694
2695 case UCON64_XF2AC:
2696 if (!access (ucon64.fname, F_OK) && ucon64.backup)
2697 printf ("Wrote backup to %s\n", mkbak (ucon64.fname, BAK_MOVE));
2698 f2a_read_rom (ucon64.fname, strtol (option_arg, NULL, 10));
2699 fputc ('\n', stdout);
2700 break;
2701
2702 case UCON64_XF2AS:
2703 if (access (ucon64.fname, F_OK) != 0)
2704 f2a_read_sram (ucon64.fname, UCON64_UNKNOWN);
2705 else
2706 f2a_write_sram (ucon64.fname, UCON64_UNKNOWN);
2707 fputc ('\n', stdout);
2708 break;
2709
2710 case UCON64_XF2AB:
2711 if (access (ucon64.fname, F_OK) != 0)
2712 f2a_read_sram (ucon64.fname, strtol (option_arg, NULL, 10));
2713 else
2714 f2a_write_sram (ucon64.fname, strtol (option_arg, NULL, 10));
2715 fputc ('\n', stdout);
2716 break;
2717 #endif // USE_PARALLEL || USE_USB
2718
2719 #ifdef USE_USB
2720 case UCON64_XQD16:
2721 if (ucon64.nfo->interleaved)
2722 fputs ("ERROR: This ROM seems to be interleaved, but the Quickdev16 does not support\n"
2723 " interleaved ROMs. Convert to an SWC compatible format\n",
2724 stderr);
2725 else
2726 {
2727 quickdev16_write_rom (ucon64.fname);
2728 fputc ('\n', stdout);
2729 }
2730 break;
2731
2732 case UCON64_XUFOSD:
2733 if (snes_get_copier_type () != UFOSD)
2734 fputs ("ERROR: This ROM is not in Super UFO Pro 8 SD format. Convert with " OPTION_LONG_S "ufosd\n",
2735 stderr);
2736 else if (ucon64.nfo->interleaved)
2737 fputs ("ERROR: This ROM seems to be interleaved, but the Super UFO Pro 8 SD does not\n"
2738 " support interleaved ROMs. Convert with " OPTION_LONG_S "ufosd\n",
2739 stderr);
2740 else
2741 {
2742 ufosd_write_rom (ucon64.fname);
2743 fputc ('\n', stdout);
2744 }
2745 break;
2746 #endif // USE_USB
2747
2748 case UCON64_Z64:
2749 n64_z64 (ucon64.nfo);
2750 break;
2751
2752 default:
2753 break;
2754 }
2755
2756 return 0;
2757 }
2758