minow@decvax.UUCP (06/15/87)
This program puts interesting wallpaper on your monitor. Have fun. munchasm.c (which is the central algorithm in assembler optimized to use the BCHG instruction is left as an exercise for the student.) Martin Minow decvax!minow -------- /* * Munching squares. * Originally from HAKMEM (MIT AI memo 239). According to * HAKMEM, this was discovered by Jackson Wright on the * MIT RLE PDP-1 circa 1962. The PDP-10 algorithm is * DATAI 2 * ADDB 1,2 * ROTC 2,-22 * XOR 1,2 * JRST .-4 * * This version is copyright 1987 by Martin Minow, Arlington MA. * It may be copied and modified without permission, but may not * be sold for direct personal gain. * */ #include <osbind.h> #include <ctype.h> #include <linea.h> #define EOS '\0' #define TRUE 1 #define FALSE 0 /* * USE_ASM is non-zero if compiling with munchasm.c */ #ifndef USE_ASM #define USE_ASM 1 #endif #ifndef BITS #define BITS 10 /* Size of display is 1 << BITS */ #endif #define SIDE (1 << BITS) char bits[] = { /* Bitmask to XOR to the screen */ 1, 2, 4, 8, 16, 32, 64, 128 }; typedef struct seed { int xseed, yseed; } SEED; SEED seeds[] = { /* x y Note: X should be non-zero */ { 1, 0 }, { 1, 1 }, { 17, 17 }, { 73, 18 }, { 1, (SIDE / 4) }, { 2, 0 }, { 16, (SIDE / 4) }, { 1, (SIDE / 2) }, { 2, (SIDE / 2) }, { 4, (SIDE / 2) }, { 6, (SIDE / 2) }, { 8, (SIDE / 2) }, { 16, (SIDE / 2) }, { 1, (SIDE / 2) - 1 }, { 2, (SIDE - 1) }, { 2, (SIDE / 4) * 3 }, { 1, 9 }, { 3, 0 }, { 4, 0 }, { 18, 73 }, { 15, 0 }, { 17, 0 }, { 0, 0 } }; /* * Define the physical screen -- the defind values are for the Atari ST * Change these and you'll have to hack munchasm.c, too. */ #define Xpixels 640 #define Ypixels 400 #define MASK ((1 << BITS) - 1) #define BYTES_PER_ROW (Xpixels / 8) #define xsize SIDE /* Pixels in one row */ #define ysize SIDE /* Pixels in one column */ #define xorigin ((Xpixels - xsize) / 2) #define yorigin ((Ypixels - ysize) / 2) long origin; /* Upper-left-hand corner */ long maxcount; /* (xsize * ysize) * 2 */ unsigned long xseed, yseed; int index = 0; char *the_screen; unsigned char signon[] = "\033EMunching squares (from Hackmem)\r\n\ Copyright \275 1987, Martin Minow, Arlington Mass. 02174, U.S.A.\r\n\ This program may be freely redistributed, but may not be sold\r\n\ for direct personal gain.\r\n\ Portions of this program copyright \275 1984, Mark Williams Company.\r\n\ Type any character to exit (eventually). Type 'x' to enter parameters.\r\n\ \r\n"; main() { register int c; /* * Write the signon message to the console, then stall * for three seconds or so. */ hidemouse(); Cconws(signon); for (index = 0; index < 210; index++) Vsync(); /* * index points into the [x,y] seeds. * origin is the offset to the image's [0,0] point. * the_screen -> the [0,0] byte of the physical screen. * maxcount is the number of points to plot for a display. */ index = 0; origin = (yorigin * BYTES_PER_ROW) + (xorigin / 8); the_screen = Physbase(); maxcount = ((long) xsize) * ((long) ysize) * 2; Cconws("\033E\033f"); /* Clear screen, cursor off */ while (Cconis() == 0) { if (seeds[index].xseed == 0 && seeds[index].yseed == 0) index = 0; xseed = seeds[index].xseed; /* Get another seed. */ yseed = seeds[index].yseed; index++; Cconws("\033E"); /* Clear screen */ munching(); } Cconws("\033E\033e"); /* Clear screen, cursor on */ /* * Read the character from the console. Maybe interact. */ if ((c = Cconin()) == 'x' || c == 'X') { for (;;) { getseed(); if (xseed == 0 && yseed == 0) break; Cconws("\033E\033f"); munching(); } } Cconws("\033E\033e"); /* Clear screen, cursor on */ showmouse(); } #if !USE_ASM munching() /* * Do one munch cycle (section of a 1024x1024 window) */ { register unsigned long acc, seed; register unsigned short x, y; register long count; short i; register char *screen = the_screen; acc = 0; seed = (yseed << BITS) + xseed; count = maxcount; do { /* * Get the x and y parts of the accumulator. * Then, convert [x,y] into a byte address * If the address is on-screen, use the low-order * 3 bits of x to select the bit to invert and do it. * Finally, update the accumulator. */ x = acc & MASK; y = ((acc >> BITS) & MASK) ^ x; i = (y * BYTES_PER_ROW) + (x >> 3) + origin; #if BITS > 8 if (i >= 0 && i < (Ypixels * BYTES_PER_ROW)) #else #assert ((1 << BITS) - 1) * ((1 << BITS) - 1) < (Ypixels * BYTES_PER_ROW) #endif screen[i] ^= bits[x & 0x7]; acc += seed; } while (--count != 0); } #endif getseed() { register char *bp; extern char *getint(); char buf[130]; /* * Position cursor and turn it on. */ Cconws("\033E\033eEnter seed, 0,0 to exit: "); buf[0] = (sizeof buf) - 2; Cconrs(buf); buf[buf[1] + 2] = EOS; bp = getint(&buf[2], &xseed); getint(bp, &yseed); } char * getint(bp, result) register char *bp; register unsigned long *result; { *result = 0; while (*bp != EOS && !isdigit(*bp)) bp++; while (isdigit(*bp)) { *result *= 10; *result += (*bp - '0'); bp++; } return (bp); }