[comp.lang.postscript] The eexec encoder/decoder and peek operator

ifarqhar@mqccsunc.mqcc.mq.OZ (Ian Farquhar) (12/20/89)

In response to the requests for both the peek operator and the eexec encoder/
decoder package, I include the following reposts.  Sorry about the length.


From: cnwietho@immd4.informatik.uni-erlangen.de (Carsten Wiethoff)
Subject: The peek operator (rather long)
Keywords: peek operator eexec cexec
Organization: IMMD IV, University of Erlangen, W-Germany

Hi folks!

This is for those who always wanted to know every single bit of their
PostScript(tm) laser printer: THE "peek" OPERATOR!

It is one of the most trivial applications of the "cexec" operator.
Since the program is written in 680x0 assembler and depends on the Adobe
"cexec" interface it should run only on laser printers with such a CPU
and a PostScript(tm) interpreter from Adobe or compatible to Adobe's .
(are there any others?)

Ah, before I forget it:
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
It may or may not be legal to run this program with the intent to
read out the contents of the ROMs, since these probably(?) contain
copyrighted data. I DO NOT ENCOURAGE YOU TO USE THIS PROGRAM TO READ
OUT COPYRIGHTED DATA! When you are in doubt, see your local law-guru.
When you are still in doubt, don't use this program. Otherwise enjoy!
END OF WARNING

First comes the assembler source file as an example of an operator
definition written in assembler. At the end is the operator definition
in eexec/cexec format ready to "print" together with some examples.
The assembler program was written on a SUN 3. Other assemblers may differ.
To change the program and convert it to eexec/cexec format you will 
have to do the following: (there may be more elegant ways)
- assemble it (using "as"), having the checksum set to 0x0000.
- strip symbols (if any) and the a.out header (32 bytes on a SUN 3).
- calculate the checksum (0x10000 - the 16 bit sum of the program).
- write the checksum into the program and reassemble
- strip it again
- construct a file with the following contents:
<BEGIN here vvv>
currentfile <length of stripped a.out file> string readstring
<stripped a.out file>
{cexec} {pop ioerror} ifelse
currentfile closefile
<END here ^^^>
- convert this file to eexec format using the algorithm I described 
  some time ago in this newsgroup (actually you will have to use the
  inverse algorithm of the one that I described). If you don't have this,
  send email. If there is enough interest I will post a C program that 
  does the job.
- print it

So here goes the assembler source:
----------------------------------cut here -------------------------------
| This is a peek program written by Carsten Wiethoff 1989
| You may do with it what you want, as long as my name stays in it.
| It may look a little weird, 
| since I adapted some of the Adobe calling conventions
|
first:          .word   0x07a2          | checksum
                .word   0x3399
                .word   last-first      | total length
                .word   0x0001
                .word   0x0402
                .word   entry-first     | entry point
                .word   reloc-first     | begin of relocation table
                .word   reloc-relocend  | end of relocation table

entry:
                movl    sp@(4),a0
                lea     arg1,a1
                movl    a0,a1@+
                movl    a0@+,a1@+
                movl    a0@+,a1@+
                movl    a0@+,a1@+
                bra     main

peek:           linkw   a6,#0
                bsr     pop_int         | pop address
                movl    d0,a0
                clrl    d0
                movb    a0@,d0          | access byte
                movl    d0,sp@-         | push value
                movl    #0x01020000,sp@-| push object descriptor
                                        | 01=integer, 02=no exec perm.
                bsr     push_general    | push on postscript stack
                addqw   #8,sp
                unlk    a6
                rts

main:           linkw   a6,#0
                bsr     userdict
                movl    d0,a0
                movl    a0@(4),sp@-
                movl    a0@,sp@-
                bsr     begindict
                addqw   #8,sp
                pea     peek
                pea     stringpeek
                bsr     defineop
                addqw   #8,sp
                bsr     enddict
                unlk    a6
                rts

stringpeek:             .asciz  "peek"

| system jump ins go here
| The names reflect my opinion about what these routines do.
| I have no documentation about these routines, so reality may differ.
                .even
begindict:      movw    #0x50,a0
                bra     jump
enddict:        movw    #0x80,a0
                bra     jump
userdict:       movw    #0xa0,a0
                bra     jump
pop_int:        movw    #0xe0,a0
                bra     jump
push_general:   movw    #0xf4,a0
                bra     jump
defineop:       movw    #0x11c,a0
                bra     jump

jump:           addl    arg2,a0
                movl    a0@,a0
                jmp     a0@

                .align  2
arg1:           .long           0
arg2:           .long           0       | system entry table
arg3:           .long           0
arg4:           .long           0

                .align  2
reloc:                                  | relocation table
relocend:       .word 0x0000
last:

------------------------- cut here ------------------------------------
Here finally comes the ready-to-print version:
--------------------------- cut here ----------------------------------
%!
% This is the peek operator written by Carsten Wiethoff 1989
% You may do with it what you want, as long as my name stays in it.
currentfile eexec
c3c703843e75cc772962e3a7fadee742b39452c3b503845648fbd351ba27c4a1
0682e041c9fa0f16614f0c04877181ee76d9e6bd87dd247a2857ccb6913dfcc1
123775eeaaab500a019e4b76d978c6e8d2383c16ed2a02acd8642efa2196cff7
dd72fc7834e096060b4259609b4a5fe03e1bce5f86e8bde12c8cdc7ee13437bc
9f1006f84253a13ed0cb41556b44df020c314ff99564f537fd0460bf77c5ac7c
a1eecc3271f4caf473668cf7c41f60b4a6702411a68490f25a96700051b3545b
91abd0161e7260f62ef55f7ab6d4e850c6e745666d29e50b045b19e96b01de4b
c5e24a59fd822ce839a8769b3830615de0781dcb0ba368ca3c8f5ca2e281149b
1a17dff0db3506609bc70393ec8f6482d798654cc171370f0b
% the previous is equivalent to 
% /peek {<function>} def
% usage: <address:integer> peek -> <byte:integer>

% example:
16#00000000 peek ==

% more useful:

(start\n)print
/str 2 string def
/nullstr (00) def
/outstr 2 string def

/byte2hex
  {
    outstr 0 nullstr putinterval
    outstr exch
    16 str cvrs
    dup length 2 exch sub exch
    putinterval
    outstr
  }
def

16#40000000 1 16#4000000f 
  {
    peek 
    byte2hex
    print
    (\n)print
  }
for

------------------------- cut here -------------------------------------

The writing of the "poke" operator, when desired, is left as an exercise
for the reader.

Enjoy and remember the warning!

                                Carsten Wiethoff
                                c/o Frank Kardel

                                Friedrich-Alexander Universitaet
                                Erlangen-Nuernberg
                                
                                CS Department IMMD IV
                                Martensstrasse 1
                                D-8520 Erlangen
                                ---------------
                                West Germany

Voice: +49/(0)9131/85-7908
E-mail: cnwietho@immd4.informatik.uni-erlangen.de

Private:                        Carsten Wiethoff
                                Untere Karlstr.7
                                D-8520 Erlangen
                                West Germany

                                Tel.: +49/(0)9131/29136



From: cnwietho@immd4.informatik.uni-erlangen.de (Carsten Wiethoff)
Subject: Postscript <-> eexec conversion programs
Reply-To: cnwietho@medusa.UUCP ()
Organization: CSD., University of Erlangen, W - Germany

Hi!

For all who have missed my description of the eexec-algorithm some
time ago (or who were not able to make a program from it ;-) I post
two little C-programs that convert postscript to eexec format and
vice versa.
ps2eexec.c is especially useful to convert machine code using the cexec
operator to eexec format.

BTW it might be interesting to know that this algorithm (using different
initial values) is used in the Adobe font format as well. So if these rumours
about Adobe publishing their font format are true, we should see a similar thingfrom Adobe soon.

This is ps2eexec.c:
----------------------------------- cut here ----------------------------
/* Quickie to convert postscript from stdin to eexec format on stdout */

#include <stdio.h>

static unsigned short buffer = 0xd971;
static unsigned long startup = 0x00000000; /* or whatever you want */

main()
{
  unsigned char input;
  unsigned char output;
  int init = 4;
  int i;
  int result;

  printf("%08x",startup);
  for (i=0;i<4;++i)
    {
      input = (startup >> ((3-i)*8));
      buffer = (input + buffer) * 0xce6d + 0x58bf;
    }  

  for(;;)
    {
      for (i=0;i<(32-init);++i)
        {
          result = getchar();
          if (result == EOF)
            break;
          output = (input ^ (buffer>>8));
          buffer = (output + buffer) * 0xce6d + 0x58bf;
          printf("%02x",output);
        }
      init = 0;
      printf("\n");
      if (input == EOF)
        break;
    }
}
----------------------------- cut here ----------------------------------

This is eexec2ps.c:
------------------------------ cut here ----------------------------------

/* Quickie to convert eexec format from stdin to postscript on stdout */

#include <stdio.h>

/* Written by Carsten Wiethoff 1989 */
/* You may do what you want with this code, 
   as long as this notice stays in it */

static unsigned short buffer = 0xd971;

main()
{
  unsigned int input;
  char output;
  int ignore = 4;
  int result;

  do
    {
      result = scanf(" %2x",&input);
      if ( (result == EOF) || (result == 0) )
        break;
      output = input ^ (buffer>>8);
      buffer = (input + buffer) * 0xce6d + 0x58bf;
      if ( ignore > 0 ) 
        {
          ignore--;
        }
      else
        {
          printf("%c",output);
        }
    } while (1);
}
      
-------------------------------- cut here --------------------------------      




                                Carsten Wiethoff
                                c/o Frank Kardel

                                Friedrich-Alexander Universitaet
                                Erlangen-Nuernberg
                                
                                CS Department IMMD IV
                                Martensstrasse 1
                                D-8520 Erlangen
                                ---------------
                                West Germany

Voice: +49/(0)9131/85-7908
E-mail: cnwietho@immd4.informatik.uni-erlangen.de

Private:                        Carsten Wiethoff
                                Untere Karlstr.7
                                D-8520 Erlangen
                                West Germany

                                Tel.: +49/(0)9131/29136



I hope that satisfies you folks.  The peek operator is very useful, though
I have no idea how it was derived (thanks anyway, Carsten!)

I will repeat the warning above about hacking.  Check with your legal people
before proceeding.

Disclaimer:   My opinions do not necessarily coincide with those of
              my employers.

Ian Farquhar
Sydney, Australia.

D