#include #include #include enum{ RISER, CHORD, DONQ, PEW, KICK, HAT, RIDE, TONE, KNOBS, A4 = 128.0 * 440.0 / 44100.0, A5 = A4 * 2, B♭5 = 256.0 * 466.163761518 / 44100.0 }; typedef struct {float Δφ, φ, out;} Op; typedef struct {float f, q, lp, hp, bp, mem;} Filter; float twiddle[KNOBS], knob[KNOBS]; uchar canvas[128 * 128], bcanvas[128 * 128]; uchar bunnypx[128 * 160], rabbitpx[96 * 96]; Image *px, *rabbit, *bunny[2], *scanimg, *scroller; Rectangle bound, box; struct Glenda{ Image *screen; Screen *_screen; char *winname; Point o; int dx, dy, floor, hop, wctl; uchar c, φ; }glenbot[9]; int t, width, height; float sine[512]; typedef struct Vec Vec; struct Vec{float x, y, z;}; Vec add(Vec a, Vec b){return (Vec){a.x+b.x, a.y+b.y, a.z+b.z};} Vec sub(Vec a, Vec b){return (Vec){a.x-b.x, a.y-b.y, a.z-b.z};} Vec mul(Vec p, float s){return (Vec){p.x*s, p.y*s, p.z*s};} float dot(Vec a, Vec b){return a.x*b.x + a.y*b.y + a.z*b.z;} float mag(Vec v){return sqrt(dot(v, v));} Vec norm(Vec v){ float len; len = mag(v); return len == 0 ? (Vec){0,0,0} : (Vec){v.x/len, v.y/len, v.z/len}; } Vec cross(Vec a, Vec b){ return (Vec){ a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x, }; } struct{Vec pos, right, up, fwd;}camera; void mvcam(float x0, float y0, float z0, float x1, float y1, float z1){ camera.pos = (Vec){x0, y0, z0}; camera.fwd = norm((Vec){x1 - x0, y1 - y0, z1 - z0}); camera.right = cross((Vec){0.f, 1.f, 0.f}, camera.fwd); camera.up = cross(camera.fwd, camera.right); } int glenorglenda(int glen){ static int glenda = 999999999; glenda ^= glenda << 13; glenda ^= glenda >> 17; glenda ^= glenda << 5; return glenda & glen; } float jazz(void){ union{float f; u32int i;}j; j.i = glenorglenda(0x7fffff) | 0x40000000; return j.f - 3.f; } void scan(void){ int i, j; uchar buf[512]; for(i = 0; i < 0x4000; i += 128){ for(j = 0; j < 512; j += 4) buf[j] = buf[j | 1] = buf[j | 2] = buf[j | 3] = canvas[i | j >> 2]; loadimage(scanimg, scanimg->r, buf, 512); box.max.y = box.min.y + 4; draw(screen, box, scanimg, nil, ZP); box.min.y = box.max.y; } box.min.y = box.max.y - 512; } void brush(void){ Point p; uchar c; int θ; c = glenorglenda(255); loadimage(px, px->r, &c, 1); p.x = bound.min.x + glenorglenda(2047) * width / -2000; p.y = bound.min.y + glenorglenda(2047) * height / -2000; for(c &= 15; c < 30; c++){ θ = p.x + p.y; p.x -= sine[θ & 511] * 4.f; p.y -= sine[θ + 128 & 511] * 6.f; draw(screen, bound, px, rabbit, p); } } void peep(void){ int i, j, off; brush(); off = t < 0x348000 ? 128 - (t >> 14 & 127) << 7 : t < 0x400000 ? 0x1700 : 0x1700 - (int)(30.f * sine[t >> 10 & 255]) * 128; for(i = 0; i < off; i++) canvas[i] = 0; off >>= 7; for(i = 0; i + off < 128; i++) for(j = 0; j < 128; j++) canvas[i + off << 7 | j] = bunnypx[i << 7 | j]; scan(); } void floorceiling(void){ int Δ, u, v, x, y; float f, dim; brush(); Δ = t >> 11; dim = 1.0; for(y = 64; y > 3; y--){ f = 63.f / y; dim *= 0.93; v = ((int)(128.f * f) + Δ & 127) << 7; for(x = 0; x < 128; x++){ u = (int)(x * f) + Δ & 127; canvas[63 + y << 7 | x] = canvas[64 - y << 7 | x] = bunnypx[v | u] * dim; } } scan(); } void warp(void){ int Δ, u, v, φ; float x, y; uchar *p; Δ = t >> 14; p = canvas; for(y = -1.f; y < 1.f; y += 0.015625f){ x = -1.f; for(x = -1.f; x < 1.f; x += 0.015625f){ φ = 512.f / PI * sqrt(x*x + y*y + 0.00001f); u = (int)(128.f * (y * sine[φ + 128] + x * sine[φ])) + Δ & 127; v = (int)(128.f * (x * sine[φ + 128] - y * sine[φ])) + Δ & 127; *p++ = bunnypx[v << 7 | u]; } } } void warp1(void){ brush(); warp(); scan(); } float smin(float a, float b, float k){ float h; h = 0.5 + 0.5 * (b - a) / k; if(h < 0.0) h = 0.0; if(h > 1.0) h = 1.0; return a * h + b * (1 - h) - k * h * (1.0 - h); } float ear(Vec p, float s){ float f; p.z -= 1.0; f = p.y - 1.5; p.y = f * 0.923879532511 - p.z * -0.382683432365; p.z = f * -0.382683432365 + p.z * 0.923879532511; f = p.x + s * 0.4; p.x = f * s * -0.980785280403 - p.y * 0.195090322016; p.y = f * 0.195090322016 + p.y * s * -0.980785280403; f = fabs(p.y) - 0.5; if(f < 0.0) f = 0.0; f = sqrt(p.x * p.x + f * f) - 0.1; return sqrt(f * f + p.z * p.z) - 0.2; } float legs(Vec p){ float f; f = p.y + 1.6; p.z += 0.6; p.y = f * 0.923879532511 - p.z * -0.382683432365; p.z = f * -0.382683432365 + p.z * 0.923879532511; p.y -= p.y < 0.0 ? 0.0 : p.y > 0.3 ? 0.3 : p.y; p.x = fabs(p.x) - 0.3; return mag(p) - 0.3; } float eyes(Vec p){ float d; p.x = fabs(p.x) - 0.33; p.y -= 0.57; p.z += 1.1; return mag(p) - 0.03; } float tail(Vec p){ float f; f = p.y + 1.4; p.z -= 1.0; p.y = f * 0.866025403784 - p.z * 0.5; p.z = f * 0.5 + p.z * 0.866025403784; p.y -= p.y < 0.0 ? 0.0 : p.y > 0.3 ? 0.3 : p.y; return mag(p) - 0.3; } float bod(Vec p){ float bot, top; p.y += 0.6; bot = mag((Vec){p.x, p.y * 0.8, p.z * 0.8}); bot *= (bot - 1.0) / mag((Vec){p.x, p.y * 0.64, p.z * 0.64}); top = p.y - 1.2; p.y = top * 0.923879532511 - p.z * 0.382683432365; p.z = top * 0.382683432365 + p.z * 0.923879532511; top = mag((Vec){p.x, p.y, p.z * 0.8}); top *= (top - 1.0) / mag((Vec){p.x, p.y, p.z * 0.64}); return smin(top, bot, 0.6); } float mouth(Vec p){ float f; p.y -= 0.2; p.z += 1.2; f = mag((Vec){p.x * 5.0, p.y * 7.0, p.z * 8.0}); return f * (f - 1.0) / mag((Vec){p.x * 25.0, p.y * 49.0, p.z * 64.0}); } float tooth(Vec p){ float d; p.x = fabs(p.x) - 0.03; p.y = fabs(p.y) - 0.06; p.z = fabs(p.z + 1.1) - 0.15; d = p.x > p.y ? p.x : p.y; d = p.z > d ? p.z : d; d = d < 0.0 ? d : 0.0; if(p.x < 0.0) p.x = 0.0; if(p.y < 0.0) p.y = 0.0; if(p.z < 0.0) p.z = 0.0; return d + mag(p) - 0.05; } float dbunny(Vec p){ float d, tmp; d = ear(p, 1.0); tmp = ear(p, -1.0); if(tmp < d) d = tmp; tmp = mag(add(p, (Vec){0.0, -0.3, 1.2})) - 0.1; /* nose */ if(tmp < d) d = tmp; tmp = eyes(p); if(tmp < d) d = tmp; tmp = mouth(p); if(tmp < d) d = tmp; tmp = tooth(p); if(tmp < d) d = tmp; tmp = legs(p); if(tmp < d) d = tmp; tmp = tail(p); if(tmp < d) d = tmp; return smin(d, bod(p), 0.1); } float dfelloff(Vec p){ float d, tmp; d = ear(p, 1.0); tmp = ear(p, -1.0); if(tmp < d) d = tmp; tmp = legs(p); if(tmp < d) d = tmp; tmp = tail(p); if(tmp < d) d = tmp; d = fabs(smin(d, bod(p), 0.1)) - 0.06; return d > -0.7 - p.z ? d : -0.7 - p.z; } void march(void){ Vec p, n, lux; float d, tot; int x, y, i; y = t >> 14 & 127; if(y == 0) mvcam(-5.5 * sine[t - 0x100000 >> 15 & 511], 2.f, -5.5 * sine[t + 0x300000 >> 15 & 511], 0, 0, 0); for(x = 0; x < 128; x++){ p = add(camera.fwd, mul(camera.right, (x - 64) / 128.f)); p = add(p, mul(camera.up, (64 - y) / 128.f)); n = norm(p); p = camera.pos; for(i = tot = 0.f; i < 50; i++){ tot += d = dbunny(p); if(tot >= 80.f){ bcanvas[y << 7 | x] = 0; continue; } if(d < 0.05f) break; p = add(p, mul(n, d)); } lux = norm(sub(camera.pos, p)); n.x = (dbunny((Vec){p.x + 0.05f, p.y, p.z}) - d) / 0.05f; n.y = (dbunny((Vec){p.x, p.y + 0.05f, p.z}) - d) / 0.05f; n.z = (dbunny((Vec){p.x, p.y, p.z + 0.05f}) - d) / 0.05f; d = dot(lux, n) * 255.f; bcanvas[y << 7 | x] = d < 0.f ? 0 : d > 255.f ? 255 : d; } x = t >> 7 & 1920; for(i = 0; i < 0x4000; i++) canvas[i] = bcanvas[i + (int)(x * sine[i >> 7]) - 1536 & 16256 | i & 127]; scan(); } void felloff(void){ Vec p, n, lux; float d, tot; int x, y, i; y = t >> 14 & 127; if(y == 0) mvcam(-5.5 * sine[t - 0x100000 >> 15 & 511], 2.f, -5.5 * sine[t + 0x300000 >> 15 & 511], 0, 0, 0); for(x = 0; x < 128; x++){ p = add(camera.fwd, mul(camera.right, (x - 64) / 128.f)); p = add(p, mul(camera.up, (64 - y) / 128.f)); n = norm(p); p = camera.pos; for(i = tot = 0.f; i < 50; i++){ tot += d = dfelloff(p); if(tot >= 80.f){ bcanvas[y << 7 | x] = 0; continue; } if(d < 0.05f) break; p = add(p, mul(n, d)); } lux = norm(sub(camera.pos, p)); n.x = (dfelloff((Vec){p.x + 0.05f, p.y, p.z}) - d) / 0.05f; n.y = (dfelloff((Vec){p.x, p.y + 0.05f, p.z}) - d) / 0.05f; n.z = (dfelloff((Vec){p.x, p.y, p.z + 0.05f}) - d) / 0.05f; d = dot(lux, n) * 255.f; bcanvas[y << 7 | x] = d < 0.f ? 0 : d > 255.f ? 255 : d; } x = t >> 7 & 1920; for(i = 0; i < 0x4000; i++) canvas[i] = bcanvas[i + (int)(x * sine[i >> 7]) - 1536 & 16256 | i & 127]; scan(); } void scape(void){ Vec p, n; int x, y, i; float d; y = t >> 14 & 120; if(y == 0){ if(t < 0x3800000) mvcam(0.f, 0.f, 0.f, -sine[(t >> 16) + 128 & 511], 0.f, -sine[(t >> 16) + 256 & 511]); else{ d = sine[t >> 16 & 127]; d *= 100 * d; mvcam(0.f, d, d, 0.f, 0.f, -20); } } do for(x = 0; x < 128; x++){ p = add(mul(camera.fwd, 128), mul(camera.right, x - 64)); n = norm(add(p, mul(camera.up, 64 - y))); p = add(camera.pos, (Vec){48.f, 4.f, 48.f}); for(i = 0; i < 180; i++){ p = add(p, n); if(p.y < 1.0){ bcanvas[y << 7 | x] = 130; break; } if(p.x >= 0.0 && p.x < 96.0 && p.z >= 0.0 && p.z < 96.0 && p.y < 25.0){ d = rabbitpx[(int)p.z * 96 + (int)p.x] / 24.0; if(p.y <= d){ bcanvas[y << 7 | x] = 50 + (int)(p.y) * 17; break; } } } if(i == 180) bcanvas[y << 7 | x] = 217; }while(++y & 7); for(i = 0; i < 0x4000; i++) canvas[i] = bcanvas[i + 1 & 0x3fff] + bcanvas[i + 128 & 0x3fff] + bcanvas[i - 1 & 0x3fff] + bcanvas[i - 128 & 0x3fff] >> 2; scan(); } void paintsky(void){ int x; uchar c; for(x = t >> 14 & 127; x < 512; x += 128){ box.min.x = bound.min.x + x * width / 512; box.max.x = bound.min.x + (x + 1) * width / 512; box.min.y = bound.min.y; box.max.y = bound.min.y + (0.2 + 0.1 * sine[x]) * height; c = 213; loadimage(px, px->r, &c, 1); draw(screen, box, px, nil, ZP); box.min.y = box.max.y; box.max.y = bound.max.y; c = 162; loadimage(px, px->r, &c, 1); draw(screen, box, px, nil, ZP); } } void paintsun(void){ box.max.x = box.min.x + 1999 * sine[t + 0x58000 >> 12 & 511]; box.max.y = box.min.y + 1999 * sine[t + 0xd8000 >> 12 & 511]; line(screen, box.min, box.max, 0, 0, 0, px, ZP); } void paintground(void){ int x; uchar c; for(x = t >> 14 & 127; x < 512; x += 128){ box.min.x = bound.min.x + x * width / 512; box.max.x = bound.min.x + (x + 1) * width / 512; box.min.y = bound.min.y + (0.6 + 0.1 * sine[x + 345 & 511]) * height; box.max.y = bound.min.y + (0.8 + 0.07 * sine[x + 100 >> 1 & 511]) * height; c = 249; loadimage(px, px->r, &c, 1); draw(screen, box, px, nil, ZP); box.min.y = box.max.y; box.max.y = bound.min.y + (0.85 + 0.04 * sine[x + 57 & 511]) * height; c = 198; loadimage(px, px->r, &c, 1); draw(screen, box, px, nil, ZP); box.min.y = box.max.y; box.max.y = bound.max.y; c = 181; loadimage(px, px->r, &c, 1); draw(screen, box, px, nil, ZP); } } void wipe(void){ int x; x = t >> 14 & 127; box.min.x = bound.min.x + x * width / 128; box.max.x = bound.min.x + (x + 1) * width / 128; draw(screen, box, display->black, nil, ZP); } void bounce(struct Glenda *g){ g->o.x += g->dx; if(g->o.x <= bound.min.x){ g->o.x = bound.min.x + 1; g->dx *= -1; }else if(g->o.x + 128 >= bound.max.x){ g->o.x = bound.max.x - 129; g->dx *= -1; } g->floor += g->dy; if(g->floor <= bound.min.y + g->hop){ g->floor = bound.min.y + g->hop + 1; g->dy *= -1; }else if(g->floor + 160 >= bound.max.y){ g->floor = bound.max.y - 161; g->dy *= -1; } g->o.y = g->floor - (int)(sine[g->φ += 16] * g->hop); } void lasso(struct Glenda *g){ static u16int φ; u16int θ; Point t; φ += 97; θ = φ + (u16int)(g - glenbot << 12) >> 7; t.x = (bound.min.x + bound.max.x + (int)(600 * sine[θ & 511])) / 2; t.y = (bound.min.y + bound.max.y + (int)(600 * sine[θ + 128 & 511])) / 2; g->o.x += (t.x - g->o.x) / 75; g->o.y += (t.y - g->o.y) / 75; } void g0(void){ draw(screen, rectaddpt(glenbot->screen->r, glenbot->o), glenbot->screen, nil, ZP); bounce(glenbot); draw(glenbot->screen, glenbot->screen->r, screen, nil, subpt(glenbot->o, ZP)); draw(screen, rectaddpt(glenbot->screen->r, glenbot->o), display->white, bunny[glenbot->dx < 0], ZP); } void g9(void){ int i; for(i = 0; i < 9; i++){ draw(screen, rectaddpt(bunny[0]->r, glenbot[i].o), px, bunny[glenbot[i].dx < 0], ZP); bounce(glenbot + i); glenbot[i].c += 17; loadimage(px, px->r, &glenbot[i].c, 1); draw(screen, rectaddpt(bunny[0]->r, glenbot[i].o), display->white, bunny[glenbot[i].dx < 0], ZP); } } void(*winfn)(struct Glenda*); void gwin(void){ int i; for(i = 0; i < 9; i++){ winfn(glenbot + i); write(glenbot[i].wctl, "current", 7); fprint(glenbot[i].wctl, "move -minx %d -miny %d", glenbot[i].o.x, glenbot[i].o.y); gengetwindow(display, glenbot[i].winname, &glenbot[i].screen, &glenbot[i]._screen, Refnone); draw(glenbot[i].screen, glenbot[i].screen->r, bunny[glenbot[i].dx < 0], nil, ZP); } } void warp2(void){ int i, x; warp(); x = (t + 0xe00000 >> 14) % scroller->r.max.x; unloadimage(scroller, Rect(x, 0, x + 128, font->height), bcanvas, font->height << 7); x = t >> 14; for(i = 0; i < font->height << 7; i++) canvas[i + 128 * ((128 - font->height >> 1) + (int)(9.9f * sine[(i << 2) + x & 511]))] = bcanvas[i] ? bcanvas[i] : glenorglenda(255); gwin(); getwindow(display, Refnone); scan(); } void drama(void){ /* hold yer breth */ } void operate(Op *o, float mod, float amp){ o->φ += o->Δφ; if(o->φ >= 512.f) o->φ -= 512.f; o->out = amp * sine[(int)(o->φ + mod) & 511]; } /* https://www.musicdsp.org/en/latest/Filters/29-resonant-filter.html */ void setfilter(Filter *f, float freq, float res){ f->f = 2.0 * sin(PI * freq / 44100.0); if(f->f == 1.f) f->f = 1.0001; f->q = res + res / (1.f - f->f); } void filter(Filter *f, float in){ f->hp = in - f->mem; f->bp = f->mem - f->lp; f->mem += f->f * (f->hp + f->q * f->bp); f->lp += f->f * (f->mem - f->lp); } int kick(void){ static Op o = {1.024}; static Filter f = {.04, 0.3}, rumble = {0.015, 1.9}; static float amp; if((t & 0x3ffff) == 0) amp = 30000.f; amp *= 0.9997; operate(&o, o.out * 0.00256f + amp * 0.4608, amp); filter(&f, o.out); filter(&rumble, jazz() * 0.097 * (t & 0x3ffff)); return f.lp + rumble.lp; } int closedhat(void){ static Filter f = {1.09, 0.0}; static float amp; switch(t & 0x1ffff) case 0: case 0x10900: amp = (2.8 + jazz()) * 1000.f; amp *= 0.999; filter(&f, jazz() * amp); return f.hp; } int ride(void){ static Filter f = {1.3, -2}; static float amp; if((t & 0x3ffff) == 0x20000) amp = 2000; amp *= 0.9998; filter(&f, jazz() * amp); return f.hp; } float donk[16] = {1.0, 0.0, 1.0, 2.0, 2.563, 0.0, 0.0, 1.0, 1.792, 1.0, 2.0, 3.63, 0.0, 1.5, 1.0, 1.0}; int donq(void){ static Op mod, car = {A4}; static Filter f = {0.1, 0.8}; static float pew; if((t & 0xffff) == 0 && donk[t >> 16 & 15]){ mod.Δφ = car.Δφ * donk[t >> 16 & 15]; pew = 1.0; } pew *= 0.9996; operate(&mod, 0, pew * knob[PEW]); operate(&car, mod.out, 4000); filter(&f, car.out); return f.bp; } int chord(void){ static Op mod, car1, car2, car3; static float modamt, amp; switch(t >> 17 & 15) case 7: case 10: { car1.Δφ = 2.001 * A4; car2.Δφ = 3.998 * A4; car3.Δφ = 4.01 * A4; mod.Δφ = 15.99 * A4; modamt = 80.4; amp = 2000; } operate(&mod, 0, modamt *= 1.00007); operate(&car1, mod.out, amp); operate(&car2, mod.out, amp); operate(&car3, mod.out, amp); mod.Δφ *= 0.99983; amp *= 0.99983; return car1.out + car2.out + car3.out; } int tone(void){ static Op mod = {A5 * 2.3}, mod2 = {A5}, car1, car2, car3; static float amp; switch(t >> 17 & 7){ case 0: case 3: case 6: car1.Δφ = A5 * 2; car2.Δφ = A5 * 2.01; car3.Δφ = A5 * 4; amp = 1000; break; case 5: car1.Δφ = B♭5 * 2; amp = 1000; break; } operate(&mod2, 0, amp * 0.2); operate(&mod, mod2.out, 100); operate(&car1, mod.out, amp); operate(&car2, mod.out, amp); operate(&car3, mod2.out, 200); amp *= 0.99983; return car1.out + car2.out + car3.out; } int eopen(char *s, int m){ int fd; fd = open(s, m); if(fd < 0) sysfatal("open: %r"); return fd; } Image* getimg(char *s){ Image *img; int fd; fd = eopen(s, OREAD); img = readimage(display, fd, 0); if(img == nil) sysfatal("readimage: %r"); close(fd); return img; } Image* allocimg(int x, int y, int chan, int repl){ Image *img; img = allocimage(display, Rect(0, 0, x, y), chan, repl, DNofill); if(img == nil) sysfatal("allocimage: %r"); return img; } void main(int, char**){ Image *scangrey, *scancmap; int audio, wctl, i, j, left, right; void(*anim)(void); uchar buf[0x1400]; /* video: ~34 FPS; audio: ~130 BPM with 64 frames per bar */ char *wsys, rewind[] = "resize -r bekindrewindbekindrewindbekindrewindbekindrewind"; char *scrollmsg = "happy new year 2024 from umbraticus"; char mnt[] = "/mnt/bunnyN/wctl"; if(initdraw(nil, nil, "glenda demo") < 0) sysfatal("initdraw: %r"); audio = eopen("/dev/audio", OWRITE); wctl = eopen("/dev/wctl", ORDWR); rabbit = allocimg(96, 96, GREY4, 0); bunny[0] = allocimg(128, 160, GREY8, 0); bunny[1] = allocimg(128, 160, GREY8, 0); scangrey = allocimg(512, 1, GREY8, 1); scancmap = allocimg(512, 1, CMAP8, 1); glenbot[0].screen = allocimg(120, 160, screen->chan, 0); scroller = allocimg(stringwidth(font, scrollmsg) + 256, font->height, GREY8, 0); draw(scroller, scroller->r, display->black, nil, ZP); string(scroller, Pt(128, 0), display->white, ZP, font, scrollmsg); px = getimg("/lib/bunny.bit"); draw(bunny[0], bunny[0]->r, px, nil, Pt(24, 5)); freeimage(px); unloadimage(bunny[0], bunny[0]->r, bunnypx, sizeof bunnypx); for(i = 0; i < 160; i++){ for(j = 0; j < 128; j++) canvas[127 - j] = bunnypx[i << 7 | j]; loadimage(bunny[1], Rect(0, i, 128, i + 1), canvas, 128); } wsys = getenv("wsys"); if(wsys == nil) sysfatal("no $wsys"); px = getimg("/lib/face/48x48x4/g/glenda.1"); unloadimage(px, px->r, buf, 1152); freeimage(px); for(i = 0; i < 9216; i += 192) for(j = 0; j < 96; j += 4){ right = ~buf[i / 192 * 24 + j / 4]; rabbitpx[i + j] = rabbitpx[i + j + 1] = rabbitpx[i + j + 96] = rabbitpx[i + j + 97] = right & 0xf0; rabbitpx[i + j + 2] = rabbitpx[i + j + 3] = rabbitpx[i + j + 98] = rabbitpx[i + j + 99] = right << 4; } loadimage(rabbit, rabbit->r, rabbitpx, sizeof rabbitpx); px = allocimg(1, 1, CMAP8, 1); for(i = 0; i < 512; i++) sine[i] = sin(PI * 2.0 * i / 512); read(wctl, rewind + 10, 48); write(wctl, "current", 7); write(wctl, "resize -r 0 0 9999 9999", 23); getwindow(display, Refnone); bound = screen->r; width = Dx(bound); height = Dy(bound); for(i = 0; i < 9; i++){ rfork(RFNAMEG); mnt[10] = '1' + i; mnt[11] = 0; j = eopen(wsys, ORDWR); if(mount(j, -1, mnt, MREPL, "new -hide -dx 128 -dy 160") < 0) sysfatal("mount: %r"); glenbot[i].winname = smprint("%s/winname", mnt); if(glenbot[i].winname == nil) sysfatal("smprint: %r"); mnt[11] = '/'; sprint(mnt + 12, "wctl"); glenbot[i].wctl = eopen(mnt, ORDWR); glenbot[i].o.x = bound.min.x + width / 2 - 64 + (int)(jazz() * 0.3 * width); glenbot[i].floor = bound.min.y + height / 2 - 80 + (int)(jazz() * 0.3 * height); glenbot[i].hop = 48 * (i + 8 >> 2); glenbot[i].c = glenorglenda(255); glenbot[i].dx = jazz() * 0.0078125 * width; if(glenbot[i].dx == 0) glenbot[i].dx = 1; glenbot[i].dy = jazz() * 0.0078125 * height; if(glenbot[i].dy == 0) glenbot[i].dx = 1; } glenbot[0].o.x = bound.min.x - 128; glenbot[0].floor = bound.min.y + height / 2 - 160; glenbot[0].dx = -1 - width / 512; glenbot[0].dy = 1; i = eopen("/dev/mouse", OWRITE); fprint(i, "m%11d %11d 0 0 ", bound.max.x, bound.max.y); close(i); /* outta my way */ getwindow(display, Refnone); draw(screen, bound, display->black, nil, ZP); anim = brush; box.min.x = bound.min.x + bound.max.x - 512 >> 1; box.min.y = bound.min.y + bound.max.y - 512 >> 1; box.max = addpt(box.min, Pt(512, 512)); for(i = 0; i < KNOBS; i++) twiddle[i] = 1.0; knob[PEW] = 762.9; twiddle[PEW] = 0.9998; knob[DONQ] = 1.0; while(t < 0x6040000){ switch(t){ case 0x200000: scanimg = scancmap; anim = peep; break; case 0x400000: knob[KICK] = 1.0; break; case 0x800000: knob[HAT] = 1.0; anim = warp1; break; case 0xc00000: knob[RIDE] = 1.0; scanimg = scangrey; for(i = 7808; i < 8832; i++) canvas[i] = 0; anim = floorceiling; break; case 0xe00000: scanimg = scancmap; break; case 0x1000000: anim = paintsky; break; case 0x1200000: buf[0] = 252; loadimage(px, px->r, buf, 1); box.min.x = bound.min.x + 7 * width / 10; box.min.y = bound.min.y + bound.max.y >> 1; i = height / 10; fillellipse(screen, box.min, i, i, px, ZP); anim = paintsun; break; case 0x1400000: anim = paintground; break; case 0x1600000: knob[CHORD] = 0.3; twiddle[CHORD] = 0.997; anim = g0; break; case 0x1e00000: box = bound; anim = wipe; knob[TONE] = 1.2; knob[DONQ] = knob[CHORD] = 0.0; break; case 0x1e40000: knob[KICK] = 0.0; break; case 0x2000000: knob[TONE] = 0.0; knob[KICK] = knob[DONQ] = 1.0; anim = g9; knob[RISER] = 3.9; twiddle[RISER] = 1.0092; knob[PEW] = 762.9; twiddle[PEW] = 1.001; break; case 0x2440000: twiddle[PEW] = 1.0055; knob[KICK] = knob[HAT] = 0.0; break; case 0x2700000: knob[RIDE] = 0.0; anim = drama; break; case 0x2800000: for(i = 8; i < 16; i++) donk[i] = 0.f; twiddle[RISER] = 0.99; twiddle[DONQ] = 1.0; knob[KICK] = knob[DONQ] = knob[HAT] = knob[RIDE] = 1.0; knob[PEW] = 500; twiddle[PEW] = 1.0006; winfn = bounce; freeimage(glenbot[0].screen); glenbot[0].screen = nil; for(i = 0; i < 9; i++) write(glenbot[i].wctl, "unhide", 6); write(wctl, "hide", 4); anim = gwin; break; case 0x2c00000: case 0x5600000: winfn = lasso; break; case 0x5800000: twiddle[KICK] = twiddle[TONE] = twiddle[DONQ] = 0.995; case 0x2e00000: winfn = bounce; break; case 0x3000000: write(wctl, "unhide", 6); getwindow(display, Refnone); draw(screen, bound, display->black, nil, ZP); box.min.x = bound.min.x + bound.max.x - 512 >> 1; box.min.y = bound.min.y + bound.max.y - 512 >> 1; box.max = addpt(box.min, Pt(512, 512)); anim = scape; knob[TONE] = 0.85; break; case 0x4000000: twiddle[PEW] = 0.999; scanimg = scangrey; anim = march; for(i = 0; i < sizeof bcanvas; i++) bcanvas[i] = 0; break; case 0x4200000: draw(bunny[1], bunny[1]->r, display->black, nil, ZP); loadimage(bunny[1], Rect(0, 16, 128, 144), bcanvas, sizeof canvas); break; case 0x4400000: draw(bunny[0], bunny[0]->r, display->black, nil, ZP); loadimage(bunny[0], Rect(0, 16, 128, 144), bcanvas, sizeof canvas); break; case 0x4800000: knob[CHORD] = 0.17; twiddle[CHORD] = 1.0024; twiddle[PEW] = 0.998; knob[RISER] = 3.9; twiddle[RISER] = 1.009; anim = felloff; break; case 0x5000000: knob[RIDE] = knob[KICK] = knob[CHORD] = 0.0; knob[PEW] = 999.9; twiddle[PEW] = 1.00059; break; case 0x5200000: knob[HAT] = 0.0; twiddle[RISER] = 0.992; knob[KICK] = 1.0; fprint(wctl, "resize -r %d %d %d %d", box.min.x - Borderwidth, box.min.y - Borderwidth, box.max.x + Borderwidth, box.max.y + Borderwidth); getwindow(display, Refnone); scanimg = scancmap; anim = warp2; case 0x5100000: case 0x5300000: case 0x5400000: case 0x5500000: case 0x5608000: case 0x5700000: case 0x5808000: for(i = 0; i < 16; i++) donk[i] = 1.7 * (2.0 + jazz()); break; } anim(); for(i = 0; i < KNOBS; i++) knob[i] *= twiddle[i]; flushimage(display, 1); i = t + 0x200000 >> 15 & 511; while((t & 0x1fff) < 0x1400){ left = right = kick() * knob[KICK] + closedhat() * knob[HAT] + ride() * knob[RIDE] + donq() * knob[DONQ] + chord() * knob[CHORD] + jazz() * knob[RISER] ; j = tone() * knob[TONE]; left += j * (0.56 + 0.3 * sine[i]); right += j * (0.55 + 0.3 * sine[i + 128 & 511]); buf[t++ & 0x1fff] = left; buf[t++ & 0x1fff] = left >> 8; buf[t++ & 0x1fff] = right; buf[t++ & 0x1fff] = right >> 8; } write(audio, buf, sizeof buf); t += 0x2c00; } write(wctl, "current", 7); write(wctl, rewind, sizeof rewind); getwindow(display, Refnone); print(scrollmsg); exits(nil); }