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