[comp.sys.handhelds] Chip-8 for Suns

moews@math.berkeley.edu (David Moews) (11/01/90)

This is a rudimentary Chip-8 interpreter for Suns.  See the README file for more
details.
--
David Moews                             moews@math.berkeley.edu
------------------------cut here---------------------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README Makefile chip8.c brix.uu pong.uu syzygy.uu
# Wrapped by moews@jell-o.berkeley.edu on Wed Oct 31 18:34:21 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(4115 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThis package implements Chip-8 for Suns.  It has
Xbeen tested on a Sun-3/50 running SunOS 4.1.
XInvoke it with chip8 [-n] [-t usec] [program-name].
XThe binary file given by program-name is loaded starting
Xat address 0x0200.  By default, the program waits until
Xa clock tick after after display operation, and a clock
Xtick occurs every 1/60th of a second (16667 microseconds).
XThe -n option disables this wait, resulting in an extreme
Xincrease in interpretation speed.  The -t option changes the
Xspeed of the clock.  For example, -t 33333 would give
Xa clock that ran twice as slowly as usual.  This will
Xalso affect the delay timer and sound timer.
X
XThe hex keypad is simulated with the 0-9 and a, b, c, d, e, f
Xkeys.  Hold the `z' key down to exit the interpreter.  The
Xinterpreter sets the keyboard to ASCII mode when it exits,
Xso you can't run this program from Sunview or XWindows.
XHowever, it uses the whole screen anyway, so you wouldn't
Xwant to.
X
XThis distribution includes uuencoded binaries of some chip-8
Xgames previously posted to comp.sys.handhelds.  `make'
Xwill uudecode them for you as well as compiling the interpreter.
X
X              -- David Moews, 10/31/90
X
XCHIP-8 instructions:
X(This summary extracted from Andreas Gustafsson's posting)
X0NNN	Call 1802 machine code subroutine at NNN, viz.:
X00E0	Clear display
X00EE	Return from subroutine
X1NNN	Jump to NNN
X2NNN	Call subroutine at NNN
X3XKK	Skip next instruction if VX == KK
X4XKK	Skip next instruction if VX != KK
X5XY0	Skip next instruction if VX == VY
X6XKK	VX := KK
X7XKK	VX := VX + KK
X8XY0	VX := VY, VF may change
X8XY1	VX := VX or VY, VF may change
X8XY2	VX := VX and VY, VF may change
X8XY3	VX := VX xor VY, VF may change *
X8XY4	VX := VX + VY, VF := carry
X8XY5	VX := VX - VY, VF := not borrow
X8XY6	VX := VX shr 1, VF := carry
X8XY7	VX := VY - VX, VF := not borrow *
X8XYE	VX := VX shl 1, VF := carry
X9XY0	Skip next instruction if VX != VY
XANNN	I := NNN
XBNNN	Jump to NNN+V0
XCXKK	VX := pseudorandom_number and KK
XDXYN	Show N-byte sprite from M(I) at coords (VX,VY), VF := collision
XEX9E	Skip next instruction if key VX pressed
XEXA1	Skip next instruction if key VX not pressed
XFX07	VX := delay_timer
XFX0A	wait for keypress, store hex value of key in VX
XFX15	delay_timer := VX
XFX18	sound_timer := VX
XFX1E	I := I + VX
XFX29	Point I to 5-byte font sprite for hex character VX
XFX33	Store BCD representation of VX in M(I)..M(I+2)
XFX55	Store V0..VX in memory starting at M(I)
XFX65	Read V0..VX from memory starting at M(I)
X
XLEGALESE AND AUTHOR ACKNOWLEDGMENTS
X
X        Pong did not have a copyright when posted to the net,
X        but was written by Paul Vervalin (vervalin@AUSTIN.LOCKHEED.COM.)
X
X	SYZYGY if (c) copyright 1990 by Roy Trevino (RTT)
X
X	Noncommercial distribution allowed, provided that this
X	copyright message is preserved, and any modified versions
X	are clearly marked as such.
X
X	SYZYGY, via CHIP-48, makes use of undocumented low-level features
X	of the HP48SX calculator, and may or may not cause loss of data,
X	excessive battery drainage, and/or damage to the calcultor
X	hardware.  The Author takes no responsibility whatsoever for
X	any damage caused by the use of this program.
X	
X	THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
X	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
X	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
X	PURPOSE.
X
X
X      CHIP-48 and BRIX are (C) Copyright 1990 Andreas Gustafsson
X
X      Noncommercial distribution allowed, provided that this
X      copyright message is preserved, and any modified versions
X      are clearly marked as such.  
X
X      CHIP-48 and BRIX make use of undocumented low-level features of
X      the HP48SX calculator, and may or may not cause loss of data,
X      excessive battery drainage, and/or damage to the calculator
X      hardware.  The Author takes no responsibility whatsoever for 
X      any damage caused by the use of this program.
X
X      THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
X      IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
X      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
X      PURPOSE.
END_OF_FILE
if test 4115 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(389 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCC = cc
XLINT = lint
XCFLAGS = -O4
XCLIBS = -lpixrect
XLINTFLAGS = -abch
X
X.SUFFIXES: .cp8 .uu
X
Xall: chip8 brix.cp8 pong.cp8 syzygy.cp8
X
X.uu.cp8:
X	uudecode $<
X
Xchip8: chip8.c
X	$(CC) $(CFLAGS) -o chip8 chip8.c $(CLIBS)
X
Xclean:
X	/bin/rm -f chip8 brix.cp8 pong.cp8 syzygy.cp8
X
Xlint:
X	$(LINT) $(LINTFLAGS) chip8.c $(CLIBS)
X
Xshar:
X	shar README Makefile chip8.c brix.uu pong.uu syzygy.uu >chip8.shar
END_OF_FILE
if test 389 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'chip8.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'chip8.c'\"
else
echo shar: Extracting \"'chip8.c'\" \(9578 characters\)
sed "s/^X//" >'chip8.c' <<'END_OF_FILE'
X/* Chip-8 for Suns. */
X
X#include <sys/types.h>
X#include <math.h>
X#include <signal.h>
X#include <pixrect/pixrect.h>
X#include <pixrect/memvar.h>
X#include <sys/time.h>
X#include <fcntl.h>
X#include <sundev/kbd.h>
X#include <sundev/kbio.h>
X#include <stdio.h>
X
X#ifndef NULL
X#define NULL 0
X#endif
X#define NULLPR ((Pixrect *)NULL)
X
X#define min(x,y) ((x)<(y)?(x):(y))
X
Xtypedef int bool;
X#define TRUE 1
X#define FALSE 0
X
X#define SCREENX 64
X#define SCREENY 32
X#define MEMSIZE (1<<12)
X#define PROGSTART (2*(1<<8))
X#define MAXSUBS 16
Xtypedef unsigned char uchar;
X/* 16 slack spaces at end in case we run over with Fxjj or Dxjj */
Xuchar memory[MEMSIZE+16];
X#define memend &memory[MEMSIZE]
Xuchar *stk[MAXSUBS];
Xint sp, v[16], del_timer, sound_timer, int_flag;
X
Xchar *fontstring = "f999f44444f1f8ff1f1faaf22f8f1ff8f9ff1111f9f9ff9f1ff9f99\
Xe9e9ef888fe999ef8f8ff8f88";
X
Xbool wait_flag = TRUE;             /* Wait a jiffy on displaying something? */
Xint timer_interval = 16667;        /* Jiffy length, in microseconds */
X
X/* Load font from fontstring */
Xvoid load_fonts()
X{
X  int i, vv;
X
X  for (i=0; i<16*5; i++)
X  {
X    if ((fontstring[i] >= '0') && (fontstring[i] <= '9')) 
X             vv = fontstring[i] - '0';
X        else vv = fontstring[i] - 'a' + 10;
X    memory[i] = vv*16;
X  }
X}
X
Xint screen_w, screen_h, replication;
XPixrect *pixscreen, *squarepr;
Xchar image[SCREENX][SCREENY];
X
X/* Set up screen pixrect */
Xvoid setup_screen()
X{
X  pixscreen = pr_open("/dev/fb");
X  screen_w = pixscreen->pr_width;
X  screen_h = pixscreen->pr_height;
X  replication = min(screen_w/SCREENX, screen_h/SCREENY);
X  squarepr = mem_create(replication, replication, 1);
X  pr_rop(squarepr, 0, 0, replication, replication, PIX_SET, NULLPR, 0, 0);
X}
X
X/* Display sprite @ (x,y), 8 across, n deep, data from pointer p */
Xvoid display(x, y, n, p)
Xint x, y, n;
Xuchar *p;
X{
X  int i, j, cnt1, lx1, ly1, nx, ny, maxx, maxy;
X  struct pr_prpos list1[8*16];
X
X  x &= SCREENX-1;
X  y &= SCREENY-1;
X  cnt1 = 0;
X  v[15] = 0;
X  lx1 = 0;
X  ly1 = 0;
X  maxx = 8;
X  if (maxx > SCREENX-x) maxx = SCREENX-x;
X  maxy = n;
X  if (maxy > SCREENY-y) maxy = SCREENY-y;
X  for (i=0; i<maxy; i++)
X  for (j=0; j<maxx; j++)
X  if (p[i] & (128>>j))
X  {
X    if (image[x+j][y+i]) v[15] = 1;
X    image[x+j][y+i] ^= 1;
X    list1[cnt1].pr = squarepr;
X    nx = j*replication;
X    ny = i*replication;
X    list1[cnt1].pos.x = nx - lx1;
X    lx1 = nx;
X    list1[cnt1].pos.y = ny - ly1;
X    ly1 = ny;
X    cnt1++;
X  }
X  pr_batchrop(pixscreen, x*replication, y*replication, 
X              PIX_SRC^PIX_DST, list1, cnt1); 
X  /* Wait for a jiffy if we have to */
X  if (wait_flag)
X  {
X    int_flag = 1;
X    while (int_flag) (void)sigpause(0);
X  }
X}
X
X/* Clear screen */
Xvoid clear_display()
X{
X  int i, j;
X
X  pr_rop(pixscreen, 0, 0, screen_w, screen_h, PIX_SET, NULLPR, 0, 0);
X  for (i=0; i<SCREENX; i++)
X  for (j=0; j<SCREENY; j++)
X      image[i][j] = 0;
X}
X
X
Xint kb_device;
Xchar kb_translation_mask[128];
Xint key_down_mask[16];          /* Keep track of hex chars... */
X
Xvoid bell_on()
X{
X  int i;
X
X  i = KBD_CMD_BELL;
X  (void)ioctl(kb_device, KIOCCMD, &i);
X}
X
Xvoid bell_off()
X{
X  int i;
X
X  i = KBD_CMD_NOBELL;
X  (void)ioctl(kb_device, KIOCCMD, &i);
X}
X
X/* Read the keyboard; update key_down_mask */
Xint read_kb()
X{
X  fd_set zero, kbtg;
X  struct timeval tv, *tvp;
X  int i, newstate;
X  char buf[2];
X
X  FD_ZERO(&zero);
X  FD_ZERO(&kbtg);
X  FD_SET(kb_device, &kbtg);
X  tv.tv_sec = tv.tv_usec = 0;
X  tvp = &tv;
X  while (select(kb_device+1, &kbtg, &zero, &zero, tvp) != 0)
X  {
X    (void)read(kb_device, buf, 1);
X    i = kb_translation_mask[buf[0] & 0x7f];
X    if (buf[0] & 0x80) newstate = 0; else newstate = 1;
X    if (i != 127)
X    {
X      if ((i >= '0') && (i <= '9')) key_down_mask[i-'0'] = newstate;
X      if ((i >= 'a') && (i <= 'f')) key_down_mask[i-'a'+10] = newstate;
X      if (i == 'z')
X      {
X        i = TR_ASCII;
X        (void)ioctl(kb_device, KIOCTRANS, &i);
X        bell_off();
X        exit(0);
X      }
X    }
X  }
X}
X
X/* Set up keyboard; get translation mask */
Xvoid setup_kb()
X{
X  int j;
X
X  struct kiockey key;
X
X  kb_device = open("/dev/kbd", O_RDWR, 0);
X  for (j=0; j<128; j++)
X  {
X    key.kio_tablemask = 0;  /* UPMASK? */
X    key.kio_station = j;
X    (void)ioctl(kb_device, KIOCGETKEY, &key);
X    kb_translation_mask[j] = key.kio_entry;
X  }
X  for (j=0; j<16; j++) key_down_mask[j] = 0;
X  j = 1;
X  (void)ioctl(kb_device, KIOCSDIRECT, &j);
X  j = TR_NONE;
X  (void)ioctl(kb_device, KIOCTRANS, &j);
X  j = fcntl(kb_device, F_GETFL, 0);
X  (void)signal(SIGIO, read_kb);
X  j |= FASYNC;
X  (void)fcntl(kb_device, F_SETFL, j);
X  j = getpid();
X  (void)fcntl(kb_device, F_SETOWN, j);
X}
X
X/* Get a hex key */
Xint gethexchar()
X{
X  int a;
X
X  for (;;)
X  {
X    for (a=0; a<16; a++)
X        if (key_down_mask[a]) return(a);
X    (void)sigpause(0);
X  }
X}
X
X/* Is `a' pressed [a=a hex digit] */
X#define kp(a) key_down_mask[a]
X
Xvoid do_interpret(n)
Xint n;
X{   
X  register int a, a0, b, b0, t;
X  register uchar *pc, *i;
X  extern long random();
X
X  sp = 0;
X  pc = &memory[n];
X  i = &memory[0];
X
X  for (;;)
X  {
X    a = *pc++;
X    b = *pc++;
X    switch (a&0xf0)
X    {
X      case 0x00: if (b == 0xe0) clear_display();
X         else if (b == 0xee) if (sp>0) pc = stk[--sp];
X              break;
X      case 0x20: if (sp<MAXSUBS) stk[sp++] = pc;
X      case 0x10: pc = &memory[((a&0x0f)<<8)|b];
X              break;
X      case 0x30: if (v[a&0x0f] == b) pc += 2;
X              break;
X      case 0x40: if (v[a&0x0f] != b) pc += 2;
X              break;
X      case 0x50: if (v[a&0x0f] == v[b>>4]) pc += 2;
X              break;
X      case 0x60: v[a&0x0f] = b;
X              break;
X      case 0x70: v[a&0x0f] += b;
X              v[a&0x0f] &= 0xff;
X              break;
X      case 0x80: a0 = a&0x0f;
X              b0 = b>>4;
X              switch (b&0x0f)
X              {
X#define CARRY v[15]=((v[a0]&0x100) != 0); v[a0]&=0xff
X#define CARRY0 v[15] = v[a0]&1
X                case 0: v[a0]=v[b0]; break;
X                case 1: v[a0]|=v[b0]; break;
X                case 2: v[a0]&=v[b0]; break;
X                case 3: v[a0]^=v[b0]; break;
X                case 4: v[a0]+=v[b0]; CARRY; break;
X                case 5: v[a0]+=0x100-v[b0]; CARRY; break;
X                case 6: CARRY0; v[a0]>>=1; break;
X                case 7: v[a0]=v[b0]+0x100-v[a0]; CARRY; break;
X                case 0xe: v[a0]<<=1; CARRY; break;
X                default: break;
X              }
X              break;
X      case 0x90: if (v[a&0x0f] != v[b>>4]) pc += 2;
X              break;
X      case 0xa0: i = &memory[((a&0x0f)<<8)|b];
X                break;
X      case 0xb0: pc = &memory[(((a&0x0f)<<8)|b) + v[0]];
X                if (pc >= memend) pc -= MEMSIZE;
X                break;
X      case 0xc0: v[a&0x0f] = (random())&b;
X                break;
X      case 0xd0: display(v[a&0x0f], v[b>>4], b&0x0f, i);
X                break;
X      case 0xe0:
X      case 0xf0: switch (b)
X                {
X                  case 0x07: v[a&0x0f] = del_timer;
X                             break;
X                  case 0x0a: v[a&0x0f] = gethexchar();
X                             break;
X                  case 0x15: del_timer = v[a&0x0f];
X                             break;
X                  case 0x18: sound_timer = v[a&0x0f];
X                             if (sound_timer > 0) bell_on();
X                             break;
X                  case 0x1e: i += v[a&0x0f];
X                             if (i >= memend) i -= MEMSIZE;
X                             break;
X                  case 0x29: i = &memory[5*(v[a&0x0f]&0x0f)];
X                             break;
X                  case 0x33: t = v[a&0x0f];
X                             i[0] = t/100;
X                             i[1] = (t%100)/10;
X                             i[2] = t%10;
X                             break;
X                  case 0x55: for (t=0; t<=(a&0x0f); t++) i[t]=v[t];
X                             break;
X                  case 0x65: for (t=0; t<=(a&0x0f); t++) v[t]=i[t];
X                             break;
X                  case 0x9e: if (kp(v[a&0x0f]&0x0f))  pc += 2;
X                             break;
X                  case 0xa1: if (!kp(v[a&0x0f]&0x0f)) pc += 2;
X                             break;
X                  default:   break;
X                }
X                break;
X    }
X  }
X}
X
Xint doalarm()
X{
X  if (del_timer>0) del_timer--;
X  if (sound_timer>0)
X  {
X    sound_timer--;
X    if (sound_timer == 0) bell_off();
X  }
X  int_flag = 0;
X}
X
Xvoid usage(s)
Xchar *s;
X{
X  (void)printf("Usage: %s [-n] [-t usec] program-name\n", s);
X  exit(1);
X}
X 
Xvoid main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  struct itimerval vv;
X  struct timeval sec60;
X  int i, j;
X  bool gotarg;
X
X  gotarg = FALSE;
X  for (j=1; j<argc; j++)
X  {
X    if (argv[j][0] == '-')
X    {
X      switch (argv[j][1])
X      {
X        case 'n': wait_flag = FALSE;
X                  break;
X
X        case 't': j++;
X                  if (j == argc) usage(argv[0]);
X                  timer_interval = atoi(argv[j]);
X                  break;
X
X        default:  usage(argv[0]);
X                  break;
X      }
X    } else
X    {
X      if (gotarg) usage(argv[0]);
X      gotarg = TRUE;
X      i = open(argv[j], O_RDONLY, 0);
X      if (i >= 0)
X      {
X        (void)read(i, memory+PROGSTART, MEMSIZE-PROGSTART);
X        (void)close(i);
X      }
X    }
X  }
X  if (!gotarg) usage(argv[0]);
X
X  setup_kb();
X  setup_screen();
X  load_fonts();
X  sec60.tv_usec = timer_interval;
X  sec60.tv_sec = 0;
X  vv.it_value = sec60;
X  vv.it_interval = sec60;
X  del_timer = sound_timer = 0;
X  (void)signal(SIGALRM, doalarm);
X  (void)setitimer(ITIMER_REAL, &vv, (struct itimerval *)NULL);
X  clear_display();
X  do_interpret(PROGSTART);
X  /*NOTREACHED*/
X}
END_OF_FILE
if test 9578 -ne `wc -c <'chip8.c'`; then
    echo shar: \"'chip8.c'\" unpacked with wrong size!
fi
# end of 'chip8.c'
fi
if test -f 'brix.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'brix.uu'\"
else
echo shar: Extracting \"'brix.uu'\" \(415 characters\)
sed "s/^X//" >'brix.uu' <<'END_OF_FILE'
Xbegin 644 brix.cp8
XM;@5E &L&:@"C#-JQ>@0Z0!((>P([$A(&;"!M'Z,0W-$B]F  80"C$M 1< BC
XM#M 18$#P%? ',  2-,8/9QYH 6G_HP[6<:,0W-%@!."A?/Y@!N"A? )@/XP"
XMW-&C#M9QAH2'E& _A@)A'X<21Q\2K$8 : %&/VC_1P!I =9Q/P$2JD<?$JI@
XM!8!U/P 2JF !\!B 8&'\@!*C#-!Q8/Z) R+V=0$B]D5@$MX21FG_@&" Q3\!
XM$LIA H 5/P$2X( 5/P$2[H 5/P$2Z& @\!BC#G[_@." !&$ T!$^ !(P$MYX
XM_TC^:/\2[G@!2 )H 6 $\!AI_Q)PHQ3U,_)E\2EC-V0 TT5S!?(ITT4 [N  
X*@ #\ *H       )H
X 
Xend
END_OF_FILE
if test 415 -ne `wc -c <'brix.uu'`; then
    echo shar: \"'brix.uu'\" unpacked with wrong size!
fi
# end of 'brix.uu'
fi
if test -f 'pong.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pong.uu'\"
else
echo shar: Extracting \"'pong.uu'\" \(369 characters\)
sed "s/^X//" >'pong.uu' <<'END_OF_FILE'
Xbegin 644 pong.cp8
XM:@)K#&P_;0RBZMJVW-9N "+49@-H F!@\!7P!S  $AK'%W<(:?^B\-9QHNK:
XMMMS68 '@H7O^8 3@H7L"8!^+ MJV8 S@H7W^8 W@H7T"8!^- MS6HO#6<8:$
XMAY1@/X8"81^'$D8"$GA&/Q*"1Q]I_T< :0'6<1(J: )C 8!P@+42BFC^8PJ 
XM<(#5/P$2HF$"@!4_ 1*Z@!4_ 1+(@!4_ 1+"8"#P&"+4CC0BU&8^,P%F VC^
XM,P%H A(6>?])_FG_$LAY 4D":0%@!/ 8=@%&0';^$FRB\OXS\F7Q*60490#4
X75705\BG450#N@(" @(" @       &508
X 
Xend
END_OF_FILE
if test 369 -ne `wc -c <'pong.uu'`; then
    echo shar: \"'pong.uu'\" unpacked with wrong size!
fi
# end of 'pong.uu'
fi
if test -f 'syzygy.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'syzygy.uu'\"
else
echo shar: Extracting \"'syzygy.uu'\" \(1335 characters\)
sed "s/^X//" >'syzygy.uu' <<'END_OF_FILE'
Xbegin 644 syzygy.cp8
XM$A*-C2"I,3DY,"!25%0@CHX )+8DVF /X*$2)& .X*$2*!(6)-H2+ #@$BS!
XM'W$0P@]R",,#A3"&$(<@B#!( '<!2 %W_T@"=@%( W;_I4S1(=9Q9/!I\:@ 
XM]!Z ,/!5= &H /0>8 'P524B:@!Z / ',  2G#T $I1@ / IV\4_ 1*,V\4E
XM(O 5$IS^%6T!;@ 2G(#@\"G;Q24B8 /@H6, 8 ;@H6,!8 ?@H6,"8 C@H6,#
XM0P!R_T,!<@%# G'_0P-Q :5,T2$_ 1,D/0$3B& _@0)@'X("@+" %S\!$XB 
XML' #@!4_ 1.(@," )S\!$XB P' $@"4_ 1.(8 3P&,X'?@**Y*5,T2%@ / I
XMV\6 X/ IV\5@,/ 5\ <P !,:I4S1(9-0$SYT :@ ]!Z ,/!5= &H /0>8 #P
XM584PJ #T'O!E< 'P54H $UA@#'#_,  33GK_$G"E3-9Q2 !W_T@!=P%( G;_
XM2 -V :@ ^1[P97#_\%4P !)P>0&H /D>\&6( 'D!$G!@#? 88 O@GA..:P%L
XM &T >P$["A.J:P!\ 3P*$ZIL 'T!I4S6<4@ =_]( 7<!2 )V_T@#=@&H /D>
XM\&5P__!5,  3F)E $]YY :@ ^1[P98@ >0$3F #@9A%G"6@O:1>E4M9^V'YW
XM_Z5.UG'6D78(UG'6D78(UG'6D78(I5#6<=:1I9YF$V<1))JEKO-ED] 4)( P
XM@-4_ 10Z%$22P!0R@"" Q3\!%#H41( 0@+4_ !1$I:Z#T(+ @;#S5:6N\V5F
XM$W?YC3",((L0I:0DFL$_PA]@#8 5/P 4?& P@!<_ !1\8 . )3\ %'Q@&( G
XM/P 4?!2"PP_S*=$E8 _@H1208 [@H126%%8 X"2V$BP X!(LUG6EJG8"UG3]
XM*78*UG7\*78%UG7[*78%UG4 [J5.80!B &8?T2'187$(,4 4OJ528@%E/]$O
XMU2]R#]$OU2\ [F$,8@>E8M$JI6QQ!M$JI79Q!M$JI6QQ!M$JI8!Q!M$JI6QQ
XM!M$J80YB&*6*T2.ECG$(<O_1)'$)<OZEDM$F<09R :68T24 [FW%RS^.L([4
XM3P$5)'L!;>;,'X[ CM1/ 14R? %M ,X_?D#^%<X_?D  [H  _P#^ (" @(" 
XM@(" @(" @(" @( ?$! 0'P$! 0$?$1$1$1\$! 0$!!\! @($! @($!\?$1 0
XM$!,1$1$?!04" '%1474,$AX4$@D4/A45*@!W1"04=P!74G)25P   0 !    
X! !,1
X 
Xend
END_OF_FILE
if test 1335 -ne `wc -c <'syzygy.uu'`; then
    echo shar: \"'syzygy.uu'\" unpacked with wrong size!
fi
# end of 'syzygy.uu'
fi
echo shar: End of shell archive.
exit 0