1#!/usr/bin/perl 2 3# Copyright 2000-2008 Robert Krawitz <rlk@alum.mit.edu> 4# 5# This program is free software; you can redistribute it and/or modify it 6# under the terms of the GNU General Public License as published by the Free 7# Software Foundation; either version 2 of the License, or (at your option) 8# any later version. 9# 10# This program is distributed in the hope that it will be useful, but 11# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13# for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program. If not, see <https://www.gnu.org/licenses/>. 17 18use Getopt::Std; 19use strict; 20 21getopts('VvO:'); 22 23use vars qw($atend 24 $escpr 25 $stuff 26 $opt_v 27 $opt_V 28 $opt_O 29 $curoffset 30 $curpos 31 $esc 32 $initial_vertical_position 33 $null 34 $page_mgmt_unit 35 $horizontal_position 36 $horizontal_unit 37 $vertical_unit 38 $vertical_position 39 $raster_x 40 $raster_y 41 $print_offsets 42 %seqtable 43 @seqkeys 44 %chartable 45 %xchartable 46 %nchartable 47 %rchartable 48 %keylengths 49 $total_length 50 @offsets); 51 52$atend = 0; 53$escpr = 0; 54%chartable = (); 55%xchartable = (); 56%nchartable = (); 57%rchartable = (); 58%keylengths = (); 59 60%seqtable = ( "@", 0, 61 "(R", "REMOTE", 62 "(", "VARIABLE", 63 "U", 1, 64 "\\", 2, 65 "\$", 2, 66 "r", 1, 67 "\031", 1, 68 ".", "SPECIAL", 69 "i", "SPECIAL1", 70 "\000", 2, 71 "\001", 22 72 ); 73 74map { 75 my ($xchar) = pack("C", $_); 76 if ($_ >= 32 && $_ < 127) { 77 $chartable{$xchar} = " $xchar"; 78 $xchartable{$xchar} = " *$xchar"; 79 $rchartable{$xchar} = $xchar; 80 } else { 81 $chartable{$xchar} = sprintf("%02x", $_); 82 $xchartable{$xchar} = sprintf("*%02x", $_); 83 $rchartable{$xchar} = sprintf("%02x ", $_); 84 } 85 $nchartable{$xchar} = $_; 86} (0..255); 87 88@seqkeys = (sort { length $b <=> length $a } keys %seqtable); 89 90map { $keylengths{$_} = length $_ } @seqkeys; 91 92$esc = "\033"; 93$null = "\000"; 94 95$curpos = 0; 96$curoffset = 0; 97 98$page_mgmt_unit = 360; 99$horizontal_unit = 180; 100$vertical_unit = 360; 101 102$initial_vertical_position = 0; 103$vertical_position = 0; 104$horizontal_position = 0; 105$print_offsets = 0; 106$total_length = 0; 107 108sub get_long($) { 109 my ($string) = @_; 110 my ($tmp) = unpack("V", $string); 111 if ($tmp >= (1 << 31)) { 112 return -(0xffffffff ^ $tmp) - 1; 113 } else { 114 return $tmp; 115 } 116} 117 118sub get_long_at($) { 119 my ($offset) = @_; 120 return get_long(substr($stuff, $curoffset + $offset, 4)) 121} 122 123sub get_short($) { 124 my ($string) = @_; 125 my ($tmp) = unpack("v", $string); 126 if ($tmp >= (1 << 15)) { 127 return -(0xffff ^ $tmp) - 1; 128 } else { 129 return $tmp; 130 } 131} 132 133sub get_raw_at($;$) { 134 my ($offset, $count) = @_; 135 $count = 1 if ! defined $count; 136 return substr($stuff, $curoffset + $offset, $count); 137} 138 139sub get_short_at($) { 140 my ($offset) = @_; 141 return get_short(get_raw_at($offset, 2)) 142} 143 144sub get_byte($) { 145 my ($string) = @_; 146 return $nchartable{substr($string, 0, 1)}; 147} 148 149sub get_byte_at($) { 150 my ($offset) = @_; 151 return get_byte(get_raw_at($offset, 1)) 152} 153 154sub get_blong_at($) { 155 my ($offset) = @_; 156 return get_blong(substr($stuff, $curoffset + $offset, 4)); 157} 158 159sub get_bshort_at($) { 160 my ($offset) = @_; 161 return get_bshort(substr($stuff, $curoffset + $offset, 2)); 162} 163 164sub get_blong($) { 165 my ($string) = @_; 166 my ($tmp) = unpack("N", $string); 167 if ($tmp >= (1 << 31)) { 168 return -(0xffffffff ^ $tmp) - 1; 169 } else { 170 return $tmp; 171 } 172} 173 174sub get_bshort($) { 175 my ($string) = @_; 176 my ($tmp) = unpack("n", $string); 177 if ($tmp >= (1 << 15)) { 178 return -(0xffff ^ $tmp) - 1; 179 } else { 180 return $tmp; 181 } 182} 183 184sub get_string_at($$) { 185 my ($offset, $count) = @_; 186 return join('', map { $rchartable{get_raw_at($offset + $_)}} (0..$count-1)); 187} 188 189sub get_char_at($) { 190 my ($offset) = @_; 191 return $chartable{get_raw_at($offset, 1)}; 192} 193 194sub get_vector_at($$;$) { 195 my ($offset, $count, $nospc) = @_; 196 my ($str) = get_raw_at($offset, $count); 197 if ($nospc) { 198 return sprintf("%*v02x ", $str); 199 } else { 200 return sprintf("%*v02x ", " ", $str); 201 } 202} 203 204sub fill_buffer($) { 205 my ($where) = @_; 206 return 1 if $total_length - $curoffset >= $where; 207 my ($end) = $total_length - $curoffset; 208 if ($curpos == 0 && $end == 0) { 209 $stuff = <>; # Need to do this once to "activate" ARGV 210 $total_length = length $stuff; 211 $end = $total_length - $curoffset; 212 } 213 my ($old_end) = $end; 214 my ($tmp); 215 my ($bytes_to_read) = 16384; 216 if ($where - $end > $bytes_to_read) { 217 $bytes_to_read = $where - $end; 218 } 219 if ($curoffset >= 16384) { 220 substr($stuff, 0, $curoffset) = ""; 221 $total_length -= $curoffset; 222 $curoffset = 0; 223 } 224 while ($end < $where) { 225 my $foo = read ARGV, $tmp, $bytes_to_read; 226 $stuff .= $tmp; 227 $end += $foo; 228 $total_length += $foo; 229 if ($old_end == $end) { 230 $atend = 1; 231 return 0; 232 } else { 233 $bytes_to_read -= $end - $old_end; 234 $old_end = $end; 235 } 236 } 237 return 1; 238} 239 240sub increment_curpos($) { 241 my ($curpos_increment) = @_; 242 $curpos += $curpos_increment; 243 $curoffset += $curpos_increment; 244} 245 246sub print_escpr_data($$$$$) { 247 my ($outbytes, $compression, $bpp, $offset, $expected) = @_; 248 if ($compression == 0) { 249 printf("%*v02x ", " ", substr($stuff, $offset, $outbytes * 3)); 250 if ($expected != $outbytes) { 251 printf "**** Wrong byte count: got %d, expected %d (%x)!!!", $outbytes, $expected, $expected; 252 } 253 } else { 254 my ($totbytes) = 0; 255 my ($orig_outbytes) = $outbytes; 256 while ($outbytes > 0) { 257 my ($place) = $offset + $orig_outbytes - $outbytes; 258 my $counter = ord(substr($stuff, $place, 1)); 259 $place++; 260 $outbytes--; 261 if ($counter <= 127) { 262 $counter++; 263 $counter *= $bpp; 264 $outbytes -= $counter; 265 printf("%*v02x ", " ", substr($stuff, $place, $counter)); 266 } else { 267 $counter = 257 - $counter; 268 $counter *= $bpp; 269 $outbytes -= $bpp; 270 my ($fchar) = sprintf "%*v02x ", " ", substr($stuff, $place, $bpp); 271 my ($outdata); 272 map { $outdata .= $fchar } (0..$counter - 1); 273 print $outdata; 274 } 275 $totbytes += $counter; 276 } 277 $totbytes /= $bpp; 278 if ($totbytes != $expected) { 279 print "**** Wrong byte count: got $totbytes, expected $expected!!!"; 280 } 281 } 282} 283 284sub do_escpr() { 285 my ($print_width, $print_length, $bpp); 286 while (fill_buffer(4)) { 287 printf("\n%08x ", $curpos); 288 my ($cmd) = substr($stuff, $curoffset, 1); 289 my ($ncmd) = $nchartable{$cmd}; 290 printf(" %02x ", $ncmd); 291 increment_curpos(1); 292 if ($cmd ne "$esc") { 293 next; 294 } 295 my ($class) = substr($stuff, $curoffset, 1); 296 printf(" %s ", $class); 297 increment_curpos(1); 298 if ($class eq "@") { 299 return; 300 } 301 my ($skipchars) = get_long(substr($stuff, $curoffset + 0, 4)); 302 printf " %08x ", $skipchars; 303 increment_curpos(4); 304 fill_buffer(4); 305 my ($remaining) = $skipchars; 306 $cmd = substr($stuff, $curoffset + 0, 4); 307 printf(" %4s ", $cmd); 308 increment_curpos(4); 309 fill_buffer($skipchars); 310 if ($cmd eq "setq") { # Set Quality 311 my (@qualities) = qw(draft normal high); 312 my (@colormono) = qw(color mono); 313 my (@colordepth) = qw(24 8); 314 printf("%*v02x ", " ", substr($stuff, $curoffset + 0, $skipchars)); 315 if ($opt_v) { 316 printf(" (Set Quality: Media: %02x Quality: %s Color: %s Brightness: %02x Contrast: %02x Saturation: %02x Color Depth: %x (%s) Palette Size: %04x)", 317 get_byte_at(0), 318 $qualities[get_byte_at(1)], 319 $colormono[get_byte_at(2)], 320 get_byte_at(3), 321 get_byte_at(4), 322 get_byte_at(5), 323 get_byte_at(6), 324 $colordepth[get_byte_at(6)], 325 get_short_at(7)); 326 } 327 $bpp = get_byte_at(6) ? 1 : 3; 328 increment_curpos($skipchars); 329 } elsif ($cmd eq "setj") { # Set Job 330 my (@resolution) = qw(360 720); 331 my (@direction) = qw(bi uni); 332 printf("%*v02x ", " ", substr($stuff, $curoffset + 0, $skipchars)); 333 if ($opt_v) { 334 printf(" (Set Job: Paper (%d %d) (%.1f %.1f) Top %d Left %d Printable (%d %d) (%.2f %.2f) In Resolution %s Direction %s)", 335 get_blong_at(0), 336 get_blong_at(4), 337 get_blong_at(0) / $resolution[get_byte_at(20)], 338 get_blong_at(4) / $resolution[get_byte_at(20)], 339 get_bshort_at(8), 340 get_bshort_at(10), 341 get_blong_at(12), 342 get_blong_at(16), 343 get_blong_at(12) / $resolution[get_byte_at(20)], 344 get_blong_at(16) / $resolution[get_byte_at(20)], 345 $resolution[get_byte_at(20)], 346 $direction[get_byte_at(21)]); 347 } 348 $print_width = get_blong_at(12); 349 $print_length = get_blong_at(16); 350 increment_curpos($skipchars); 351 } elsif ($cmd eq "sttp") { # Start Page 352 printf("%*v02x ", " ", substr($stuff, $curoffset + 0, $skipchars)); 353 } elsif ($cmd eq "dsnd") { # Data Send 354 printf("%*v02x ", " ", substr($stuff, $curoffset + 0, 7)); 355 if ($opt_v) { 356 printf(" (Send Data: Offset (%d %d) Compression %d Size %d) ", 357 get_bshort_at(0), 358 get_bshort_at(2), 359 get_byte_at(4), 360 get_bshort_at(5)); 361 } 362 if ($opt_V) { 363 print_escpr_data(get_bshort_at(5), get_byte_at(4), $bpp, $curoffset + 7, $print_width); 364 increment_curpos($skipchars); 365 } else { 366 increment_curpos($skipchars); 367 } 368 } elsif ($cmd eq "bsnd") { # Data Send -- ??? 369 printf("%*v02x ", " ", substr($stuff, $curoffset + 0, 34)); 370 my ($data_size) = get_blong_at(18) + get_blong_at(22) + get_blong_at(26); 371 if ($opt_v) { 372 printf(" (Send Data: Offset (%d %d) Compression %d Size %d %d %d = %x, delta = %x) ", 373 get_bshort_at(3), 374 get_bshort_at(5), 375 get_byte_at(7), 376 get_blong_at(18), 377 get_blong_at(22), 378 get_blong_at(26), 379 $data_size, 380 $skipchars - ($data_size + 42)) 381 } 382 if ($opt_V) { 383 print_escpr_data($data_size, get_byte_at(7), $bpp, $curoffset + 34, $print_width); 384 } 385 increment_curpos($skipchars); 386 } elsif ($cmd eq "endp") { # End Page 387 printf("%*v02x ", " ", substr($stuff, $curoffset + 0, $skipchars)); 388 increment_curpos($skipchars); 389 } elsif ($cmd eq "endj") { # End Job 390 printf("%*v02x ", " ", substr($stuff, $curoffset + 0, $skipchars)); 391 increment_curpos($skipchars); 392 } else { 393 printf("%*v02x ", " ", substr($stuff, $curoffset + 0, $skipchars)); 394 increment_curpos($skipchars); 395 } 396 } 397} 398 399sub print_remote_SN($) { 400 my ($skipchars) = @_; 401 if ($skipchars == 1) { 402 print(" (Setup)"); 403 } elsif ($skipchars == 3) { 404 my ($subcmd) = get_byte_at(1); 405 my ($arg) = get_byte_at(2); 406 if ($subcmd == 0) { 407 print(" (Feed Sequence $arg)"); 408 } elsif ($subcmd == 4) { 409 print(" (Feed Adjustment $arg)"); 410 } elsif ($subcmd == 5) { 411 print(" (Vacuum Intensity $arg)"); 412 } else { 413 print(" (Unknown command $subcmd, arg $arg)"); 414 } 415 } else { 416 print(" (Unknown command)"); 417 } 418} 419 420sub print_remote_DR($) { 421 my ($skipchars) = @_; 422 if ($skipchars == 4) { 423 my ($subcmd) = get_byte_at(1); 424 my ($arg) = get_short_at(2); 425 if ($subcmd == 0) { 426 printf(" (Scan dry time %.1f)", $arg / 10.0); 427 } elsif ($subcmd == 1) { 428 printf(" (Page dry time %.1f)", $arg / 10.0); 429 } elsif ($subcmd == 0x40) { 430 printf(" (Scan minimum dry time %.1f)", $arg / 10.0); 431 } else { 432 print(" (Unknown command $subcmd, arg $arg)"); 433 } 434 } else { 435 print(" (Unknown command)"); 436 } 437} 438 439sub print_remote_CO($) { 440 my ($skipchars) = @_; 441 if ($skipchars == 8) { 442 my ($cmd) = get_byte_at(2); 443 my ($arg) = get_long_at(4); 444 if ($cmd == 0) { 445 print(" (cut)"); 446 } elsif ($cmd == 1) { 447 print(" (cut all at $arg)"); 448 } elsif ($cmd == 2) { 449 print(" (cut last at $arg)"); 450 } else { 451 print(" (Unknown command $cmd)"); 452 } 453 } else { 454 print(" (unknown command)"); 455 } 456} 457 458sub print_remote_MI($) { 459 my ($skipchars) = @_; 460 if ($skipchars == 4) { 461 my ($media) = get_byte_at(2); 462 my ($size) = get_byte_at(3); 463 print(" (Media type $media, size code $size)"); 464 } else { 465 print(" (unknown command)"); 466 } 467} 468 469sub print_remote_DP($) { 470 my ($skipchars) = @_; 471 if ($skipchars == 2) { 472 my ($cmd) = get_byte_at(1); 473 if ($cmd == 0) { 474 print(" (no duplex)"); 475 } elsif ($cmd == 1) { 476 print(" (duplex no tumble)"); 477 } elsif ($cmd == 2) { 478 print(" (duplex tumble)"); 479 } else { 480 print(" (unknown duplex command $cmd)"); 481 } 482 } else { 483 print(" (unknown command)"); 484 } 485} 486 487sub print_remote_PH($) { 488 my ($skipchars) = @_; 489 if ($skipchars == 2) { 490 my ($thickness) = get_byte_at(1); 491 print(" (Paper thickness $thickness)"); 492 } else { 493 print(" (unknown command)"); 494 } 495} 496 497sub print_remote_US($) { 498 my ($skipchars) = @_; 499 if ($skipchars == 3) { 500 my ($cmd) = get_byte_at(1); 501 my ($arg) = get_byte_at(2); 502 if ($cmd == 1) { 503 print(" (Platen gap $arg)"); 504 } else { 505 print(" (Unknown command $cmd, arg $arg)"); 506 } 507 } else { 508 print(" (unknown command)"); 509 } 510} 511 512sub print_remote_FP($) { 513 my ($skipchars) = @_; 514 if ($skipchars == 3) { 515 my ($offset) = get_short_at(1); 516 print(" (Full bleed, offset $offset)"); 517 } else { 518 print(" (unknown command)"); 519 } 520} 521 522sub print_remote_IK($) { 523 my ($skipchars) = @_; 524 if ($skipchars == 2) { 525 my ($ink_type) = get_byte_at(1); 526 my ($ink) = $ink_type >= 0x80 ? "matte" : "photo"; 527 print(" (Ink type $ink_type, probably $ink)"); 528 } else { 529 print(" (unknown command)"); 530 } 531} 532 533sub print_remote_JS($) { 534 my ($skipchars) = @_; 535 print(" (Job start)"); 536} 537 538sub print_remote_JE($) { 539 my ($skipchars) = @_; 540 print(" (Job end)"); 541} 542 543sub print_remote_PP($) { 544 my ($skipchars) = @_; 545 print(" (Set input slot, printer-specific)"); 546} 547 548sub do_remote() { 549 while (fill_buffer(2) && get_raw_at(0, 2) =~ /[A-Z0-9][A-Z0-9]/) { 550 printf "\n%08x ", $curpos; 551 my ($cmd) = get_raw_at(0, 2); 552 print $cmd; 553 increment_curpos(2); 554 fill_buffer(2); 555 my $nlchar = get_byte_at(0); 556 my $nhchar = get_byte_at(1); 557 my $skipchars; 558 if ($cmd eq "DF") { 559 $skipchars = 0; 560 } else { 561 $skipchars = ($nhchar * 256) + $nlchar; 562 } 563 printf(" %02x %02x ", $nlchar, $nhchar); 564 increment_curpos(2); 565 fill_buffer($skipchars); 566 print get_vector_at(0, $skipchars); 567 if ($opt_v) { 568 if (eval "defined \&print_remote_$cmd") { 569 map { print(" "); } ($skipchars...5) if ($skipchars < 6); 570 eval "print_remote_$cmd($skipchars)"; 571 } 572 } 573 increment_curpos($skipchars); 574 } 575} 576 577sub do_remote_command() { 578 printf "\n%08x 1b ( R ", $curpos; 579 increment_curpos(3); 580 fill_buffer(2); 581 my ($nlchar) = get_byte_at(0); 582 my ($nhchar) = get_byte_at(1); 583 my $skipchars = ($nhchar * 256) + $nlchar; 584 increment_curpos(2); 585 fill_buffer($skipchars); 586 my $rstring = get_string_at(0, $skipchars); 587 print $rstring; 588 increment_curpos($skipchars); 589 if ($rstring eq "00 ESCPR") { 590 do_escpr(); 591 } else { 592 do_remote(); 593 } 594} 595 596sub print_prefix_bytes($$) { 597 my ($bytes_to_print) = @_; 598 printf "\n%08x 1b ", $curpos; 599 fill_buffer($bytes_to_print); 600 print get_char_at(1), " ", get_vector_at(2, $bytes_to_print - 2); 601 increment_curpos($bytes_to_print); 602} 603 604sub print_output_data($$$$$$) { 605 my ($comptype, $bitsperpixel, $dots, $rows, $dot_scale, $color) = @_; 606 my $counter; 607 my $fchar; 608 my $last_row = 0; 609 my $first_row = -1; 610 my $i; 611 my $vstuff; 612 $dots *= 8; 613 $dots /= $dot_scale; 614 my $real_dots = $dots / $bitsperpixel; 615 if ($opt_v) { 616 my ($xcolor) = sprintf("%02x", $color); 617 print " ($xcolor color $real_dots dots, $rows rows, $bitsperpixel bits"; 618 } 619 my $savedots = $dots; 620 if ($comptype == 0) { 621 foreach $i (0..$rows-1) { 622 fill_buffer($dots / 8); 623 print get_vector_at(0, $dots / 8) if ($opt_V); 624 increment_curpos($dots / 8); 625 } 626 } elsif ($comptype == 1) { 627 foreach $i (0..$rows-1) { 628 my ($found_something) = 0; 629 $dots = $savedots / 8; 630 my ($tstuff) = "\n $i "; 631 while ($dots > 0) { 632 if ($total_length - $curoffset < 1) { 633 fill_buffer(1); 634 } 635 $counter = ord(substr($stuff, $curoffset + 0, 1)); 636 $curpos++; 637 $curoffset++; 638 if ($counter <= 127) { 639 $counter++; 640 if ($total_length - $curoffset < $counter) { 641 fill_buffer($counter); 642 } 643 if ($opt_V || ($opt_v && ! $found_something)) { 644 my $tmp = get_vector_at(0, $counter); 645 if (!($tmp =~ /^[0 ]+$/)) { 646 $found_something = 1; 647 $last_row = $i; 648 if ($first_row == -1) { 649 $first_row = $i; 650 } 651 } 652 if ($opt_V) { 653 $tstuff .= $tmp; 654 } 655 } 656 $curpos += $counter; 657 $curoffset += $counter; 658 } else { 659 $counter = 257 - $counter; 660 if ($total_length - $curoffset < 1) { 661 fill_buffer(1); 662 } 663 if ($opt_v) { 664 if (! $found_something) { 665 my $tbyte = get_raw_at(0, 1); 666 if ($tbyte != 0) { 667 $found_something = 1; 668 $last_row = $i; 669 if ($first_row == -1) { 670 $first_row = $i; 671 } 672 } 673 } 674 } elsif ($opt_V) { 675 $fchar = sprintf "%v02x ", get_raw_at(0, 1); 676 if ($fchar ne "00 ") { 677 $found_something = 1; 678 $last_row = $i; 679 if ($first_row == -1) { 680 $first_row = $i; 681 } 682 } 683 map { $tstuff .= $fchar } (0..$counter - 1); 684 } 685 $curpos++; 686 $curoffset++; 687 } 688 $dots -= $counter; 689 } 690 if ($opt_V && $found_something) { 691 $vstuff .= $tstuff; 692 } 693 } 694 } else { 695 print "\nUnknown compression type $comptype!\n"; 696 } 697 if ($opt_v) { 698 my ($offset) = $offsets[$color]; 699 my ($first_position) = ($vertical_position / $vertical_unit) 700 + ($first_row + $offset) * $raster_y; 701 my ($last_position) = ($vertical_position / $vertical_unit) 702 + ($last_row + $offset) * $raster_y; 703 my ($final_position) = ($vertical_position / $vertical_unit) 704 + ($rows + $offset) * $raster_y; 705 my ($final_horizontal) = $horizontal_position + 706 ($real_dots * $page_mgmt_unit * $raster_x); 707 if ($print_offsets) { 708 printf (" %d,%d+%d %.4f %d,%d+%d %.4f %.4f) ", 709 $horizontal_position, $first_row, $offset, $first_position, 710 $final_horizontal, $last_row, $offset, $last_position, 711 $final_position); 712 } else { 713 printf (" %d,%d %.4f %d,%d %.4f %.4f) ", 714 $horizontal_position, $first_row, $first_position, 715 $final_horizontal, $last_row, $last_position, 716 $final_position); 717 } 718 } 719 if ($opt_V) { 720 print " $vstuff"; 721 } 722} 723 724sub purge_line() { 725 fill_buffer(1); 726 while (get_raw_at(0) eq "\r") { 727 fill_buffer(1); 728 increment_curpos(1); 729 } 730} 731 732sub do_special_command() { 733 fill_buffer(8); 734 my $comptype = get_byte_at(2); 735 my $color = 0; 736 my $dots = get_short_at(6); 737 my $rows = get_byte_at(5); 738 print_prefix_bytes(8, 2); 739 print_output_data($comptype, 1, $dots, $rows, 8, $color); 740 purge_line(); 741} 742 743sub do_special1_command() { 744 fill_buffer(9); 745 my $color = get_byte_at(2); 746 my $comptype = get_byte_at(3); 747 my $bitsperpixel = get_byte_at(4); 748 my $dots = get_short_at(5); 749 my $rows = get_short_at(7); 750 print_prefix_bytes(9, 1); 751 print_output_data($comptype, $bitsperpixel, $dots, $rows, 1, $color); 752 purge_line(); 753} 754 755if ($opt_O) { 756 my (@stuff) = split(/,/, $opt_O); 757 map { 758 my ($key, $val) = split(/=/, $_); 759 if ($val) { 760 $print_offsets = 1; 761 } 762 @offsets[$key] = $val; 763 } @stuff; 764} 765 766sub indent_cmd($) { 767 my ($skipchars) = @_; 768 map { print(" "); } ($skipchars...3) if ($skipchars < 4); 769} 770 771sub do_xcmd_c($) { 772 my ($skipchars) = @_; 773 my ($top, $bottom); 774 if ($skipchars == 8) { 775 $top = get_long_at(5); 776 $bottom = get_long_at(9) if ($opt_v); 777 } else { 778 $top = get_short_at(5); 779 $bottom = get_short_at(7) if ($opt_v); 780 } 781 if ($opt_v) { 782 printf (" (page format %d %d %.2f %.2f)", $top, $bottom, 783 $top / $page_mgmt_unit, $bottom / $page_mgmt_unit); 784 } 785 $initial_vertical_position = $top * $vertical_unit / $page_mgmt_unit; 786 $vertical_position = $initial_vertical_position; 787} 788 789sub do_xcmd_S($) { 790 my ($skipchars) = @_; 791 if ($opt_v) { 792 my ($width, $height); 793 if ($skipchars == 8) { 794 $width = get_long_at(5); 795 $height = get_long_at(9); 796 } else { 797 $width = get_short_at(5); 798 $height = get_short_at(7); 799 } 800 indent_cmd($skipchars); 801 printf (" (paper size %d %d %.2f %.2f)", $width, $height, 802 $width / $page_mgmt_unit, $height / $page_mgmt_unit); 803 } 804} 805 806sub do_xcmd_C($) { 807 my ($skipchars) = @_; 808 if ($opt_v) { 809 my ($length); 810 if ($skipchars == 4) { 811 $length = get_long_at(5); 812 } else { 813 $length = get_short_at(5); 814 } 815 indent_cmd($skipchars); 816 printf (" (page length %d %.2f)", $length, $length / $page_mgmt_unit); 817 } 818} 819 820sub do_xcmd_D($) { 821 my ($skipchars) = @_; 822 my $base = get_short_at(5); 823 my $y = get_byte_at(7); 824 my $x = get_byte_at(8); 825 $raster_x = $x / $base; 826 $raster_y = $y / $base; 827 if ($opt_v) { 828 indent_cmd($skipchars); 829 printf (" (raster base %d, %d x %d)", $base, $base / $x, $base / $y); 830 } 831} 832 833sub do_xcmd_U($) { 834 my ($skipchars) = @_; 835 my $page_mgmt = get_byte_at(5); 836 if ($skipchars == 5) { 837 my $vertical = get_byte_at(6); 838 my $horiz = get_byte_at(7); 839 my $scale = get_short_at(8); 840 $page_mgmt_unit = $scale / $page_mgmt; 841 $horizontal_unit = $scale / $horiz; 842 $vertical_unit = $scale / $vertical; 843 if ($opt_v) { 844 indent_cmd($skipchars); 845 printf (" (units base %d mgmt %d vert %d horiz %d)", 846 $scale, $page_mgmt_unit, $vertical_unit, $horizontal_unit); 847 } 848 } else { 849 if ($opt_v) { 850 indent_cmd($skipchars); 851 printf " (units base = %d/3600)", $page_mgmt; 852 } 853 $page_mgmt_unit = 3600 / $page_mgmt; 854 $horizontal_unit = 3600 / $page_mgmt; 855 $vertical_unit = 3600 / $page_mgmt; 856 } 857} 858 859sub do_xcmd_v($) { 860 my ($skipchars) = @_; 861 my ($length); 862 if ($skipchars == 4) { 863 $length = get_long_at(5); 864 } else { 865 $length = get_short_at(5); 866 } 867 $vertical_position += $length; 868 if ($opt_v) { 869 indent_cmd($skipchars); 870 printf (" (skip vertical %d at %d %.4f)", $length, $vertical_position, 871 $vertical_position / $vertical_unit); 872 } 873} 874 875sub do_xcmd_dlr($) { 876 my ($skipchars) = @_; 877 if ($skipchars == 4) { 878 $horizontal_position = get_long_at(5); 879 } else { 880 $horizontal_position = get_short_at(5); 881 } 882 if ($opt_v) { 883 indent_cmd($skipchars); 884 printf (" (horizontal position %d %.4f)", 885 $horizontal_position, $horizontal_position / $horizontal_unit); 886 } 887} 888 889sub do_xcmd_d($) { 890 my ($skipchars) = @_; 891 if ($opt_v) { 892 my ($bytes) = get_short_at(3); 893 indent_cmd($skipchars); 894 printf " (nop $bytes bytes)"; 895 } 896} 897 898sub do_xcmd_m($) { 899 my ($skipchars) = @_; 900 if ($opt_v) { 901 indent_cmd($skipchars); 902 printf(" (print method %x)", get_byte_at(5)); 903 } 904} 905 906sub do_xcmd_e($) { 907 my ($skipchars) = @_; 908 if ($opt_v) { 909 indent_cmd($skipchars); 910 printf(" (dot size %x)", get_byte_at(6)); 911 } 912} 913 914sub do_xcmd_G($) { 915 my ($skipchars) = @_; 916 if ($opt_v) { 917 indent_cmd($skipchars); 918 print(" (set graphics mode)"); 919 } 920} 921 922sub do_xcmd_K($) { 923 my ($skipchars) = @_; 924 if ($opt_v) { 925 indent_cmd($skipchars); 926 my ($ctype) = get_byte_at(6); 927 if ($ctype == 1) { 928 print(" (BW mode)"); 929 } elsif ($ctype == 2) { 930 print(" (Color mode)"); 931 } elsif ($ctype == 3) { 932 print(" (Fast 360 color mode)"); 933 } else { 934 print(" (Unknown BW/color mode)"); 935 } 936 } 937} 938 939sub do_xcmd_i($) { 940 my ($skipchars) = @_; 941 if ($opt_v) { 942 indent_cmd($skipchars); 943 my ($ctype) = get_byte_at(5); 944 if ($ctype == 0) { 945 print(" (Soft weave)"); 946 } else { 947 printf(" (Printer weave method %d)", $ctype); 948 } 949 } 950} 951 952while (! $atend) { 953 my $found; 954 my $skipchars; 955 my $startoff; 956 my $bytes; 957 my ($maxklen) = $keylengths{$seqkeys[0]}; 958 fill_buffer(1); 959 my $cchar = get_raw_at(0); 960 if ($cchar eq "$esc") { 961 $found = 0; 962 fill_buffer(2 + $maxklen); 963 foreach my $key (@seqkeys) { 964 my ($klen) = $keylengths{$key}; 965 if (get_raw_at(1, $klen) eq $key) { 966 $skipchars = $seqtable{$key}; 967 if ($skipchars eq "SPECIAL") { 968 do_special_command(); 969 $found = 2; 970 } elsif ($skipchars eq "SPECIAL1") { 971 do_special1_command(); 972 $found = 2; 973 } elsif ($skipchars eq "REMOTE") { 974 do_remote_command(); 975 $found = 2; 976 } else { 977 printf "\n%08x 1b ", $curpos; 978 $startoff = 0; 979 my $print_stuff = 0; 980 my $print_variable = 0; 981 if ($skipchars eq "VARIABLE") { 982 fill_buffer(3); 983 $print_variable = 1; 984 my $nlchar = get_byte_at($klen + 2); 985 my $nhchar = get_byte_at($klen + 3); 986 $skipchars = ($nhchar * 256) + $nlchar; 987 $startoff = 3; 988 $print_stuff = 1; 989 } 990 my ($blen) = $skipchars + $klen + $startoff; 991 fill_buffer($blen + 1); 992 print get_char_at(1), " "; 993 if ($blen > 1) { 994 my $char = get_raw_at(2); 995 print get_char_at(2), " "; 996 if ($blen > 2) { 997 if ($print_variable && $char eq "d") { 998 print get_vector_at(3, 2); 999 } else { 1000 print get_vector_at(3, $blen - 2); 1001 } 1002 } 1003 } 1004 if ($print_stuff) { 1005 my $xchar = get_raw_at(2); 1006 if ($xchar eq '$') { 1007 $xchar = 'dlr'; 1008 } 1009 if (eval defined "defined do_xcmd_$xchar") { 1010 eval "do_xcmd_$xchar($skipchars)"; 1011 } 1012 } 1013 $found = 1; 1014 } 1015 $bytes = $klen + 1 + $skipchars + $startoff; 1016 last; 1017 } 1018 } 1019 if (! $found) { 1020 printf "\n%08x 1b ", $curpos; 1021 increment_curpos(1); 1022 } elsif ($found == 1) { 1023 increment_curpos($bytes); 1024 } 1025 } elsif ($cchar eq "\0" || $cchar eq "\f") { 1026 printf "\n%08x $chartable{$cchar} ", $curpos; 1027 $vertical_position = $initial_vertical_position; 1028 increment_curpos(1); 1029 } else { 1030 print "$xchartable{$cchar} " if ($cchar ne "\021"); 1031 increment_curpos(1); 1032 } 1033} 1034 1035print "\n" if $curpos > 1; 1036