jsgray@watrose.UUCP (03/01/87)
Here is a fast (400,000 cell-generations/s) life program for monochrome Atari-ST computers (which should port easily to other 68000 machines). It animates all 240,000 pixels on the screen. Feel free to add a better user-interface! But how does it go so fast? It sums the neighbours of 32 cells in one pass, by synthesizing addition instructions out of logical operators. The rest of this file is a shar containing life.c - mainline gen.s - quickly compute next generation life.uue - uuencoded life.prg (Atari ST only) Have fun! Jan Gray jsgray@watrose University of Waterloo (519) 885-1211 x3870 # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by watrose!jsgray on Sun Mar 1 11:29:07 EST 1987 # Contents: life.c gen.s life.uue echo x - life.c sed 's/^@//' > "life.c" <<'@//E*O*F life.c//' /* * Fast monochrome life for Atari ST. * * Written by * Jan Gray * 300 Regina St. N Apt. 2-905 * Waterloo, Ontario * N2J 4H2 * Canada * (jsgray@watrose.UUCP) * * Copyright (C) 1987 Jan Gray. * This program may be freely redistributed if this notice is retained. */ #include "define.h" #include "osbind.h" #define MAXX 640 #define MAXY 400 #define BPL 32 #define ROW_LONGS (MAXX / BPL) #define SCREEN_LONGS (ROW_LONGS * MAXY) long *Screen; long NextScreen[SCREEN_LONGS]; main() { Screen = (long *)Physbase(); while (!Cconis()) { /* until key press... */ clearBorders(); gen(); copyScreen(); } } copyScreen() { register long *p; register long *q; for (p = NextScreen, q = Screen; p < &NextScreen[SCREEN_LONGS]; ) { *q++ = *p++; *q++ = *p++; *q++ = *p++; *q++ = *p++; } } clearBorders() { register long *p; for (p = Screen; p < &Screen[ROW_LONGS]; p++) *p = 0L; for (p = &Screen[(MAXY - 1) * ROW_LONGS]; p < &Screen[MAXY * ROW_LONGS]; p++) *p = 0L; for (p = Screen; p < &Screen[SCREEN_LONGS]; p += ROW_LONGS) *p &= ~0x80000000L; for (p = &Screen[ROW_LONGS-1]; p < &Screen[SCREEN_LONGS]; p += ROW_LONGS) *p &= ~1L; } @//E*O*F life.c// chmod u=rw,g=rw,o=r life.c echo x - gen.s sed 's/^@//' > "gen.s" <<'@//E*O*F gen.s//' * * Fast monochrome life for Atari ST. * * Written by * Jan Gray * 300 Regina St. N Apt. 2-905 * Waterloo, Ontario * N2J 4H2 * Canada * (jsgray@watrose.UUCP) * * Copyright (C) 1987 Jan Gray. * This program may be freely redistributed if this notice is retained. * * * gen -- compute the next generation of cells * * This code is a transliteration of the the pdp-11 code presented in * "Life Algorithms" by Mark Niemiec, Byte, 4:1, January 1979. * * gen currently does about 400,000 cell-generations/second. It can go faster. * * Forgive the hardwired-in constants, and the terse comments. It's a hack. * Think of the fun you'll have figuring out how it works. * @.globl _gen @.text _gen: movem.l d0-d7/a0-a2,-(sp) move.l _Screen,a0 move.l a0,a2 add.l #80,a0 add.l #31920,a2 move.l #_NextScreen+80,a1 * 1 2 3 * 7 * 8 * 4 5 6 * (d1,d0) = neighbours 1+2 again: move.l -80(a0),d0 move.l d0,d1 move.l d0,d2 move.b -81(a0),d7 roxr.b #1,d7 roxr.l #1,d0 eor.l d1,d0 or.l d0,d1 eor.l d0,d1 * (d1,d0) = neighbours 1+2+3 move.b -76(a0),d7 roxl.b #1,d7 roxl.l #1,d2 eor.l d2,d0 or.l d0,d2 eor.l d0,d2 or.l d2,d1 * (d3,d2) = neighbours 4+5 move.l 80(a0),d2 move.l d2,d3 move.l d2,d4 move.b 79(a0),d7 roxr.b #1,d7 roxr.l #1,d2 eor.l d3,d2 or.l d2,d3 eor.l d2,d3 * (d3,d2) = neighbours 4+5+6 move.b 84(a0),d7 roxl.b #1,d7 roxl.l #1,d4 eor.l d4,d2 or.l d2,d4 eor.l d2,d4 or.l d4,d3 * (d2,d1,d0) = neighbours 1+2+3+4+5+6 eor.l d2,d0 or.l d0,d2 eor.l d0,d2 eor.l d2,d1 or.l d1,d2 eor.l d1,d2 eor.l d3,d1 or.l d1,d3 eor.l d1,d3 or.l d3,d2 * (d4,d3) = neighbours 7+8 move.l (a0),d3 move.l d3,d4 move.b -1(a0),d7 roxr.b #1,d7 roxr.l #1,d3 move.b 4(a0),d7 roxl.b #1,d7 roxl.l #1,d4 eor.l d4,d3 or.l d3,d4 eor.l d3,d4 * (d2,d1,d0) = neighbours 1+2+3+4+5+6+7+8 eor.l d3,d0 or.l d0,d3 eor.l d0,d3 eor.l d3,d1 or.l d1,d3 eor.l d1,d3 eor.l d4,d1 or.l d1,d4 eor.l d1,d4 or.l d3,d2 or.l d4,d2 * next generation or.l (a0)+,d0 not.l d2 and.l d2,d0 and.l d1,d0 move.l d0,(a1)+ cmp.l a2,a0 blt again movem.l (sp)+,d0-d7/a0-a2 rts @//E*O*F gen.s// chmod u=rw,g=rw,o=r gen.s echo x - life.uue sed 's/^@//' > "life.uue" <<'@//E*O*F life.uue//' begin 664 life.prg M8!H )" !7 C*P "I/+GP !,^*FT !" M S0 MK0 4T*T '-"\ ! "\ +PT_ #\\ $I.0=_\ #$ZY 2B\\ $Y! M(B\ !# \ ,A.0DYU3E;__#Z\ ).N0 A(CP D$9A3F *3KD %.811A M0CZ\ M.N0 C)*0&?H3EY.=4Y6 !(YP$,*GP !-&*'D )!&8 @HW2C= M*-THW;O\ "01F7P2I],WS 3EY.=4Y6 !(YP$$*GD )!&8 1"E5B-(#D M )!&T+P !0N\!E["IY "01MO\ !\L& $0I58C2 Y "01M"\ !] +O M9>PJ>0 D$9@#B \?____\&5V_P !0(#D )!&T+P 'T N\!EXBIY "0 M1MO\ 3& , I7____^V_P !0(#D )!&T+P 'T N\!EY$J?3-\@ $Y> M3G5(Y__@('D )!&)$C1_ %#5_ ?+ B? $Y8@*/^P(@ D !XH_Z_B M%^*0LX""@+&!'BC_M.,7XY*U@(2 L8*"@B0H % F B@"'B@ 3^(7XI*W@H:" MM8,>* !4XQ?CE+F"B(*UA(:$M8"$@+&"M8&$@;."MX&&@;.#A(,F$"@#'BC_ M_^(7XI,>* $XQ?CE+F#B(.WA+> AH"Q@[>!AH&S@[F!B(&SA(2#A(2 F$:" MP(+ @2+ L<IM /]B3-\'_TYU(]\ !-"3DXO.0 $T).=2/? 30DY-+SD M !-"3G4CWP $T).02\Y 30DYU $ @$! @$! $! @$! 0$! M $ $ P4 !04 $! @$ $ <! @$ 0$! @$! @$! M @$! 0$" 0$! @$! 0$!!@$!! $! 0,! @$!! (!" $! M 0$!"0$! 0$! 0$ 4! M ! , " , !@$ " $ " $ ! $! P$! 4 M 0$! 4 $! $! (" M !0$ !0$ 0$ 0$ @4 !@$ @$ 0$ M!@4 $! $ @$ @$! 0$! $" P$" 0$! F 0$! $! $" !"XB!@H.%@80&@P0$A 6$!H>%*P(" @(" " end @//E*O*F life.uue// chmod u=rw,g=rw,o=r life.uue echo Inspecting for damage in transit... temp=/tmp/shar$$; dtemp=/tmp/.shar$$ trap "rm -f $temp $dtemp; exit" 0 1 2 3 15 cat > $temp <<\!!! 69 192 1192 life.c 138 336 2108 gen.s 25 185 1381 life.uue 232 713 4681 total !!! wc life.c gen.s life.uue | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp if [ -s $dtemp ] then echo "Ouch [diff of wc output]:" ; cat $dtemp else echo "No problems found." fi exit 0