fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/utils/pri/main.c *
7 * Created: 2012-01-31 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2012-2025 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include "main.h"
24#include "pri-mac-gcr.h"
25
26#include <stdlib.h>
27#include <stdio.h>
28#include <string.h>
29
30#include <lib/getopt.h>
31#include <lib/sysdep.h>
32
33#include <drivers/psi/psi-img.h>
34#include <drivers/psi/psi.h>
35
36#include <drivers/pri/pri.h>
37#include <drivers/pri/pri-img.h>
38#include <drivers/pri/pri-enc-fm.h>
39#include <drivers/pri/pri-enc-mfm.h>
40
41
42const char *arg0 = NULL;
43
44int par_verbose = 0;
45
46int par_list = 0;
47int par_list_long = 0;
48int par_print_info = 0;
49
50unsigned par_fmt_inp = PRI_FORMAT_NONE;
51unsigned par_fmt_out = PRI_FORMAT_NONE;
52
53char par_invert = 0;
54
55char par_cyl_all = 1;
56unsigned long par_cyl[2];
57
58char par_trk_all = 1;
59unsigned long par_trk[2];
60
61unsigned long par_data_rate = 500000;
62unsigned long par_track_size = 0;
63
64pri_enc_fm_t par_enc_fm;
65
66pri_dec_mfm_t par_dec_mfm;
67pri_enc_mfm_t par_enc_mfm;
68
69unsigned par_mac_align = 0;
70char par_mac_no_slip = 0;
71char par_psi_dec_pos = 0;
72char par_text_align = 1;
73
74
75static pce_option_t opts[] = {
76 { '?', 0, "help", NULL, "Print usage information" },
77 { 'c', 1, "cylinder", "c", "Select cylinders [all]" },
78 { 'e', 2, "edit", "what val", "Edit image and track attributes" },
79 { 'f', 0, "info", NULL, "Print image information [no]" },
80 { 'h', 1, "head", "h", "Select heads [all]" },
81 { 'i', 1, "input", "filename", "Load an input file" },
82 { 'I', 1, "input-format", "format", "Set the input format [auto]" },
83 { 'l', 0, "list-short", NULL, "List tracks (short) [no]" },
84 { 'L', 0, "list-long", NULL, "List tracks (long) [no]" },
85 { 'm', 1, "merge", "filename", "Merge an image" },
86 { 'M', 1, "merge-overwrite", "filename", "Merge an image and overwrite tracks" },
87 { 'o', 1, "output", "filename", "Set the output file name [none]" },
88 { 'O', 1, "output-format", "format", "Set the output format [auto]" },
89 { 'p', 1, "operation", "name [...]", "Perform an operation" },
90 { 'r', 1, "data-rate", "rate", "Set the data rate [500000]" },
91 { 's', 2, "set", "par val", "Set a paramter value" },
92 { 't', 2, "track", "c h", "Select tracks [all]" },
93 { 'v', 0, "verbose", NULL, "Verbose operation [no]" },
94 { 'V', 0, "version", NULL, "Print version information" },
95 { 'x', 0, "invert", NULL, "Invert the selection [no]" },
96 { 'z', 0, "clear", NULL, "Clear the selection [yes]" },
97 { -1, 0, NULL, NULL, NULL }
98};
99
100static struct {
101 const char *name;
102 const char *opts;
103 const char *desc;
104} ops[] = {
105 { "comment-add", "text", "Add to the image comment" },
106 { "comment-load", "filename", "Load the image comment from a file" },
107 { "comment-print", "", "Print the image comment" },
108 { "comment-save", "filename", "Save the image comment to a file" },
109 { "comment-set", "text", "Set the image comment" },
110 { "event-add", "type pos val", "Add an event on selected tracks" },
111 { "event-clear", "", "Clear all events on selected tracks" },
112 { "event-del", "type [@]range", "Delete events by position or index" },
113 { "event-list", "type [@]range", "List events by position or index" },
114 { "decode", "type file", "Decode tracks" },
115 { "delete", "", "Delete tracks" },
116 { "double-step", "", "Remove odd numbered tracks" },
117 { "double-step-even", "", "Remove even numbered tracks" },
118 { "encode", "type file", "Encode tracks" },
119 { "half-rate", "", "Half the data rate by removing odd numbered bits" },
120 { "half-step", "", "Duplicate all tracks" },
121 { "info", "", "Print image information" },
122 { "mac-align", "mode", "Align mac tracks" },
123 { "mfm-align-am", "what number pos", "Align an address mark with pos" },
124 { "new", "", "Create new tracks" },
125 { "rotate-angle", "angle", "Rotate tracks by <angle> degrees" },
126 { "rotate", "bits", "Rotate tracks left" },
127 { "save", "filename", "Save raw tracks" },
128 { "weak-clean", "", "Clean up weak bit events" },
129 { "weak-close", "max", "Fill gaps up to <max> bits between weak bits" },
130 { "weak-detect", "max", "Autodetect weak bits after <max> zero bits" },
131 { "weak-expand", "left right", "Expand runs of weak bits" },
132 { "weak-load", "file", "Load the weak bit mask" },
133 { "weak-open", "max", "Remove runs of weak bits up to <max> bits long" },
134 { "weak-save", "file", "Save the weak bit mask" },
135 { "weak-set", "val", "Set weak bits (0|1|flip|random)" },
136 { NULL, NULL, NULL }
137};
138
139
140static
141void print_help_ops (void)
142{
143 unsigned i, n, w;
144
145 n = 0;
146
147 i = 0;
148 while (ops[i].name != NULL) {
149 w = strlen (ops[i].name) + strlen (ops[i].opts);
150
151 if (w > n) {
152 n = w;
153 }
154
155 i += 1;
156 }
157
158 n += 2;
159
160 i = 0;
161 while (ops[i].name != NULL) {
162 w = strlen (ops[i].name) + strlen (ops[i].opts);
163
164 fprintf (stdout, " %s %s", ops[i].name, ops[i].opts);
165
166 while (w < n) {
167 fputc (' ', stdout);
168 w += 1;
169 }
170
171 fprintf (stdout, "%s\n", ops[i].desc);
172
173 i += 1;
174 }
175}
176
177static
178void print_help (void)
179{
180 pce_getopt_help (
181 "pri: convert and modify PCE raw image files",
182 "usage: pri [options] [input] [options] [output]",
183 opts
184 );
185
186 fputs ("\noperations are:\n", stdout);
187
188 print_help_ops();
189
190 fputs (
191 "\n"
192 "parameters are:\n"
193 " fm-auto-gap3, fm-clock, fm-iam, fm-gap1, fm-gap3,"
194 " fm-gap4a, fm-track-size,\n"
195 " mac-align, mac-no-slip,\n"
196 " mfm-auto-gap3, mfm-clock, mfm-iam, mfm-gap1, mfm-gap3,"
197 " mfm-gap4a,\n"
198 " mfm-min-size, mfm-nopos, mfm-track-size\n"
199 " psi-pos, text-align\n"
200 "\n"
201 "decode types are:\n"
202 " auto, ibm-fm, ibm-mfm, mac-gcr,\n"
203 " text, text-fm, text-mfm, text-mac, text-raw\n"
204 "\n"
205 "encode types are:\n"
206 " auto, text, mac-gcr\n"
207 " ibm-fm, ibm-fm-sd-300,\n"
208 " ibm-mfm, ibm-mfm-dd-300, ibm-mfm-hd-300, ibm-mfm-hd-360\n"
209 "\n"
210 "file formats are:\n"
211 " pri, tc, woz, moof\n"
212 "\n"
213 "image attributes are:\n"
214 " readonly, woz-cleaned, woz-track-sync\n"
215 "\n"
216 "track attributes are:\n"
217 " clock, data, size\n",
218 stdout
219 );
220
221 fflush (stdout);
222}
223
224static
225void print_version (void)
226{
227 fputs (
228 "pri version " PCE_VERSION_STR
229 "\n\n"
230 "Copyright (C) 2012-" PCE_YEAR " Hampa Hug <hampa@hampa.ch>\n",
231 stdout
232 );
233
234 fflush (stdout);
235}
236
237
238int strcmp2 (const char *str, const char *str1, const char *str2)
239{
240 if (strcmp (str, str1) == 0) {
241 return (0);
242 }
243
244 if (strcmp (str, str2) == 0) {
245 return (0);
246 }
247
248 return (1);
249}
250
251int pri_parse_range (const char *str, unsigned long *v1, unsigned long *v2, char *all)
252{
253 *v1 = 0;
254 *v2 = 0;
255 *all = 0;
256
257 if (strcmp (str, "all") == 0) {
258 *all = 1;
259 return (0);
260 }
261
262 while ((*str >= '0') && (*str <= '9')) {
263 *v1 = 10 * *v1 + (*str - '0');
264 str += 1;
265 }
266
267 if (*str == '-') {
268 str += 1;
269
270 if (*str == 0) {
271 *v2 = ~(unsigned long) 0;
272 return (0);
273 }
274
275 while ((*str >= '0') && (*str <= '9')) {
276 *v2 = 10 * *v2 + (*str - '0');
277 str += 1;
278 }
279 }
280 else {
281 *v2 = *v1;
282 }
283
284 if (*str != 0) {
285 return (1);
286 }
287
288 return (0);
289}
290
291
292static
293int pri_sel_match_track (unsigned c, unsigned h)
294{
295 if (!par_cyl_all && ((c < par_cyl[0]) || (c > par_cyl[1]))) {
296 return (par_invert);
297 }
298
299 if (!par_trk_all && ((h < par_trk[0]) || (h > par_trk[1]))) {
300 return (par_invert);
301 }
302
303 return (!par_invert);
304}
305
306int pri_for_all_tracks (pri_img_t *img, pri_trk_cb fct, void *opaque)
307{
308 unsigned long c, h;
309 pri_cyl_t *cyl;
310 pri_trk_t *trk;
311
312 for (c = 0; c < img->cyl_cnt; c++) {
313 cyl = img->cyl[c];
314
315 if (cyl == NULL) {
316 continue;
317 }
318
319 for (h = 0; h < cyl->trk_cnt; h++) {
320 trk = cyl->trk[h];
321
322 if (trk == NULL) {
323 continue;
324 }
325
326 if (pri_sel_match_track (c, h) == 0) {
327 continue;
328 }
329
330 if (fct (img, trk, c, h, opaque)) {
331 return (1);
332 }
333 }
334 }
335
336 return (0);
337}
338
339
340static
341int pri_operation (pri_img_t **img, const char *op, int argc, char **argv)
342{
343 int r;
344 char **optarg1, **optarg2, **optarg3;
345
346 if (*img == NULL) {
347 *img = pri_img_new();
348
349 if (*img == NULL) {
350 return (1);
351 }
352 }
353
354 r = 1;
355
356 if (strcmp (op, "comment-add") == 0) {
357 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
358 return (1);
359 }
360
361 r = pri_comment_add (*img, optarg1[0]);
362 }
363 else if (strcmp (op, "comment-load") == 0) {
364 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
365 return (1);
366 }
367
368 r = pri_comment_load (*img, optarg1[0]);
369 }
370 else if (strcmp (op, "comment-print") == 0) {
371 r = pri_comment_show (*img);
372 }
373 else if (strcmp (op, "comment-save") == 0) {
374 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
375 return (1);
376 }
377
378 r = pri_comment_save (*img, optarg1[0]);
379 }
380 else if (strcmp (op, "comment-set") == 0) {
381 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
382 return (1);
383 }
384
385 r = pri_comment_set (*img, optarg1[0]);
386 }
387 else if (strcmp (op, "decode") == 0) {
388 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
389 fprintf (stderr, "%s: missing decode type\n", arg0);
390 return (1);
391 }
392
393 if (pce_getopt (argc, argv, &optarg2, NULL) != 0) {
394 fprintf (stderr, "%s: missing file name\n", arg0);
395 return (1);
396 }
397
398 r = pri_decode (*img, optarg1[0], optarg2[0]);
399 }
400 else if (strcmp (op, "delete") == 0) {
401 r = pri_delete_tracks (*img);
402 }
403 else if (strcmp (op, "double-step") == 0) {
404 r = pri_double_step (*img, 1);
405 }
406 else if (strcmp (op, "double-step-even") == 0) {
407 r = pri_double_step (*img, 0);
408 }
409 else if (strcmp (op, "double-step-odd") == 0) {
410 r = pri_double_step (*img, 1);
411 }
412 else if (strcmp (op, "encode") == 0) {
413 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
414 fprintf (stderr, "%s: missing encode type\n", arg0);
415 return (1);
416 }
417
418 if (pce_getopt (argc, argv, &optarg2, NULL) != 0) {
419 fprintf (stderr, "%s: missing file name\n", arg0);
420 return (1);
421 }
422
423 r = pri_encode (img, optarg1[0], optarg2[0]);
424 }
425 else if (strcmp (op, "event-add") == 0) {
426 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
427 fprintf (stderr, "%s: missing event type\n", arg0);
428 return (1);
429 }
430
431 if (pce_getopt (argc, argv, &optarg2, NULL) != 0) {
432 fprintf (stderr, "%s: missing event position\n", arg0);
433 return (1);
434 }
435
436 if (pce_getopt (argc, argv, &optarg3, NULL) != 0) {
437 fprintf (stderr, "%s: missing event value\n", arg0);
438 return (1);
439 }
440
441 r = pri_event_add (*img, optarg1[0], optarg2[0], optarg3[0]);
442 }
443 else if (strcmp (op, "event-clear") == 0) {
444 r = pri_event_clear (*img);
445 }
446 else if (strcmp (op, "event-del") == 0) {
447 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
448 fprintf (stderr, "%s: missing event type\n", arg0);
449 return (1);
450 }
451
452 if (pce_getopt (argc, argv, &optarg2, NULL) != 0) {
453 fprintf (stderr, "%s: missing event range\n", arg0);
454 return (1);
455 }
456
457 r = pri_event_del (*img, optarg1[0], optarg2[0]);
458 }
459 else if (strcmp (op, "event-list") == 0) {
460 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
461 fprintf (stderr, "%s: missing event type\n", arg0);
462 return (1);
463 }
464
465 if (pce_getopt (argc, argv, &optarg2, NULL) != 0) {
466 fprintf (stderr, "%s: missing event range\n", arg0);
467 return (1);
468 }
469
470 r = pri_event_list (*img, optarg1[0], optarg2[0]);
471 }
472 else if (strcmp (op, "mac-align") == 0) {
473 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
474 fprintf (stderr, "%s: missing mode\n", arg0);
475 return (1);
476 }
477
478 r = pri_mac_gcr_align (*img, optarg1[0]);
479 }
480 else if (strcmp (op, "mac-align-index") == 0) {
481 r = pri_mac_gcr_align_index (*img);
482 }
483 else if (strcmp (op, "mac-align-sector") == 0) {
484 r = pri_mac_gcr_align_sector (*img);
485 }
486 else if ((strcmp (op, "weak-clean") == 0)) {
487 r = pri_weak_clean (*img);
488 }
489 else if ((strcmp (op, "weak-close") == 0)) {
490 unsigned cnt;
491
492 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
493 fprintf (stderr, "%s: missing window size\n", arg0);
494 return (1);
495 }
496
497 cnt = strtoul (optarg1[0], NULL, 0);
498
499 r = pri_weak_close (*img, cnt);
500 }
501 else if ((strcmp (op, "weak-detect") == 0)) {
502 unsigned long max;
503
504 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
505 fprintf (stderr, "%s: missing weak bit detection limit\n", arg0);
506 return (1);
507 }
508
509 max = strtoul (optarg1[0], NULL, 0);
510
511 r = pri_weak_detect (*img, max);
512 }
513 else if ((strcmp (op, "weak-expand") == 0)) {
514 unsigned long left, right;
515
516 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
517 fprintf (stderr, "%s: value\n", arg0);
518 return (1);
519 }
520
521 left = strtoul (optarg1[0], NULL, 0);
522
523 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
524 fprintf (stderr, "%s: value\n", arg0);
525 return (1);
526 }
527
528 right = strtoul (optarg1[0], NULL, 0);
529
530 r = pri_weak_expand (*img, left, right);
531 }
532 else if (strcmp (op, "weak-load") == 0) {
533 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
534 fprintf (stderr, "%s: missing file name\n", arg0);
535 return (1);
536 }
537
538 r = pri_weak_load (*img, optarg1[0]);
539 }
540 else if (strcmp (op, "weak-open") == 0) {
541 unsigned cnt;
542
543 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
544 fprintf (stderr, "%s: missing window size\n", arg0);
545 return (1);
546 }
547
548 cnt = strtoul (optarg1[0], NULL, 0);
549
550 r = pri_weak_open (*img, cnt);
551 }
552 else if (strcmp (op, "weak-save") == 0) {
553 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
554 fprintf (stderr, "%s: missing file name\n", arg0);
555 return (1);
556 }
557
558 r = pri_weak_save (*img, optarg1[0]);
559 }
560 else if (strcmp (op, "weak-set") == 0) {
561 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
562 fprintf (stderr, "%s: missing weak bit value\n", arg0);
563 return (1);
564 }
565
566 if (strcmp (optarg1[0], "random") == 0) {
567 r = pri_weak_flip (*img, 1);
568 }
569 else if (strcmp (optarg1[0], "flip") == 0) {
570 r = pri_weak_flip (*img, 0);
571 }
572 else if (strcmp (optarg1[0], "0") == 0) {
573 r = pri_weak_set (*img, 0);
574 }
575 else if (strcmp (optarg1[0], "1") == 0) {
576 r = pri_weak_set (*img, 1);
577 }
578 else {
579 fprintf (stderr, "%s: unknown weak bit value (%s)\n",
580 arg0, optarg1[0]
581 );
582 return (1);
583 }
584 }
585 else if (strcmp (op, "half-rate") == 0) {
586 r = pri_half_rate (*img);
587 }
588 else if (strcmp (op, "half-step") == 0) {
589 r = pri_half_step (*img);
590 }
591 else if (strcmp (op, "info") == 0) {
592 r = pri_print_info (*img);
593 }
594 else if (strcmp (op, "mfm-align-am") == 0) {
595 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
596 fprintf (stderr, "%s: missing address mark type\n", arg0);
597 return (1);
598 }
599
600 if (pce_getopt (argc, argv, &optarg2, NULL) != 0) {
601 fprintf (stderr, "%s: missing address mark number\n", arg0);
602 return (1);
603 }
604
605 if (pce_getopt (argc, argv, &optarg3, NULL) != 0) {
606 fprintf (stderr, "%s: missing position\n", arg0);
607 return (1);
608 }
609
610 r = pri_mfm_align_am (*img, optarg1[0], optarg2[0], optarg3[0]);
611 }
612 else if (strcmp (op, "new") == 0) {
613 r = pri_new (*img);
614 }
615 else if (strcmp (op, "rotate-angle") == 0) {
616 double val;
617
618 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
619 fprintf (stderr, "%s: missing angle\n", arg0);
620 return (1);
621 }
622
623 val = strtod (optarg1[0], NULL);
624
625 r = pri_rotate_tracks_angle (*img, val);
626 }
627 else if (strcmp (op, "rotate") == 0) {
628 long ofs;
629
630 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
631 fprintf (stderr, "%s: missing start position\n", arg0);
632 return (1);
633 }
634
635 ofs = strtol (optarg1[0], NULL, 0);
636
637 r = pri_rotate_tracks (*img, ofs);
638 }
639 else if (strcmp (op, "save") == 0) {
640 if (pce_getopt (argc, argv, &optarg1, NULL) != 0) {
641 fprintf (stderr, "%s: missing file name\n", arg0);
642 return (1);
643 }
644
645 r = pri_decode_raw (*img, optarg1[0]);
646 }
647 else {
648 fprintf (stderr, "%s: unknown operation (%s)\n", arg0, op);
649 return (1);
650 }
651
652 if (r) {
653 fprintf (stderr, "%s: operation failed (%s)\n", arg0, op);
654 }
655
656 return (r);
657}
658
659
660static
661pri_img_t *pri_load_image (const char *fname)
662{
663 pri_img_t *img;
664
665 if (par_verbose) {
666 fprintf (stderr, "%s: loading image from %s\n", arg0, fname);
667 }
668
669 if (strcmp (fname, "-") == 0) {
670 img = pri_img_load_fp (stdin, par_fmt_inp);
671 }
672 else {
673 img = pri_img_load (fname, par_fmt_inp);
674 }
675
676 if (img == NULL) {
677 fprintf (stderr, "%s: loading failed (%s)\n", arg0, fname);
678 return (NULL);
679 }
680
681 if (par_list) {
682 par_list = 0;
683 pri_list_tracks (img);
684 }
685
686 if (par_print_info) {
687 par_print_info = 0;
688 pri_print_info (img);
689 }
690
691 return (img);
692}
693
694static
695int pri_save_image (const char *fname, pri_img_t **img)
696{
697 int r;
698
699 if (*img == NULL) {
700 *img = pri_img_new();
701 }
702
703 if (*img == NULL) {
704 return (1);
705 }
706
707 if (par_verbose) {
708 fprintf (stderr, "%s: save image to %s\n", arg0, fname);
709 }
710
711 if (strcmp (fname, "-") == 0) {
712 r = pri_img_save_fp (stdout, *img, par_fmt_out);
713 }
714 else {
715 r = pri_img_save (fname, *img, par_fmt_out);
716 }
717
718 if (r) {
719 fprintf (stderr, "%s: saving failed (%s)\n",
720 arg0, fname
721 );
722
723 return (1);
724 }
725
726 return (0);
727}
728
729static
730int pri_set_parameter (const char *name, const char *val)
731{
732 if (strcmp (name, "mac-no-slip") == 0) {
733 par_mac_no_slip = (strtoul (val, NULL, 0) != 0);
734 }
735 else if (strcmp (name, "mfm-auto-gap3") == 0) {
736 par_enc_mfm.auto_gap3 = (strtoul (val, NULL, 0) != 0);
737 }
738 else if (strcmp (name, "mfm-clock") == 0) {
739 par_enc_mfm.clock = strtoul (val, NULL, 0);
740 }
741 else if (strcmp (name, "mfm-iam") == 0) {
742 par_enc_mfm.enable_iam = (strtoul (val, NULL, 0) != 0);
743 }
744 else if (strcmp (name, "mfm-gap1") == 0) {
745 par_enc_mfm.gap1 = strtoul (val, NULL, 0);
746 }
747 else if (strcmp (name, "mfm-gap3") == 0) {
748 par_enc_mfm.gap3 = strtoul (val, NULL, 0);
749 }
750 else if (strcmp (name, "mfm-gap4a") == 0) {
751 par_enc_mfm.gap4a = strtoul (val, NULL, 0);
752 }
753 else if (strcmp (name, "mfm-min-size") == 0) {
754 par_dec_mfm.min_sct_size = strtoul (val, NULL, 0);
755 }
756 else if (strcmp (name, "mfm-nopos") == 0) {
757 par_enc_mfm.nopos = (strtoul (val, NULL, 0) != 0);
758 }
759 else if (strcmp (name, "mfm-track-size") == 0) {
760 par_enc_mfm.track_size = strtoul (val, NULL, 0);
761 }
762 else if (strcmp (name, "fm-auto-gap3") == 0) {
763 par_enc_fm.auto_gap3 = (strtoul (val, NULL, 0) != 0);
764 }
765 else if (strcmp (name, "fm-clock") == 0) {
766 par_enc_fm.clock = strtoul (val, NULL, 0);
767 }
768 else if (strcmp (name, "fm-iam") == 0) {
769 par_enc_fm.enable_iam = (strtoul (val, NULL, 0) != 0);
770 }
771 else if (strcmp (name, "fm-gap1") == 0) {
772 par_enc_fm.gap1 = strtoul (val, NULL, 0);
773 }
774 else if (strcmp (name, "fm-gap3") == 0) {
775 par_enc_fm.gap3 = strtoul (val, NULL, 0);
776 }
777 else if (strcmp (name, "fm-gap4a") == 0) {
778 par_enc_fm.gap4a = strtoul (val, NULL, 0);
779 }
780 else if (strcmp (name, "fm-track-size") == 0) {
781 par_enc_fm.track_size = strtoul (val, NULL, 0);
782 }
783 else if (strcmp (name, "mac-align") == 0) {
784 if (pri_mac_align_mode (val, &par_mac_align)) {
785 fprintf (stderr, "%s: unknown mode (%s)\n", arg0, val);
786 return (1);
787 }
788 }
789 else if (strcmp (name, "psi-pos") == 0) {
790 par_psi_dec_pos = (strtoul (val, NULL, 0) != 0);
791 }
792 else if (strcmp (name, "text-align") == 0) {
793 par_text_align = (strtoul (val, NULL, 0) != 0);
794 }
795 else if (strcmp (name, "track-size") == 0) {
796 par_track_size = strtoul (val, NULL, 0);
797 }
798 else {
799 fprintf (stderr, "%s: unknown parameter (%s)\n", arg0, name);
800 return (1);
801 }
802
803 return (0);
804}
805
806static
807int pri_set_format (const char *name, unsigned *val)
808{
809 if (strcmp (name, "pbit") == 0) {
810 *val = PRI_FORMAT_PBIT;
811 }
812 else if (strcmp (name, "pri") == 0) {
813 *val = PRI_FORMAT_PRI;
814 }
815 else if (strcmp (name, "tc") == 0) {
816 *val = PRI_FORMAT_TC;
817 }
818 else if (strcmp (name, "woz") == 0) {
819 *val = PRI_FORMAT_WOZ;
820 }
821 else if (strcmp (name, "moof") == 0) {
822 *val = PRI_FORMAT_MOOF;
823 }
824 else {
825 fprintf (stderr, "%s: unknown format (%s)\n", arg0, name);
826 *val = PRI_FORMAT_NONE;
827 return (1);
828 }
829
830 return (0);
831}
832
833int main (int argc, char **argv)
834{
835 int r;
836 char **optarg;
837 pri_img_t *img;
838
839 arg0 = argv[0];
840
841 img = NULL;
842
843 pri_encode_fm_init (&par_enc_fm, 250000, 300);
844
845 pri_decode_mfm_init (&par_dec_mfm);
846 pri_encode_mfm_init (&par_enc_mfm, 500000, 300);
847
848 pce_srand (0);
849
850 while (1) {
851 r = pce_getopt (argc, argv, &optarg, opts);
852
853 if (r == GETOPT_DONE) {
854 break;
855 }
856
857 if (r < 0) {
858 return (1);
859 }
860
861 switch (r) {
862 case '?':
863 print_help();
864 return (0);
865
866 case 'V':
867 print_version();
868 return (0);
869
870 case 'c':
871 if (pri_parse_range (optarg[0], &par_cyl[0], &par_cyl[1], &par_cyl_all)) {
872 return (1);
873 }
874 break;
875
876 case 'e':
877 if (img != NULL) {
878 if (pri_edit (img, optarg[0], optarg[1])) {
879 return (1);
880 }
881 }
882 break;
883
884 case 'f':
885 if (img != NULL) {
886 pri_print_info (img);
887 }
888 else {
889 par_print_info = 1;
890 }
891 break;
892
893 case 'h':
894 if (pri_parse_range (optarg[0], &par_trk[0], &par_trk[1], &par_trk_all)) {
895 return (1);
896 }
897 break;
898
899 case 'i':
900 if (img != NULL) {
901 pri_img_del (img);
902 }
903
904 img = pri_load_image (optarg[0]);
905
906 if (img == NULL) {
907 return (1);
908 }
909 break;
910
911 case 'I':
912 if (pri_set_format (optarg[0], &par_fmt_inp)) {
913 return (1);
914 }
915 break;
916
917 case 'l':
918 case 'L':
919 par_list_long = (r == 'L');
920 if (img != NULL) {
921 pri_list_tracks (img);
922 }
923 else {
924 par_list = 1;
925 }
926 break;
927
928 case 'm':
929 case 'M':
930 if (img != NULL) {
931 if (pri_merge_image (img, optarg[0], r == 'M')) {
932 fprintf (stderr, "%s: merge failed\n", arg0);
933 return (1);
934 }
935 }
936 else {
937 img = pri_load_image (optarg[0]);
938
939 if (img == NULL) {
940 fprintf (stderr, "%s: merge failed\n", arg0);
941 return (1);
942 }
943 }
944 break;
945
946 case 'o':
947 if (pri_save_image (optarg[0], &img)) {
948 return (1);
949 }
950 break;
951
952 case 'O':
953 if (pri_set_format (optarg[0], &par_fmt_out)) {
954 return (1);
955 }
956 break;
957
958 case 'p':
959 if (pri_operation (&img, optarg[0], argc, argv)) {
960 return (1);
961 }
962 break;
963
964 case 'r':
965 par_data_rate = strtoul (optarg[0], NULL, 0);
966
967 if (par_data_rate <= 1000) {
968 par_data_rate *= 1000;
969 }
970 break;
971
972 case 's':
973 if (pri_set_parameter (optarg[0], optarg[1])) {
974 return (1);
975 }
976 break;
977
978 case 't':
979 if (pri_parse_range (optarg[0], &par_cyl[0], &par_cyl[1], &par_cyl_all)) {
980 return (1);
981 }
982 if (pri_parse_range (optarg[1], &par_trk[0], &par_trk[1], &par_trk_all)) {
983 return (1);
984 }
985 break;
986
987 case 'v':
988 par_verbose = 1;
989 break;
990
991 case 'x':
992 par_invert = !par_invert;
993 break;
994
995 case 'z':
996 par_invert = 0;
997 par_cyl_all = 1;
998 par_trk_all = 1;
999 break;
1000
1001 case 0:
1002 if (img == NULL) {
1003 img = pri_load_image (optarg[0]);
1004
1005 if (img == NULL) {
1006 return (1);
1007 }
1008 }
1009 else {
1010 if (pri_save_image (optarg[0], &img)) {
1011 return (1);
1012 }
1013 }
1014 break;
1015
1016 default:
1017 return (1);
1018 }
1019 }
1020
1021 return (0);
1022}