fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 975 lines 20 kB view raw
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}