fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/utils/psi/main.c *
7 * Created: 2010-08-13 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2010-2024 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 "comment.h"
25#include "delete.h"
26#include "edit.h"
27#include "info.h"
28#include "list.h"
29#include "load.h"
30#include "merge.h"
31#include "new.h"
32#include "reorder.h"
33#include "save.h"
34
35#include <stdlib.h>
36#include <stdio.h>
37#include <string.h>
38
39#include <lib/getopt.h>
40
41#include <drivers/psi/psi.h>
42#include <drivers/psi/psi-img-raw.h>
43#include <drivers/psi/psi-img-stx.h>
44#include <drivers/psi/psi-img.h>
45
46
47const char *arg0 = NULL;
48int par_verbose = 0;
49unsigned par_filler = 0xf6;
50unsigned long par_cnt;
51
52char par_invert = 0;
53
54char par_cyl_all = 1;
55unsigned par_cyl[2];
56
57char par_trk_all = 1;
58unsigned par_trk[2];
59
60char par_sct_all = 1;
61unsigned par_sct[2];
62
63char par_rsc_all = 1;
64unsigned par_rsc[2];
65
66char par_alt_all = 1;
67unsigned par_alt[2];
68
69
70static int par_list_tracks = 0;
71static int par_list_sectors = 0;
72static int par_print_info = 0;
73
74static unsigned par_fmt_inp = PSI_FORMAT_NONE;
75static unsigned par_fmt_out = PSI_FORMAT_NONE;
76
77
78static pce_option_t opts[] = {
79 { '?', 0, "help", NULL, "Print usage information" },
80 { 'a', 1, "alternate", "a", "Select alternate sectors" },
81 { 'c', 1, "cylinder", "c", "Select cylinders [all]" },
82 { 'D', 0, "dump", NULL, "Dump extra information [no]" },
83 { 'e', 2, "edit", "what val", "Edit selected sector attributes" },
84 { 'f', 0, "info", NULL, "Print image information [no]" },
85 { 'F', 1, "filler", "val", "Set the sector fill byte [0xf6]" },
86 { 'h', 1, "head", "h", "Select heads [all]" },
87 { 'i', 1, "input", "filename", "Load an input file" },
88 { 'I', 1, "input-format", "format", "Set the input format [auto]" },
89 { 'l', 0, "list-tracks", NULL, "List tracks [no]" },
90 { 'L', 0, "list-sectors", NULL, "List sectors [no]" },
91 { 'm', 1, "merge", "filename", "Merge an image" },
92 { 'n', 1, "new-dos", "size", "Create a standard image of <size> KiB" },
93 { 'N', 2, "new", "type size", "Create a standard image of <size> KiB" },
94 { 'o', 1, "output", "filename", "Save to an output file [none]" },
95 { 'O', 1, "output-format", "format", "Set the output format [auto]" },
96 { 'p', 1, "operation", "name [...]", "Perform an operation" },
97 { 'r', 3, "record", "c h s", "Select sectors [all all all]" },
98 { 's', 1, "sectors", "s", "Select logical sectors [all]" },
99 { 'S', 1, "real-sectors", "s", "Select real sectors [all]" },
100 { 't', 2, "track", "c h", "Select tracks [all]" },
101 { 'v', 0, "verbose", NULL, "Verbose operation [no]" },
102 { 'V', 0, "version", NULL, "Print version information" },
103 { 'x', 0, "invert", NULL, "Invert the selection [no]" },
104 { 'z', 0, "clear", NULL, "Clear the selection [yes]" },
105 { -1, 0, NULL, NULL, NULL }
106};
107
108
109static
110void print_help (void)
111{
112 pce_getopt_help (
113 "psi: convert and modify PCE sector image files",
114 "usage: psi [options] [input] [options] [output...]",
115 opts
116 );
117
118 fputs (
119 "\noperations are:\n"
120 " clear-position Clear the sector position\n"
121 " comment-add text Add to the image comment\n"
122 " comment-load filename Load the image comment from a file\n"
123 " comment-print Print the image comment\n"
124 " comment-save filename Save the image comment to a file\n"
125 " comment-set text Set the image comment\n"
126 " delete Delete sectors\n"
127 " info Print image information\n"
128 " interleave n Set the sector interleave to n\n"
129 " load filename Load individual sectors\n"
130 " new Create new sectors\n"
131 " regular c/h/s/n Regularize the image\n"
132 " reorder s1,s2,... Reorder sectors in a track\n"
133 " rotate first Rotate tracks\n"
134 " save filename Save individual sectors\n"
135 " sort Sort sectors on tracks\n"
136 " sort-reverse Sort sectors on tracks in reverse order\n"
137 " tags-load filename Load sector tags\n"
138 " tags-save filename Save sector tags\n"
139 " weak-auto Convert alternate sectors to weak bit masks\n"
140 " weak-clear Remove weak bit masks\n"
141 " weak-load filename Load the weak bit mask\n"
142 " weak-save filename Save the weak bit mask\n",
143 stdout
144 );
145
146 fputs (
147 "\nfile formats are:\n"
148 " ana, cp2, dc42, imd, msa, pfdc, psi, raw, st, td0, xdf\n",
149 stdout
150 );
151
152 fputs (
153 "\nsector attributes are:\n"
154 " c, crc-id, crc-data, del-dam, fm, fm-hd, gcr, h,\n"
155 " mfm, mfm-hd, mfm-ed, no-dam, position, round-time,\n"
156 " s, size, tags, time\n",
157 stdout
158 );
159
160 fflush (stdout);
161}
162
163static
164void print_version (void)
165{
166 fputs (
167 "psi version " PCE_VERSION_STR
168 "\n\n"
169 "Copyright (C) 2010-" PCE_YEAR " Hampa Hug <hampa@hampa.ch>\n",
170 stdout
171 );
172
173 fflush (stdout);
174}
175
176
177int psi_check_duplicate (const psi_trk_t *trk, unsigned idx)
178{
179 unsigned i;
180
181 if (idx >= trk->sct_cnt) {
182 return (0);
183 }
184
185 for (i = 0; i < trk->sct_cnt; i++) {
186 if (i == idx) {
187 continue;
188 }
189
190 if (trk->sct[i]->s == trk->sct[idx]->s) {
191 return (1);
192 }
193 }
194
195 return (0);
196}
197
198static
199int psi_parse_range (const char *str, unsigned *v1, unsigned *v2, char *all)
200{
201 *v1 = 0;
202 *v2 = 0;
203 *all = 0;
204
205 if (strcmp (str, "all") == 0) {
206 *all = 1;
207 return (0);
208 }
209
210 while ((*str >= '0') && (*str <= '9')) {
211 *v1 = 10 * *v1 + (*str - '0');
212 str += 1;
213 }
214
215 if (*str == '-') {
216 str += 1;
217
218 if (*str == 0) {
219 *v2 = ~(unsigned) 0;
220 return (0);
221 }
222
223 while ((*str >= '0') && (*str <= '9')) {
224 *v2 = 10 * *v2 + (*str - '0');
225 str += 1;
226 }
227 }
228 else {
229 *v2 = *v1;
230 }
231
232
233 if (*str != 0) {
234 return (1);
235 }
236
237 return (0);
238}
239
240int psi_parse_int_list (const char **str, unsigned *val)
241{
242 const char *s;
243
244 s = *str;
245
246 if ((*s < '0') || (*s > '9')) {
247 return (1);
248 }
249
250 *val = 0;
251
252 while ((*s >= '0') && (*s <= '9')) {
253 *val = 10 * *val + (*s - '0');
254 s += 1;
255 }
256
257 if (*s == ',') {
258 s += 1;
259 }
260
261 *str = s;
262
263 return (0);
264}
265
266int psi_isstr (const char *str, const char *s1, const char *s2)
267{
268 if (s1 != NULL) {
269 if (strcmp (str, s1) == 0) {
270 return (1);
271 }
272 }
273
274 if (s2 != NULL) {
275 if (strcmp (str, s2) == 0) {
276 return (1);
277 }
278 }
279
280 return (0);
281}
282
283static
284int psi_sel_match_track (unsigned c, unsigned h)
285{
286 if (!par_cyl_all && ((c < par_cyl[0]) || (c > par_cyl[1]))) {
287 return (par_invert);
288 }
289
290 if (!par_trk_all && ((h < par_trk[0]) || (h > par_trk[1]))) {
291 return (par_invert);
292 }
293
294 return (!par_invert);
295}
296
297int psi_sel_match (unsigned c, unsigned h, unsigned s, unsigned r, unsigned a)
298{
299 if (psi_sel_match_track (c, h) == par_invert) {
300 return (par_invert);
301 }
302
303 if (!par_sct_all && ((s < par_sct[0]) || (s > par_sct[1]))) {
304 return (par_invert);
305 }
306
307 if (!par_rsc_all && ((r < par_rsc[0]) || (r > par_rsc[1]))) {
308 return (par_invert);
309 }
310
311 if (!par_alt_all && ((a < par_alt[0]) || (a > par_alt[1]))) {
312 return (par_invert);
313 }
314
315 return (!par_invert);
316}
317
318int psi_for_all_sectors (psi_img_t *img, psi_sct_cb fct, void *opaque)
319{
320 unsigned c, h, s, a;
321 psi_cyl_t *cyl;
322 psi_trk_t *trk;
323 psi_sct_t *sct;
324
325 for (c = 0; c < img->cyl_cnt; c++) {
326 cyl = img->cyl[c];
327
328 for (h = 0; h < cyl->trk_cnt; h++) {
329 trk = cyl->trk[h];
330
331 for (s = 0; s < trk->sct_cnt; s++) {
332 sct = trk->sct[s];
333
334 a = 0;
335 while (sct != 0) {
336 if (psi_sel_match (c, h, sct->s, s, a)) {
337 if (fct (img, sct, c, h, s, a, opaque)) {
338 return (1);
339 }
340 }
341
342 sct = sct->next;
343 a += 1;
344 }
345 }
346 }
347 }
348
349 return (0);
350}
351
352int psi_for_all_tracks (psi_img_t *img, psi_trk_cb fct, void *opaque)
353{
354 unsigned c, h;
355 psi_cyl_t *cyl;
356 psi_trk_t *trk;
357
358 for (c = 0; c < img->cyl_cnt; c++) {
359 cyl = img->cyl[c];
360
361 for (h = 0; h < cyl->trk_cnt; h++) {
362 trk = cyl->trk[h];
363
364 if (psi_sel_match_track (c, h) == 0) {
365 continue;
366 }
367
368 if (fct (img, trk, c, h, opaque)) {
369 return (1);
370 }
371 }
372 }
373
374 return (0);
375}
376
377
378static
379int psi_auto_weak_cb (psi_img_t *img, psi_sct_t *sct,
380 unsigned c, unsigned h, unsigned s, unsigned a, void *p)
381{
382 unsigned i, n;
383 psi_sct_t *tmp;
384
385 if (sct->next == NULL) {
386 return (0);
387 }
388
389 if (psi_weak_alloc (sct)) {
390 return (1);
391 }
392
393 tmp = sct->next;
394
395 while (tmp != NULL) {
396 if (psi_weak_alloc (tmp)) {
397 return (1);
398 }
399
400 n = (sct->n < tmp->n) ? sct->n : tmp->n;
401
402 for (i = 0; i < n; i++) {
403 sct->weak[i] |= sct->data[i] ^ tmp->data[i];
404 sct->weak[i] |= tmp->weak[i];
405 tmp->weak[i] = sct->weak[i];
406 }
407
408 tmp = tmp->next;
409 }
410
411 psi_weak_clean (sct);
412
413 return (0);
414}
415
416int psi_auto_weak (psi_img_t *img)
417{
418 int r;
419
420 r = psi_for_all_sectors (img, psi_auto_weak_cb, NULL);
421
422 if (r) {
423 fprintf (stderr, "%s: converting failed\n", arg0);
424 }
425
426 return (r);
427}
428
429
430static
431int psi_clear_weak_cb (psi_img_t *img, psi_sct_t *sct,
432 unsigned c, unsigned h, unsigned s, unsigned a, void *p)
433{
434 psi_weak_free (sct);
435
436 return (0);
437}
438
439int psi_clear_weak (psi_img_t *img)
440{
441 int r;
442
443 r = psi_for_all_sectors (img, psi_clear_weak_cb, NULL);
444
445 if (r) {
446 fprintf (stderr, "%s: clearing weak mask failed\n", arg0);
447 }
448
449 return (r);
450}
451
452
453static
454int psi_operation (psi_img_t **img, const char *op, int argc, char **argv)
455{
456 int r;
457 char **optarg;
458
459 if (*img == NULL) {
460 *img = psi_img_new();
461
462 if (*img == NULL) {
463 return (1);
464 }
465 }
466
467 r = -1;
468
469 if (psi_isstr (op, "clear-position", "nopos")) {
470 r = psi_edit_sectors (*img, "position", "-1");
471 }
472 else if (psi_isstr (op, "comment-print", "cp")) {
473 r = psi_show_comment (*img);
474 }
475 else if (strcmp (op, "delete") == 0) {
476 r = psi_delete_sectors (*img);
477 }
478 else if (strcmp (op, "info") == 0) {
479 r = psi_print_info (*img);
480 }
481 else if (strcmp (op, "new") == 0) {
482 r = psi_new (img);
483 }
484 else if (strcmp (op, "sort") == 0) {
485 r = psi_sort_tracks (*img, 0);
486 }
487 else if (strcmp (op, "sort-reverse") == 0) {
488 r = psi_sort_tracks (*img, 1);
489 }
490 else if (strcmp (op, "weak-auto") == 0) {
491 r = psi_auto_weak (*img);
492 }
493 else if (strcmp (op, "weak-clear") == 0) {
494 r = psi_clear_weak (*img);
495 }
496
497 if (r != -1) {
498 return (r);
499 }
500
501 r = pce_getopt (argc, argv, &optarg, opts);
502
503 if ((r != 0) && (r != 'p')) {
504 fprintf (stderr, "%s: bad operation argument (%s)\n",
505 arg0, op
506 );
507 return (1);
508 }
509
510 r = 1;
511
512 if (psi_isstr (op, "comment-add", "ca")) {
513 r = psi_add_comment (*img, optarg[0]);
514 }
515 else if (psi_isstr (op, "comment-load", "cload")) {
516 r = psi_load_comment (*img, optarg[0]);
517 }
518 else if (psi_isstr (op, "comment-save", "csave")) {
519 r = psi_save_comment (*img, optarg[0]);
520 }
521 else if (psi_isstr (op, "comment-set", "cs")) {
522 r = psi_set_comment (*img, optarg[0]);
523 }
524 else if (strcmp (op, "interleave") == 0) {
525 unsigned il;
526
527 il = strtoul (optarg[0], NULL, 0);
528 r = psi_interleave_tracks (*img, il);
529 }
530 else if (strcmp (op, "load") == 0) {
531 r = psi_load_sectors (*img, optarg[0]);
532 }
533 else if (strcmp (op, "regular") == 0) {
534 r = psi_regular (img, optarg[0]);
535 }
536 else if (strcmp (op, "reorder") == 0) {
537 r = psi_reorder_tracks (*img, optarg[0]);
538 }
539 else if (strcmp (op, "rotate") == 0) {
540 unsigned long first;
541
542 first = strtoul (optarg[0], NULL, 0);
543 r = psi_rotate_tracks (*img, first);
544 }
545 else if (strcmp (op, "save") == 0) {
546 r = psi_save_sectors (*img, optarg[0]);
547 }
548 else if (strcmp (op, "tags-load") == 0) {
549 r = psi_load_tags (*img, optarg[0]);
550 }
551 else if (strcmp (op, "tags-save") == 0) {
552 r = psi_save_tags (*img, optarg[0]);
553 }
554 else if (strcmp (op, "weak-load") == 0) {
555 r = psi_load_weak (*img, optarg[0]);
556 }
557 else if (strcmp (op, "weak-save") == 0) {
558 r = psi_save_weak (*img, optarg[0]);
559 }
560 else {
561 fprintf (stderr, "%s: unknown operation (%s)\n", arg0, op);
562 return (1);
563 }
564
565 if (r) {
566 fprintf (stderr, "%s: operation failed (%s)\n", arg0, op);
567 }
568
569 return (r);
570}
571
572
573static
574psi_img_t *psi_load_image (const char *fname)
575{
576 psi_img_t *img;
577
578 if (par_verbose) {
579 fprintf (stderr, "%s: load image from %s\n", arg0, fname);
580 }
581
582 if (strcmp (fname, "-") == 0) {
583 if (par_fmt_inp == PSI_FORMAT_NONE) {
584 fprintf (stderr, "%s: need an input file type\n", arg0);
585 return (NULL);
586 }
587
588 img = psi_load_fp (stdin, par_fmt_inp);
589 }
590 else {
591 img = psi_load (fname, par_fmt_inp);
592 }
593
594 if (img == NULL) {
595 fprintf (stderr, "%s: loading failed (%s)\n", arg0, fname);
596 return (NULL);
597 }
598
599 if (par_list_tracks) {
600 par_list_tracks = 0;
601 psi_list_tracks (img);
602 }
603
604 if (par_list_sectors) {
605 par_list_sectors = 0;
606 psi_list_sectors (img);
607 }
608
609 if (par_print_info) {
610 par_print_info = 0;
611 psi_print_info (img);
612 }
613
614 return (img);
615}
616
617static
618int psi_save_image (psi_img_t **img, const char *fname)
619{
620 int r;
621 unsigned fmt;
622
623 if (par_verbose) {
624 fprintf (stderr, "%s: save image to %s\n", arg0, fname);
625 }
626
627 if (*img == NULL) {
628 *img = psi_img_new();
629
630 if (*img == NULL) {
631 return (1);
632 }
633 }
634
635 if (strcmp (fname, "-") == 0) {
636 fmt = par_fmt_out;
637
638 if (fmt == PSI_FORMAT_NONE) {
639 fmt = PSI_FORMAT_PSI;
640 }
641
642 r = psi_save_fp (stdout, *img, fmt);
643 }
644 else {
645 r = psi_save (fname, *img, par_fmt_out);
646 }
647
648 if (r) {
649 fprintf (stderr, "%s: saving failed (%s)\n",
650 arg0, fname
651 );
652
653 return (1);
654 }
655
656 return (0);
657}
658
659static
660int psi_set_format (const char *name, unsigned *val)
661{
662 if (strcmp (name, "ana") == 0) {
663 *val = PSI_FORMAT_ANADISK;
664 }
665 else if (strcmp (name, "cp2") == 0) {
666 *val = PSI_FORMAT_CP2;
667 }
668 else if (strcmp (name, "dc42") == 0) {
669 *val = PSI_FORMAT_DC42;
670 }
671 else if (strcmp (name, "imd") == 0) {
672 *val = PSI_FORMAT_IMD;
673 }
674 else if (strcmp (name, "mac") == 0) {
675 *val = PSI_FORMAT_MAC;
676 }
677 else if (strcmp (name, "msa") == 0) {
678 *val = PSI_FORMAT_MSA;
679 }
680 else if (strcmp (name, "pfdc") == 0) {
681 *val = PSI_FORMAT_PFDC;
682 }
683 else if (strcmp (name, "pfdc0") == 0) {
684 *val = PSI_FORMAT_PFDC0;
685 }
686 else if (strcmp (name, "pfdc1") == 0) {
687 *val = PSI_FORMAT_PFDC1;
688 }
689 else if (strcmp (name, "pfdc2") == 0) {
690 *val = PSI_FORMAT_PFDC2;
691 }
692 else if (strcmp (name, "pfdc4") == 0) {
693 *val = PSI_FORMAT_PFDC4;
694 }
695 else if (strcmp (name, "psi") == 0) {
696 *val = PSI_FORMAT_PSI;
697 }
698 else if (strcmp (name, "raw") == 0) {
699 *val = PSI_FORMAT_RAW;
700 }
701 else if (strcmp (name, "raw-chs") == 0) {
702 *val = PSI_FORMAT_RAW;
703 }
704 else if (strcmp (name, "raw-hcs") == 0) {
705 *val = PSI_FORMAT_RAW_HCS;
706 }
707 else if (strcmp (name, "raw-hts") == 0) {
708 *val = PSI_FORMAT_RAW_HTS;
709 }
710 else if (strcmp (name, "st") == 0) {
711 *val = PSI_FORMAT_ST;
712 }
713 else if (strcmp (name, "tc") == 0) {
714 *val = PSI_FORMAT_TC;
715 }
716 else if (strcmp (name, "td0") == 0) {
717 *val = PSI_FORMAT_TD0;
718 }
719 else if (strcmp (name, "xdf") == 0) {
720 *val = PSI_FORMAT_XDF;
721 }
722 else {
723 fprintf (stderr, "%s: unknown format (%s)\n", arg0, name);
724 *val = PSI_FORMAT_NONE;
725 return (1);
726 }
727
728 return (0);
729}
730
731int main (int argc, char **argv)
732{
733 int r;
734 char **optarg;
735 psi_img_t *img;
736
737 arg0 = argv[0];
738
739 img = NULL;
740
741 while (1) {
742 r = pce_getopt (argc, argv, &optarg, opts);
743
744 if (r == GETOPT_DONE) {
745 break;
746 }
747
748 if (r < 0) {
749 return (1);
750 }
751
752 switch (r) {
753 case '?':
754 print_help();
755 return (0);
756
757 case 'V':
758 print_version();
759 return (0);
760
761 case 'a':
762 if (psi_parse_range (optarg[0], &par_alt[0], &par_alt[1], &par_alt_all)) {
763 return (1);
764 }
765 break;
766
767 case 'c':
768 if (psi_parse_range (optarg[0], &par_cyl[0], &par_cyl[1], &par_cyl_all)) {
769 return (1);
770 }
771 break;
772
773 case 'D':
774 par_stx_dump_tracks = 1;
775 break;
776
777 case 'e':
778 if (img != NULL) {
779 if (psi_edit_sectors (img, optarg[0], optarg[1])) {
780 return (1);
781 }
782 }
783 break;
784
785 case 'f':
786 if (img != NULL) {
787 psi_print_info (img);
788 }
789 else {
790 par_print_info = 1;
791 }
792 break;
793
794 case 'F':
795 par_filler = strtoul (optarg[0], NULL, 0);
796 break;
797
798 case 'h':
799 if (psi_parse_range (optarg[0], &par_trk[0], &par_trk[1], &par_trk_all)) {
800 return (1);
801 }
802 break;
803
804 case 'i':
805 if (img != NULL) {
806 psi_img_del (img);
807 }
808
809 img = psi_load_image (optarg[0]);
810
811 if (img == NULL) {
812 return (1);
813 }
814 break;
815
816 case 'I':
817 if (psi_set_format (optarg[0], &par_fmt_inp)) {
818 return (1);
819 }
820 break;
821
822 case 'l':
823 if (img != NULL) {
824 psi_list_tracks (img);
825 }
826 else {
827 par_list_tracks = 1;
828 }
829 break;
830
831 case 'L':
832 if (img != NULL) {
833 psi_list_sectors (img);
834 }
835 else {
836 par_list_sectors = 1;
837 }
838 break;
839
840 case 'm':
841 if (img != NULL) {
842 if (psi_merge_image (img, optarg[0])) {
843 return (1);
844 }
845 }
846 else {
847 img = psi_load_image (optarg[0]);
848
849 if (img == NULL) {
850 return (1);
851 }
852 }
853 break;
854
855 case 'n':
856 if (img != NULL) {
857 psi_img_del (img);
858 }
859
860 img = psi_new_image ("dos", optarg[0]);
861
862 if (img == NULL) {
863 return (1);
864 }
865 break;
866
867 case 'N':
868 if (img != NULL) {
869 psi_img_del (img);
870 }
871
872 img = psi_new_image (optarg[0], optarg[1]);
873
874 if (img == NULL) {
875 return (1);
876 }
877 break;
878
879 case 'o':
880 if (psi_save_image (&img, optarg[0])) {
881 return (1);
882 }
883 break;
884
885 case 'O':
886 if (psi_set_format (optarg[0], &par_fmt_out)) {
887 return (1);
888 }
889 break;
890
891 case 'p':
892 if (psi_operation (&img, optarg[0], argc, argv)) {
893 return (1);
894 }
895 break;
896
897 case 'r':
898 if (psi_parse_range (optarg[0], &par_cyl[0], &par_cyl[1], &par_cyl_all)) {
899 return (1);
900 }
901
902 if (psi_parse_range (optarg[1], &par_trk[0], &par_trk[1], &par_trk_all)) {
903 return (1);
904 }
905
906 if (psi_parse_range (optarg[2], &par_sct[0], &par_sct[1], &par_sct_all)) {
907 return (1);
908 }
909 break;
910
911 case 's':
912 if (psi_parse_range (optarg[0], &par_sct[0], &par_sct[1], &par_sct_all)) {
913 return (1);
914 }
915 break;
916
917 case 'S':
918 if (psi_parse_range (optarg[0], &par_rsc[0], &par_rsc[1], &par_rsc_all)) {
919 return (1);
920 }
921 break;
922
923 case 't':
924 if (psi_parse_range (optarg[0], &par_cyl[0], &par_cyl[1], &par_cyl_all)) {
925 return (1);
926 }
927
928 if (psi_parse_range (optarg[1], &par_trk[0], &par_trk[1], &par_trk_all)) {
929 return (1);
930 }
931 break;
932
933 case 'v':
934 par_verbose = 1;
935 break;
936
937 case 'x':
938 par_invert = !par_invert;
939 break;
940
941 case 'z':
942 par_invert = 0;
943 par_cyl_all = 1;
944 par_trk_all = 1;
945 par_sct_all = 1;
946 par_rsc_all = 1;
947 par_alt_all = 1;
948 break;
949
950 case 0:
951 if (img == NULL) {
952 img = psi_load_image (optarg[0]);
953
954 if (img == NULL) {
955 return (1);
956 }
957 }
958 else {
959 if (psi_save_image (&img, optarg[0])) {
960 return (1);
961 }
962 }
963 break;
964
965 default:
966 return (1);
967 }
968 }
969
970 if (img != NULL) {
971 psi_img_del (img);
972 }
973
974 return (0);
975}