#include #include #include #include #include #include #include #include #include #include #include extern const char *__progname; static const char *fbpath = "/dev/cgsix0"; typedef struct fxy FXY; typedef struct pattern PATTERN; struct fxy { float x; float y; } ; struct pattern { PATTERN *link; int rteeth; int wteeth; int rrt; int rwt; double wpct; int roffset; int colour; } ; 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 PATTERN *patterns; static PATTERN **pattail; #define CMAP_BASE 8 /* must be a multiple of 8 */ 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 int add_pattern(const char *s0) { const char *s; char *e; PATTERN *p; int g; static int intval(int *loc, const char *what, int min, int max) { long int li; li = strtol(s,&e,0); if ((s == e) || (li != (int)li) || (li < min) || (li > max)) { fprintf(stderr,"%s: %s: missing/bad %s\n",__progname,s0,what); return(1); } *loc = li; s = e; if (*s) s ++; return(0); } static int dblval(double *loc, const char *what) { double d; d = strtod(s,&e); if ((s == e) || (d < 0) || (d > 1)) { fprintf(stderr,"%s: %s: missing/bad %s\n",__progname,s0,what); return(1); } *loc = d; s = e; if (*s) s ++; return(0); } p = malloc(sizeof(PATTERN)); s = s0; if (intval(&p->rteeth,"ring tooth count",1,16777216)) return(1); if (intval(&p->wteeth,"wheel tooth count",1,16777216)) return(1); if (dblval(&p->wpct,"hole position")) return(1); if (intval(&p->roffset,"ring offset",-p->rteeth,p->rteeth)) return(1); switch (*s) { case 'r': case 'R': p->colour = 1; break; case 'g': case 'G': p->colour = 2; break; case 'b': case 'B': p->colour = 4; break; case 'c': case 'C': p->colour = 6; break; case 'm': case 'M': p->colour = 5; break; case 'y': case 'Y': p->colour = 3; break; case 'w': case 'W': p->colour = 7; break; case 'k': case 'K': p->colour = 0; break; case '\0': p->colour = 7; break; default: fprintf(stderr,"%s: %s: missing/bad colour\n",__progname,s0); return(1); break; } g = gcd(p->rteeth,p->wteeth); p->rrt = p->rteeth / g; p->rwt = p->wteeth / g; *pattail = p; pattail = &p->link; return(0); } static void init(int ac, char **av) { int i; int errs; pattail = &patterns; errs = 0; for (i=1;idraw & 0xa0000000) == 0xa0000000) ; } static void drain(void) { while (fbc->s & 0x10000000) ; } static void setcmap(void) { int i; bt->addr = 0; for (i=0;icmap = 0; bt->cmap = 0; bt->cmap = 0; } for (i=0;i<8;i++) { bt->cmap = (i & 1) ? 0xff000000 : 0; bt->cmap = (i & 2) ? 0xff000000 : 0; bt->cmap = (i & 4) ? 0xff000000 : 0; } } static void fbsetup(void) { int fd; struct fbgattr a; fd = open(fbpath,O_RDWR,0); if (fd < 0) { fprintf(stderr,"%s: can't open %s: %s\n",__progname,fbpath,strerror(errno)); exit(1); } if ( (ioctl(fd,FBIOGATTR,&a) < 0) || (a.fbtype.fb_type != FBTYPE_SUNFAST_COLOR) || (a.fbtype.fb_width != 1152) || (a.fbtype.fb_height != 900) || (a.fbtype.fb_depth != 8) ) { fprintf(stderr,"%s: %s: not a usable cgsix\n",__progname,fbpath); exit(1); } fbmaplen = 0x16000 + a.fbtype.fb_size; fbmap = mmap(0,fbmaplen,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0x70000000); if (fbmap == MAP_FAILED) { fprintf(stderr,"%s: can't mmap %s: %s\n",__progname,fbpath,strerror(errno)); exit(1); } fbc = fbmap; thc = (void *)(0x5000+(unsigned char *)fbmap); bt = (void *)(0x2000+(unsigned char *)fbmap); vram = 0x16000 + (unsigned char *)fbmap; setcmap(); fbc->bg = 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 FXY compute(PATTERN *p, double wca) { double wa; double o; wca *= 2*M_PI / p->wteeth; o = p->roffset * 2*M_PI / p->rteeth; wa = wca - ((wca * p->rrt) / p->rwt); return((FXY){ x : ( ((p->rrt-p->rwt) * cos(wca+o)) + (p->rwt * cos(wa+o) * p->wpct) ) / p->rrt, y : ( ((p->rrt-p->rwt) * sin(wca+o)) + (p->rwt * sin(wa+o) * p->wpct) ) / p->rrt }); } static void pt(FXY loc) { fbc->aliney = (int)(450-(loc.y*449)); fbc->alinex = (int)(576+(loc.x*449)); } static void drawpattern(PATTERN *p) { int i; FXY loc; fbc->fg = CMAP_BASE + p->colour; pt(compute(p,0)); for (i=0;i<=1024;i++) { loc = compute(p,(i*p->wteeth*p->rwt)/1024.0); pt(loc); draw(); } } static void drawpatterns(void) { PATTERN *p; for (p=patterns;p;p=p->link) drawpattern(p); drain(); } int main(int, char **); int main(int ac, char **av) { init(ac,av); fbsetup(); drawpatterns(); return(0); }