/* * What fun! A new LIFE program by Tomas Rokicki. Commented rather * erratically; hell, this is all just one big hack. */ int modulo ; int wmodulo ; int vsize ; #define RASTSIZE (wmodulo * (long)(vsize+1)) #include "structures.h" #include "blit.h" short *a, *b, *c, *d, *e, *t1=NULL, *t2=NULL, *t3=NULL, *t4=NULL ; short noplanes ; short torus ; short orify ; struct GfxBase *GfxBase = NULL ; /* the GfxBase */ struct IntuitionBase *IntuitionBase = NULL ; /* the IntuitionBase */ struct Screen *myscreen = NULL ; struct Window *mywindow = NULL ; struct TextAttr myfont = {(STRPTR)"topaz.font", TOPAZ_EIGHTY, 0, 0 }; struct NewScreen mynewscreen = {0, 0, 0, 0, 0, 1, 2, 0, CUSTOMSCREEN, &myfont, (UBYTE *)"AmigaLIFE -- Radical Eye Software"} ; /* * Let's use a borderless window too, so we can get vanilla * keys. This gives us a nicer way to exit and adjust the * speed of the program. But we still play with the screen * bitmaps. */ static struct NewWindow mynewwindow = { 0, 0, 0, 0, 0, 1, VANILLAKEY, SIMPLE_REFRESH | ACTIVATE | NOCAREREFRESH | BORDERLESS | BACKDROP, NULL, NULL, NULL, NULL, NULL, -1, -1, -1, -1, CUSTOMSCREEN } ; /* * This routine gets a raster for temporary storage. */ short *myalloc() { void *AllocMem() ; void *p ; if ((p=AllocMem(2L*RASTSIZE, MEMF_CHIP | MEMF_CLEAR))==NULL) { printf("Could not allocate raster data\n") ; cleanup() ; } return(p) ; } /* * Here we set things up. */ initialize() { long color ; if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary( "intuition.library",0L))==NULL || (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L)) ==NULL) { printf("Couldn't open libraries.\n") ; cleanup() ; } if ((myscreen = OpenScreen(&mynewscreen))==NULL) { printf("Couldn't open screen.\n") ; cleanup() ; } mynewwindow.Screen = myscreen ; if ((mywindow = OpenWindow(&mynewwindow))==NULL) { printf("Couldn't open window.\n") ; cleanup() ; } a = ((short *)(myscreen->BitMap.Planes[0])) + 10 * wmodulo ; b = ((short *)(myscreen->BitMap.Planes[1])) + 10 * wmodulo ; c = ((short *)(myscreen->BitMap.Planes[2])) + 10 * wmodulo ; d = ((short *)(myscreen->BitMap.Planes[3])) + 10 * wmodulo ; e = ((short *)(myscreen->BitMap.Planes[4])) + 10 * wmodulo ; t1 = myalloc() ; t2 = myalloc() ; t3 = myalloc() ; t4 = myalloc() ; if (orify) { color = GetRGB4(myscreen->ViewPort.ColorMap, 0L) ; if (color & 0xf00) color -= 256 ; if (color & 0xf0) color -= 16 ; if (color & 0xf) color -= 1 ; SetRGB4(&(myscreen->ViewPort), 1L << (noplanes - 1), (color >> 8) & 15, (color >> 4) & 15, color & 15) ; } } /* * Exit routine. */ cleanup() { if (mywindow != NULL) CloseWindow(mywindow) ; if (myscreen != NULL) CloseScreen(myscreen) ; if (IntuitionBase) CloseLibrary(IntuitionBase) ; IntuitionBase = NULL ; if (GfxBase) CloseLibrary(GfxBase) ; GfxBase = NULL ; if (t1) FreeMem(t1, 2L*RASTSIZE) ; if (t2) FreeMem(t2, 2L*RASTSIZE) ; if (t3) FreeMem(t3, 2L*RASTSIZE) ; if (t4) FreeMem(t4, 2L*RASTSIZE) ; exit(0) ; } #define PARITY (0x96) #define CARRY (0xe8) #define SPEC1 (0x6a) #define SPEC2 (0xbe) #define SPEC3 (0x40) #define COPY (0xf0) #define ORIFY (0xfc) #define ORAC (0xfa) /* * This routine does the necessary four blits to wrap the LIFE image. * Please make sure that you own the blitter when you call it! */ struct blitparam blitparam ; fixit() { register struct blitparam *p = &blitparam ; p->bltsize = BLTSIZE(1, vsize) ; p->asource = a ; p->csource = a + wmodulo - 1 ; p->dsource = a + wmodulo - 1 ; p->amod = 2 * (wmodulo - 1) ; p->bmod = 0 ; p->cmod = 2 * (wmodulo - 1) ; p->dmod = 2 * (wmodulo - 1) ; p->fwm = 0x4000 ; p->lwm = 0xffff ; p->con0 = SHIFTSHIFT(14) + USEA + USEC + USED + ORAC ; p->con1 = 0 ; blit(p) ; p->asource = a + 2 * wmodulo - 1 ; p->csource = a ; p->dsource = a ; p->fwm = 0x0002 ; p->con0 = SHIFTSHIFT(2) + USEA + USEC + USED + ORAC ; blit(p) ; p->bltsize = BLTSIZE(wmodulo, 1) ; p->asource = a + wmodulo ; p->dsource = a + wmodulo * (long)(vsize - 1) ; p->amod = 0 ; p->cmod = 0 ; p->dmod = 0 ; p->fwm = 0xffff ; p->lwm = 0xffff ; p->con0 = USEA + USED + COPY ; blit(p) ; p->asource = a + wmodulo * (long)(vsize - 2) ; p->dsource = a ; blit(p) ; } /* * Does one LIFE generation. Fancy algorithm uses only 9 blits. If * anyone can improve this, please let me know. */ dogeneration() { register struct blitparam *p = &blitparam ; /* * Initialize the parameters we are not going to change. */ p->fwm = 0xffff ; p->lwm = 0xffff ; p->amod = 0 ; p->bmod = 0 ; p->cmod = 0 ; p->dmod = 0 ; p->asource = a - wmodulo ; p->bsource = a - wmodulo + 1 ; p->csource = a - wmodulo ; p->dsource = t1 ; p->bltsize = BLTSIZE(wmodulo, vsize+1) ; p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + PARITY ; p->con1 = SHIFTSHIFT(15) ; OwnBlitter() ; blit(p) ; p->dsource = t2 ; p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + CARRY ; blit(p) ; p->csource = t1 + wmodulo ; p->dsource = t3 ; p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + CARRY ; blit(p) ; p->bltsize = BLTSIZE(wmodulo, vsize) ; p->asource = t2 ; p->bsource = t2 + 2 * wmodulo ; p->csource = t3 + wmodulo ; p->dsource = t4 ; p->con1 = 0 ; p->con0 = USEA + USEB + USEC + USED + CARRY ; blit(p) ; p->dsource = t3 ; p->con0 = USEA + USEB + USEC + USED + PARITY ; blit(p) ; p->bltsize = BLTSIZE(wmodulo, vsize+1) ; p->asource = a - wmodulo ; p->bsource = a - wmodulo + 1 ; p->csource = t1 + wmodulo ; p->dsource = t2 ; p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + PARITY ; p->con1 = SHIFTSHIFT(15) ; blit(p) ; p->bltsize = BLTSIZE(wmodulo, vsize) ; p->asource = t1 ; p->bsource = t2 + wmodulo ; p->csource = t3 ; p->dsource = t3 ; p->con0 = USEA + USEB + USEC + USED + SPEC1 ; p->con1 = 0 ; blit(p) ; p->csource = a ; p->dsource = t1 ; p->con0 = USEA + USEB + USEC + USED + SPEC2 ; blit(p) ; /* * Before we do the final write, we copy bits down one generation. */ if (orify) { a = ((short *)(myscreen->BitMap.Planes[0])) + 10 * wmodulo ; p->asource = ((short *)(myscreen->BitMap.Planes[noplanes-1])) + 10 * wmodulo ; p->bsource = ((short *)(myscreen->BitMap.Planes[noplanes-2])) + 10 * wmodulo ; p->dsource = p->asource ; p->con0 = USEA + USEB + USED + ORIFY ; blit(p) ; } p->con0 = USEA + USED + COPY ; switch (noplanes - orify) { case 5: p->asource = d ; p->dsource = e ; blit(p) ; case 4: p->asource = c ; p->dsource = d ; blit(p) ; case 3: p->asource = b ; p->dsource = c ; blit(p) ; case 2: p->asource = a ; p->dsource = b ; blit(p) ; default: ; } p->bltsize = BLTSIZE(wmodulo, vsize-2) ; p->asource = t1 + wmodulo ; p->bsource = t3 + wmodulo ; p->csource = t4 + wmodulo ; p->dsource = a + wmodulo ; p->fwm = 0x7fff ; p->lwm = 0xfffe ; p->con0 = USEA + USEB + USEC + USED + SPEC3 ; blit(p) ; /* * Wrap, if necessary */ if (torus) fixit() ; DisownBlitter() ; } /* * Random number generator; probably not a very good one. */ int rnd(i) int i ; { static long seed = 323214521 ; long rval ; seed = seed * 123213 + 121 ; rval = (seed >> 5) & 65535 ; return ((i * rval) >> 16) ; } /* * Main routine. If called with no arguments, makes 1 bit plane screen. * Otherwise, first argument is used as the number of bit planes. */ char buffer[200] ; main (argc, argv) int argc ; char *argv[] ; { register int x, y ; int hires = 320 ; int randoms = 0 ; int ir ; int dvsize = 0 ; struct IntuiMessage *message ; int code ; long delayval = 0 ; noplanes = 1 ; while (argc > 1 && argv[1][0]=='-') { argc-- ; argv++ ; if (argv[0][1]=='h' || argv[0][1]=='H') { if (sscanf(argv[0]+2, "%d", &hires)!=1) hires = 640 ; } else if (argv[0][1]=='r' || argv[0][1]=='R') { if (sscanf(argv[0]+2, "%d", &randoms)!=1) randoms = 1 ; } else if (argv[0][1]=='p' || argv[0][1]=='P') { noplanes = argv[0][2] - '0' ; if (noplanes < 1 || noplanes > 6) noplanes = 1 ; } else if (argv[0][1]=='o' || argv[0][1]=='O') { orify = 1 ; } else if (argv[0][1]=='t' || argv[0][1]=='T') { torus = 1 ; } else if (argv[0][1]=='v' || argv[0][1]=='V') { if (sscanf(argv[0]+2, "%d", &dvsize)!=1) dvsize = 0 ; } else if (argv[0][1]=='s' || argv[0][1]=='S') { delayval = -1 ; } } if (noplanes == 1) orify = 0 ; if (argc > 1) { if (argv[1][0]=='?' && argv[1][1]==0) { printf( "Usage: life [-h[n]] [-r[n]] [-p[n]] [-o] [-t] [-v[n]] [-s] [infile]\n") ; cleanup() ; } if (freopen(argv[1], "r", stdin)==NULL) { printf("Couldn't open %s\n", argv[1]) ; cleanup() ; } } if (hires > 400) { vsize = 390 ; mynewscreen.ViewModes |= HIRES ; } else { vsize = 190 ; } modulo = hires & ~15 ; ir = randoms ; if (dvsize >= 10 && dvsize <= 600) vsize = dvsize ; wmodulo = modulo / 16 ; mynewscreen.Depth = noplanes ; mynewscreen.Width = modulo ; mynewscreen.Height = vsize + 10 ; mynewwindow.Width = modulo ; mynewwindow.Height = vsize + 10 ; if (vsize > 300) mynewscreen.ViewModes |= LACE ; initialize() ; readin(a) ; if (torus) { OwnBlitter() ; fixit() ; DisownBlitter() ; } while (1) { if (message = (struct IntuiMessage *)GetMsg(mywindow->UserPort)) { code = message->Code ; ReplyMsg(message) ; switch(code) { case 27 : case 3 : case 'q' : case 'Q' : case 'x' : case 'X' : cleanup() ; case '0' : case 'g' : case 'G' : delayval = 0 ; break ; case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : delayval = 1L << (code - '0') ; break ; case ' ' : delayval = -1 ; goto doone ; case 'S' : case 's' : delayval = -1 ; default : break ; } } if (delayval) { if (delayval == -1) continue ; Delay(delayval) ; } doone: if (randoms) { if (ir-- == 0) { x = rnd(modulo-2) + 1 ; y = rnd(vsize-2) + 1 ; a[y * (long)wmodulo + (x >> 4)] |= 1 << (15 - (15 & x)) ; ir = randoms ; } } dogeneration() ; } cleanup() ; }