X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fpetri.c;h=b9da70ad7cec69c48d17fe10fdea1c9ed715dbc7;hb=2d04c4f22466851aedb6ed0f2919d148f726b889;hp=8b7016507a2a99a33233d872dd6711a54860a746;hpb=df7adbee81405e2849728a24b498ad2117784b1f;p=xscreensaver diff --git a/hacks/petri.c b/hacks/petri.c index 8b701650..b9da70ad 100644 --- a/hacks/petri.c +++ b/hacks/petri.c @@ -1,4 +1,4 @@ -/* petri, simulate mold in a petri dish. v2.6 +/* petri, simulate mold in a petri dish. v2.7 * by Dan Bornstein, danfuzz@milk.com * with help from Jamie Zawinski, jwz@jwz.org * Copyright (c) 1992-1999 Dan Bornstein. @@ -69,19 +69,16 @@ typedef struct cell_s { - short x; /* 0 */ - short y; /* 2 */ - unsigned char col; /* 4 */ - unsigned char isnext; /* 5 */ - unsigned char nextcol; /* 6 */ - /* 7 */ - struct cell_s *next; /* 8 */ - struct cell_s *prev; /* 12 */ - struct cell_s *(adj)[3][3]; /* 16 */ - FLOAT speed; /* 52 */ - FLOAT growth; /* 56 60 */ - FLOAT nextspeed; /* 60 68 */ - /* 64 76 */ + unsigned char col; /* 0 */ + unsigned char isnext; /* 1 */ + unsigned char nextcol; /* 2 */ + /* 3 */ + struct cell_s *next; /* 4 */ + struct cell_s *prev; /* 8 - */ + FLOAT speed; /* 12 */ + FLOAT growth; /* 16 20 - */ + FLOAT nextspeed; /* 20 28 */ + /* 24 36 - */ } cell; static int arr_width; @@ -117,6 +114,10 @@ static FLOAT mindeathspeed; static FLOAT maxdeathspeed; static Bool originalcolors; +#define cell_x(c) (((c) - arr) % arr_width) +#define cell_y(c) (((c) - arr) / arr_width) + + static int random_life_value (void) { return (int) ((RAND_FLOAT * (maxlifespan - minlifespan)) + minlifespan); @@ -136,7 +137,10 @@ static void setup_random_colormap (XWindowAttributes *xgwa) make_random_colormap (display, xgwa->visual, xgwa->colormap, colors+1, &ncolors, True, True, 0, True); if (ncolors < 1) + { + fprintf (stderr, "%s: couldn't allocate any colors\n", progname); exit (-1); + } ncolors++; count = ncolors; @@ -234,17 +238,53 @@ static void setup_display (void) Colormap cmap; int cell_size = get_integer_resource ("size", "Integer"); + int osize, alloc_size, oalloc; + int mem_throttle = 0; + char *s; + if (cell_size < 1) cell_size = 1; + osize = cell_size; + + s = get_string_resource ("memThrottle", "MemThrottle"); + if (s) + { + int n; + char c; + if (1 == sscanf (s, " %d M %c", &n, &c) || + 1 == sscanf (s, " %d m %c", &n, &c)) + mem_throttle = n * (1 << 20); + else if (1 == sscanf (s, " %d K %c", &n, &c) || + 1 == sscanf (s, " %d k %c", &n, &c)) + mem_throttle = n * (1 << 10); + else if (1 == sscanf (s, " %d %c", &n, &c)) + mem_throttle = n; + else + { + fprintf (stderr, "%s: invalid memThrottle \"%s\" (try \"10M\")\n", + progname, s); + exit (1); + } + + free (s); + } + XGetWindowAttributes (display, window, &xgwa); originalcolors = get_boolean_resource ("originalcolors", "Boolean"); count = get_integer_resource ("count", "Integer"); if (count < 2) count = 2; + + /* number of colors can't be greater than the half depth of the screen. */ if (count > (1L << (xgwa.depth-1))) count = (1L << (xgwa.depth-1)); + /* Actually, since cell->col is of type char, this has to be small. */ + if (count >= (1L << ((sizeof(arr[0].col) * 8) - 1))) + count = (1L << ((sizeof(arr[0].col) * 8) - 1)); + + if (originalcolors && (count > 8)) { count = 8; @@ -358,6 +398,38 @@ static void setup_display (void) arr_width = windowWidth / cell_size; arr_height = windowHeight / cell_size; + alloc_size = sizeof(cell) * arr_width * arr_height; + oalloc = alloc_size; + + if (mem_throttle > 0) + while (cell_size < windowWidth/10 && + cell_size < windowHeight/10 && + alloc_size > mem_throttle) + { + cell_size++; + arr_width = windowWidth / cell_size; + arr_height = windowHeight / cell_size; + alloc_size = sizeof(cell) * arr_width * arr_height; + } + + if (osize != cell_size) + { + static int warned = 0; + if (!warned) + { + fprintf (stderr, + "%s: throttling cell size from %d to %d because of %dM limit.\n", + progname, osize, cell_size, mem_throttle / (1 << 20)); + fprintf (stderr, "%s: %dx%dx%d = %.1fM, %dx%dx%d = %.1fM.\n", + progname, + windowWidth, windowHeight, osize, + ((float) oalloc) / (1 << 20), + windowWidth, windowHeight, cell_size, + ((float) alloc_size) / (1 << 20)); + warned = 1; + } + } + xSize = windowWidth / arr_width; ySize = windowHeight / arr_height; if (xSize > ySize) @@ -395,8 +467,6 @@ static void drawblock (int x, int y, unsigned char c) static void setup_arr (void) { int x, y; - int i, j; - int a, b; if (arr != NULL) { @@ -419,27 +489,12 @@ static void setup_arr (void) int row = y * arr_width; for (x = 0; x < arr_width; x++) { - arr[row+x].x = x; - arr[row+x].y = y; arr[row+x].speed = 0.0; arr[row+x].growth = 0.0; arr[row+x].col = 0; arr[row+x].isnext = 0; arr[row+x].next = 0; arr[row+x].prev = 0; - for (i = 0; i < 3; i++) - { - a = x + i - 1; - if (a < 0) a = arr_width - 1; - else if (a >= arr_width) a = 0; - for (j = 0; j < 3; j++) - { - b = y + j - 1; - if (b < 0) b = arr_height - 1; - else if (b >= arr_height) b = 0; - arr[row+x].adj[i][j] = &arr[(b * arr_width) + a]; - } - } } } @@ -485,7 +540,7 @@ static void killcell (cell *c) c->next->prev = c->prev; c->prev = 0; c->speed = 0.0; - drawblock (c->x, c->y, c->col); + drawblock (cell_x(c), cell_y(c), c->col); } @@ -548,23 +603,45 @@ static void update (void) for (a = head->next; a != tail; a = a->next) { - if (a->speed == 0) continue; - a->growth += a->speed; - if (a->growth >= orthlim) + static XPoint all_coords[] = {{-1, -1}, {-1, 1}, {1, -1}, {1, 1}, + {-1, 0}, { 1, 0}, {0, -1}, {0, 1}, + {99, 99}}; + + XPoint *coords = 0; + + if (a->speed == 0) continue; + a->growth += a->speed; + + if (a->growth >= diaglim) { - newcell (a->adj[0][1], a->col, a->speed); - newcell (a->adj[2][1], a->col, a->speed); - newcell (a->adj[1][0], a->col, a->speed); - newcell (a->adj[1][2], a->col, a->speed); + coords = all_coords; } - if (a->growth >= diaglim) + else if (a->growth >= orthlim) { - newcell (a->adj[0][0], a->col, a->speed); - newcell (a->adj[0][2], a->col, a->speed); - newcell (a->adj[2][0], a->col, a->speed); - newcell (a->adj[2][2], a->col, a->speed); - killcell (a); + coords = &all_coords[4]; + } + else + { + continue; } + + while (coords->x != 99) + { + int x = cell_x(a) + coords->x; + int y = cell_y(a) + coords->y; + coords++; + + if (x < 0) x = arr_width - 1; + else if (x >= arr_width) x = 0; + + if (y < 0) y = arr_height - 1; + else if (y >= arr_height) y = 0; + + newcell (&arr[y * arr_width + x], a->col, a->speed); + } + + if (a->growth >= diaglim) + killcell (a); } randblip ((head->next) == tail); @@ -577,7 +654,7 @@ static void update (void) a->speed = a->nextspeed; a->growth = 0.0; a->col = a->nextcol; - drawblock (a->x, a->y, a->col + count); + drawblock (cell_x(a), cell_y(a), a->col + count); } } } @@ -602,6 +679,8 @@ char *defaults [] = { "*mindeathspeed: 0.42", "*maxdeathspeed: 0.46", "*originalcolors: false", + "*memThrottle: 22M", /* don't malloc more than this much. + Scale the pixels up if necessary. */ 0 }; @@ -620,6 +699,7 @@ XrmOptionDescRec options [] = { { "-mindeathspeed", ".mindeathspeed", XrmoptionSepArg, 0 }, { "-maxdeathspeed", ".maxdeathspeed", XrmoptionSepArg, 0 }, { "-originalcolors", ".originalcolors", XrmoptionNoArg, "true" }, + { "-mem-throttle", ".memThrottle", XrmoptionSepArg, 0 }, { 0, 0, 0, 0 } }; @@ -642,5 +722,3 @@ void screenhack (Display *dpy, Window win) usleep (delay); } } - -