#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define FPS 50 extern const char *__progname; #define NPOINTS 1000 static const char *fbpath = "/dev/cgsix0"; typedef struct fxy FXY; typedef struct figure FIGURE; struct fxy { float x; float y; } ; struct figure { FIGURE *link; const char *name; int closed; FXY pts[NPOINTS]; } ; static float curcol_r; static float curcol_g; static float curcol_b; static int curcol_plane; static float curcol_da; static float curcol_dx; static float curcol_dy; static float *curcol_xp; static float *curcol_yp; static float *curcol_zp; static void *fbmap; static int fbmaplen; static volatile struct cg6fbc *fbc; static volatile struct cg6thc *thc; static volatile struct brooktree *bt; static volatile unsigned char *vram; static int drawbit; static int timerfd; static FIGURE *figures; static FIGURE *prevfigure; static int prevrot; static int prevtrans; static double fraction; static FIGURE *nextfigure; static int nextrot; static int nexttrans; static float blend[NPOINTS]; #define CMAP_BASE 20 /* must be a multiple of 4 */ #define COL_BG (CMAP_BASE) #define COL_FG (CMAP_BASE+3) #define PM_0 1 #define PM_1 2 __inline__ static float fclamp(float, float, float) __attribute__((__const__)); __inline__ static float fclamp(float v, float min, float max) { return((vmax)?max:v); } static void setcmap(int bit) { int i; int x; bt->addr = 0; for (i=0;icmap = 0; bt->cmap = 0; bt->cmap = 0; } for (i=0;i<4;i++) { x = i & (bit ? PM_1 : PM_0); bt->cmap = x ? 0xff000000&(unsigned int)(fclamp(curcol_r,0,1)*0xffffffff) : 0; bt->cmap = x ? 0xff000000&(unsigned int)(fclamp(curcol_g,0,1)*0xffffffff) : 0; bt->cmap = x ? 0xff000000&(unsigned int)(fclamp(curcol_b,0,1)*0xffffffff) : 0; } } static void draw(void) { while ((fbc->draw & 0xa0000000) == 0xa0000000) ; } static void drain(void) { while (fbc->s & 0x10000000) ; } static void add_figure(void (*fn)(FIGURE *)) { FIGURE *f; f = malloc(sizeof(FIGURE)); (*fn)(f); f->link = figures; figures = f; } #define LISSFN(mx,my) \ static void liss_##mx##_##my(FIGURE *f) { int i; f->closed = 1; f->name \ = "liss_" #mx "_" #my; for (i=0;ipts[i].x = (sin((mx)*i*2*M_PI/(NPOINTS-1)) + 1) / 2; \ f->pts[i].y = (cos((my)*i*2*M_PI/(NPOINTS-1)) + 1) / 2; \ } } LISSFN(1,1) LISSFN(1,3) LISSFN(1,5) LISSFN(2,1) LISSFN(2,3) LISSFN(2,5) LISSFN(3,5) LISSFN(4,1) LISSFN(4,3) LISSFN(4,5) #undef LISSFN #define SINFN(n) \ static void open_sin_##n(FIGURE *f) { int i; f->closed = 0; f->name = \ "open_sin_" #n; for (i=0;ipts[i].x = i / \ (double)(NPOINTS-1); f->pts[i].y = \ (sin((n)*i*2*M_PI/(NPOINTS-1)) + 1) / 2; } } SINFN(1) SINFN(2) SINFN(3) SINFN(4) SINFN(5) #undef SINFN #define SPIRAL(n) \ static void spiral_##n(FIGURE *f) { int i; f->closed = 0; f->name = \ "spiral_" #n; for (i=0;ipts[i].x \ = ((r * cos(a)) + 1) / 2; f->pts[i].y = ((r * sin(a)) + 1) / 2; } } SPIRAL(3) SPIRAL(5) SPIRAL(7) #undef SINFN #define WIGGLE(n,m) \ static void wiggle_##n##_##m(FIGURE *f) { int i; f->closed = 1; f->name \ = "wiggle_" #n "_" #m; for (i=0;ipts[i].x = ((r * cos(a)) + 1) / 2; f->pts[i].y = \ ((r * sin(a)) + 1) / 2; } } WIGGLE(16,4); WIGGLE(32,4); WIGGLE(37,3); WIGGLE(23,3); #undef WIGGLE static void box1(FIGURE *f) { int c1; int c2; int c3; int i; f->closed = 1; f->name = "box1"; c2 = (NPOINTS-1) / 2; c1 = c2 / 2; c3 = (c2 + NPOINTS-1) / 2; for (i=0;ipts[i].x = i / (double)c1; f->pts[i].y = 0; } for (;ipts[i].x = 1; f->pts[i].y = (i - c1) / (double)(c2-c1); } for (;ipts[i].x = (c3 - i) / (double)(c3-c2); f->pts[i].y = 1; } for (;ipts[i].x = 0; f->pts[i].y = (NPOINTS-1 - i) / (double)(NPOINTS-1-c3); } } static void box2(FIGURE *f) { int c1; int c2; int c3; int i; f->closed = 1; f->name = "box2"; c2 = (NPOINTS-1) / 2; c1 = c2 / 2; c3 = (c2 + NPOINTS-1) / 2; for (i=0;ipts[i].x = 0; f->pts[i].y = 0; } for (;ipts[i].x = 1; f->pts[i].y = 0; } for (;ipts[i].x = 1; f->pts[i].y = 1; } for (;ipts[i].x = 0; f->pts[i].y = 1; } f->pts[NPOINTS-1] = f->pts[0]; } static void modulated(FIGURE *f) { int i; double d; f->closed = 0; f->name = "modulated"; for (i=0;ipts[i].x = d; f->pts[i].y = ((sin(d*M_PI) * sin(d*15*M_PI)) + 1) / 2; } } static __inline__ int gcd(int, int) __attribute__((__const__)); static __inline__ int gcd(int a, int b) { while (b) { int t; t = a % b; a = b; b = t; } return(a); } static void spirograph(FIGURE *f, int rteeth, int wteeth, double wfrac) { int i; double r; double wca; double wa; i = gcd(rteeth,wteeth); rteeth /= i; wteeth /= i; r = 1 - (wteeth * (1-wfrac) / rteeth); f->closed = 1; for (i=0;ipts[i].x = ( ( ( ((rteeth-wteeth) * cos(wca) / rteeth) + (wteeth * cos(wa) * wfrac / rteeth) ) / r) + 1 ) / 2; f->pts[i].y = ( ( ( ((rteeth-wteeth) * sin(wca) / rteeth) + (wteeth * sin(wa) * wfrac / rteeth) ) / r) + 1 ) / 2; } } #define SPIROGRAPH(n,r,w,p)\ static void spirograph_##n(FIGURE *f) { f->name = "spirograph "#r" "#w" "#p;\ spirograph(f,r,w,p); } SPIROGRAPH(a,5,3,.8) SPIROGRAPH(b,5,3,.8) SPIROGRAPH(c,7,3,.9) SPIROGRAPH(d,11,4,.9) SPIROGRAPH(e,11,8,.9) SPIROGRAPH(f,15,8,1) #undef SPIROGRAPH static FIGURE *pickfigure(FIGURE *exclude) { int n; FIGURE *f; FIGURE *p; p = 0; n = 0; for (f=figures;f;f=f->link) { if (f == exclude) continue; n ++; if (random() % n) continue; p = f; } return(p?:figures); } static void set_curcol_xyz(void) { switch (curcol_plane) { case 0: curcol_xp = &curcol_r; curcol_yp = &curcol_g; curcol_zp = &curcol_b; break; case 1: curcol_xp = &curcol_g; curcol_yp = &curcol_b; curcol_zp = &curcol_r; break; case 2: curcol_xp = &curcol_b; curcol_yp = &curcol_r; curcol_zp = &curcol_g; break; default: abort(); break; } } static void set_curcol_dxy(void) { while (curcol_da < -M_PI) curcol_da += 2*M_PI; while (curcol_da > M_PI) curcol_da -= 2*M_PI; curcol_dx = cos(curcol_da) / (10 * FPS); curcol_dy = sin(curcol_da) / (10 * FPS); } static int rand_trans(void) { return(random()&15); } static void init(void) { int i; figures = 0; add_figure(&liss_1_1); add_figure(&liss_1_3); add_figure(&liss_1_5); add_figure(&liss_2_1); add_figure(&liss_2_3); add_figure(&liss_2_5); add_figure(&liss_3_5); add_figure(&liss_4_1); add_figure(&liss_4_3); add_figure(&liss_4_5); add_figure(&open_sin_1); add_figure(&open_sin_2); add_figure(&open_sin_3); add_figure(&open_sin_4); add_figure(&open_sin_5); add_figure(&spiral_3); add_figure(&spiral_5); add_figure(&spiral_7); add_figure(&wiggle_16_4); add_figure(&wiggle_32_4); add_figure(&wiggle_37_3); add_figure(&wiggle_23_3); add_figure(&box1); add_figure(&box2); add_figure(&modulated); add_figure(&spirograph_a); add_figure(&spirograph_b); add_figure(&spirograph_c); add_figure(&spirograph_d); add_figure(&spirograph_e); add_figure(&spirograph_f); srandom(time(0)); for (i=getpid();i>0;i--) random(); prevfigure = figures; prevrot = 0; prevtrans = 0; nextfigure = pickfigure(prevfigure); nextrot = nextfigure->closed ? random() % (NPOINTS-1) : 0; nexttrans = rand_trans(); fraction = 1; curcol_r = 1; curcol_g = 1; curcol_b = 1; curcol_plane = random() % 3; curcol_da = ((random() & 0x7fffffff) * (M_PI/2) / (double)0x80000000U) - M_PI; set_curcol_dxy(); set_curcol_xyz(); for (i=0;ibg = 0; fbc->pixelm = ~0; fbc->s = 0; fbc->mode = 0x00229540; /* not all bits known */ fbc->alu = 0xc0000000 /* GX_PLANE_MASK */ | 0x20000000 /* GX_PIXEL_ONES */ | 0x00800000 /* GX_ATTR_SUPP (?) */ | 0x00000000 /* GX_RAST_BOOL (?) */ | 0x00000000 /* GX_PLOT_PLOT (?) */ | 0x08000000 /* GX_PATTERN_ONES */ | 0x01000000 /* GX_POLYG_OVERLAP */ | ALU_FG; fbc->clip = 0; fbc->offx = 0; fbc->offy = 0; fbc->clipminx = 0; fbc->clipminy = 0; fbc->clipmaxx = 1151; fbc->clipmaxy = 899; fbc->fg = CMAP_BASE; fbc->pm = ~0; drain(); fbc->arecty = 0; fbc->arectx = 0; fbc->arecty = 900; fbc->arectx = 1152; draw(); drain(); close(fd); } static void timersetup(void) { struct itimerval itv; timerfd = socket(AF_TIMER,SOCK_STREAM,0); if (timerfd < 0) { fprintf(stderr,"%s: AF_TIMER socket: %s\n",__progname,strerror(errno)); exit(1); } itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 1000000 / FPS; itv.it_value = itv.it_interval; write(timerfd,&itv,sizeof(itv)); } static FXY getpoint(FIGURE *f, int inx, int rot, int trans) { FXY p; p = f->closed ? f->pts[(((trans&8)?(NPOINTS*2)-3-inx:inx)+rot)%(NPOINTS-1)] : f->pts[(trans&8)?NPOINTS-1-inx:inx]; if (trans & 1) p.x = 1 - p.x; if (trans & 2) p.y = 1 - p.y; return((trans&4)?(FXY){x:p.y,y:p.x}:p); } static FXY interp(FXY, float, FXY) __attribute__((__const__)); static FXY interp(FXY a, float f, FXY b) { return((FXY){x:(a.x*(1-f))+(b.x*f),y:(a.y*(1-f))+(b.y*f)}); } static void drawit(void) { int i; FXY prev; FXY next; FXY cur; float f; f = (cos(fraction*M_PI) + 1) / 2; for (i=0;ialiney = (int)(cur.y*899); fbc->alinex = (int)(cur.x*1151); if (i) draw(); } drain(); } static void setblend(void) { int x; int i; x = random() % NPOINTS; for (i=0;ipixelm = ~0; fbc->s = 0; fbc->mode = 0x00229540; /* not all bits known */ fbc->alu = 0xc0000000 /* GX_PLANE_MASK */ | 0x20000000 /* GX_PIXEL_ONES */ | 0x00800000 /* GX_ATTR_SUPP (?) */ | 0x00000000 /* GX_RAST_BOOL (?) */ | 0x00000000 /* GX_PLOT_PLOT (?) */ | 0x08000000 /* GX_PATTERN_ONES */ | 0x01000000 /* GX_POLYG_OVERLAP */ | ALU_FG; fbc->clip = 0; fbc->offx = 0; fbc->offy = 0; fbc->clipminx = 0; fbc->clipminy = 0; fbc->clipmaxx = 1151; fbc->clipmaxy = 899; fbc->pm = drawbit ? ~PM_0 : ~PM_1; fbc->fg = CMAP_BASE; fbc->arecty = 0; fbc->arectx = 0; fbc->arecty = 899; fbc->arectx = 1151; draw(); fbc->fg = 3; fbc->pm = drawbit ? PM_1 : PM_0; drawit(); setcmap(drawbit); drawbit = ! drawbit; if (fraction == 1) { prevfigure = nextfigure; prevrot = prevfigure->closed ? random() % (NPOINTS-1) : 0; prevtrans = nexttrans; nextfigure = pickfigure(prevfigure); nextrot = nextfigure->closed ? random() % (NPOINTS-1) : 0; nexttrans = rand_trans(); fraction = 0; setblend(); } else { fraction += 1 / (double)(5 * FPS); if (fraction > 1) fraction = 1; } set = 0; cx = *curcol_xp += curcol_dx; cy = *curcol_yp += curcol_dy; if (cx < 0) { *curcol_xp = 0; curcol_da = M_PI - curcol_da; set = 1; } else if (cy < 0) { *curcol_yp = 0; curcol_da = - curcol_da; set = 1; } else if (cx > 1) { *curcol_xp = 1; curcol_plane = (curcol_plane+1) % 3; curcol_da -= M_PI / 2; set = 1; } else if (cy > 1) { *curcol_yp = 1; curcol_plane = (curcol_plane+2) % 3; curcol_da += M_PI / 2; set = 1; } if (set) { set_curcol_xyz(); curcol_da += ((random() & 0x7fffffff) / (double)0x80000000U) * .1; set_curcol_dxy(); } } int main(void); int main(void) { init(); fbsetup(); timersetup(); while (1) { struct timersock_event e; read(timerfd,&e,sizeof(e)); step(); } }