Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

boot-anim: matrix-rain BG + 3s→2s runtime (boot into notepat faster)

Two changes to the startup-fade animation (draw_startup_fade):

1. Matrix-rain background. Pseudo-CJK glyphs falling in columns —
started as an homage to the "garbled-character" bug from when the
firmware loaded a chain-loading EFI binary (splash.efi) directly
and displayed its bytes as UTF-16 CJK. User liked the look, so
kept as a proper boot aesthetic. Glyphs are random 7x9 pixel
patterns drawn per-frame with per-column xorshift seeds (no CJK
font needed). Bright white-green leader, fading green trail.
Rain alpha is dimmed in day mode so the title stays legible; more
prominent in dark mode where it gets the full matrix vibe.

2. Cut animation 180f (3s) → 120f (2s). Hold-period to accept keys
dropped 60f (1s) → 40f (667ms). The 3-second hold was branding
padding; the W hint is legible within 400ms. Shaves 1s off every
cold boot without losing the install-during-boot window.

Sub-effects scaled to the new total (subtitle fade 130→80, badges
60→40). Arpeggio boot notes at f=10/20/30/42 stay put — still
within the 2s envelope, no retune needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+78 -11
+78 -11
fedac/native/src/ac-native.c
··· 2441 2441 char greet_city[96]; 2442 2442 read_cached_city(greet_city, sizeof greet_city); 2443 2443 2444 - // 180 frames = 3 second animation. 2445 - // W press → halt and show y/n confirmation 2446 - // Any other key → skip animation and start playing 2447 - int total_frames = 180; // 3 seconds 2444 + // 120 frames = 2 second animation (was 180/3s — shaved 1s off every boot). 2445 + // W press → halt and show y/n confirmation. 2446 + // Any other key → skip animation and start playing. 2447 + // Keys accepted after frame 40 (667ms hold so the W hint is legible). 2448 + int total_frames = 120; 2449 + int hold_frames = 40; 2448 2450 int skip_anim = 0; 2449 2451 int w_pressed = 0; 2452 + // Matrix-rain background state — persistent across frames. One entry 2453 + // per column; column width fixed at 10 px. 2454 + #define RAIN_MAX_COLS 128 2455 + int rain_col_y[RAIN_MAX_COLS]; 2456 + int rain_col_speed[RAIN_MAX_COLS]; 2457 + unsigned int rain_col_seed[RAIN_MAX_COLS]; 2458 + { 2459 + unsigned int s = (unsigned int)time(NULL); 2460 + for (int c = 0; c < RAIN_MAX_COLS; c++) { 2461 + s ^= s << 13; s ^= s >> 17; s ^= s << 5; 2462 + rain_col_y[c] = -(int)(s % 400); 2463 + s ^= s << 13; s ^= s >> 17; s ^= s << 5; 2464 + rain_col_speed[c] = 2 + (int)(s % 4); 2465 + s ^= s << 13; s ^= s >> 17; s ^= s << 5; 2466 + rain_col_seed[c] = s; 2467 + } 2468 + } 2450 2469 for (int f = 0; f < total_frames && !skip_anim && !w_pressed; f++) { 2451 2470 double t = (double)f / (double)total_frames; 2452 2471 ··· 2456 2475 for (int ki = 0; ki < key_fd_count; ki++) { 2457 2476 while (read(key_fds[ki], &ev, sizeof(ev)) == sizeof(ev)) { 2458 2477 if (ev.type == EV_KEY && ev.value == 1) { 2459 - // First 60 frames (1 second): ignore all keys 2460 - // Ensures W hint is visible before accepting input 2461 - if (f < 60) { 2478 + if (f < hold_frames) { 2462 2479 fprintf(stderr, "[boot-anim] drained key %d at f=%d (hold period)\n", ev.code, f); 2463 2480 continue; 2464 2481 } ··· 2538 2555 int bg_b = start_b + (int)((target_b - start_b) * fade_t); 2539 2556 graph_wipe(graph, (ACColor){(uint8_t)bg_r, (uint8_t)bg_g, (uint8_t)bg_b, 255}); 2540 2557 2558 + // Matrix-rain BG: pseudo-CJK glyphs falling in columns. Started 2559 + // as an homage to the "garbled-character" bug we hit when the 2560 + // firmware loaded a chain-loading EFI binary directly — user 2561 + // liked the look, so we're keeping it as a boot aesthetic. 2562 + // Glyphs are random 7x9 pixel patterns drawn per-frame with a 2563 + // per-column xorshift seed; no CJK font needed. Brighter leader 2564 + // + fading trail for the classic terminal-rain feel. 2565 + { 2566 + int col_w = 10; 2567 + int glyph_w = 7, glyph_h = 9; 2568 + int nc = screen->width / col_w; 2569 + if (nc > RAIN_MAX_COLS) nc = RAIN_MAX_COLS; 2570 + // Slight fade toward title, so rain doesn't fight the text. 2571 + int rain_alpha_scale = is_day ? 80 : 180; 2572 + for (int c = 0; c < nc; c++) { 2573 + rain_col_y[c] += rain_col_speed[c]; 2574 + if (rain_col_y[c] > screen->height + glyph_h * 12) { 2575 + unsigned int s = rain_col_seed[c]; 2576 + s ^= s << 13; s ^= s >> 17; s ^= s << 5; 2577 + rain_col_seed[c] = s; 2578 + rain_col_y[c] = -(int)(s % 300); 2579 + rain_col_speed[c] = 2 + (int)(s % 4); 2580 + } 2581 + int cx = c * col_w + 1; 2582 + // Trail of ~10 glyphs fading behind the leader. 2583 + for (int trail = 0; trail < 10; trail++) { 2584 + int gy = rain_col_y[c] - trail * glyph_h; 2585 + if (gy < -glyph_h || gy >= screen->height) continue; 2586 + int tb = (trail == 0) ? 220 : 180 - trail * 18; 2587 + if (tb < 15) continue; 2588 + int b = (tb * rain_alpha_scale) >> 8; 2589 + // Leader glows a bit whitish — classic matrix-rain tip. 2590 + ACColor cg = (trail == 0) 2591 + ? (ACColor){ (uint8_t)(b * 0.8), 255, (uint8_t)(b * 0.8), (uint8_t)b } 2592 + : (ACColor){ 40, (uint8_t)(b * 0.9 + 20), (uint8_t)(b * 0.4), (uint8_t)b }; 2593 + graph_ink(graph, cg); 2594 + // Random 7x9 bitmap from deterministic seed + column + trail + slow frame shimmer. 2595 + unsigned int gseed = rain_col_seed[c] ^ ((unsigned)trail * 2654435761u) ^ ((unsigned)(f / 4) * 2246822519u); 2596 + for (int row = 0; row < glyph_h; row++) { 2597 + for (int col = 0; col < glyph_w; col++) { 2598 + gseed ^= gseed << 13; gseed ^= gseed >> 17; gseed ^= gseed << 5; 2599 + if (gseed & 1) graph_plot(graph, cx + col, gy + row); 2600 + } 2601 + } 2602 + } 2603 + } 2604 + } 2605 + 2541 2606 // Title — per-handle palette (fallback rainbow), animated pulse 2542 2607 int alpha = (int)(255.0 * fade_t); 2543 2608 if (alpha > 0) { ··· 2625 2690 #endif 2626 2691 2627 2692 // Subtitle: "enjoy <city>!" appears after frame 130 2628 - if (f > 130) { 2629 - double sub_t = (double)(f - 130) / 30.0; 2693 + // Scaled for 120-frame total (was gated at 130 of 180). 2694 + if (f > 80) { 2695 + double sub_t = (double)(f - 80) / 20.0; 2630 2696 if (sub_t > 1.0) sub_t = 1.0; 2631 2697 int sub_alpha = (int)(180.0 * sub_t); 2632 2698 graph_ink(graph, is_day ··· 2640 2706 } 2641 2707 2642 2708 // Auth badges (bottom-left): pixel crab = Claude, pixel octocat = GitHub 2643 - if (f > 60 && alpha > 80) { 2709 + // Badges — scaled to appear earlier in the shorter animation. 2710 + if (f > 40 && alpha > 80) { 2644 2711 int badge_x = 6; 2645 2712 int badge_y = screen->height - 22; 2646 - double badge_t = (double)(f - 60) / 40.0; 2713 + double badge_t = (double)(f - 40) / 30.0; 2647 2714 if (badge_t > 1.0) badge_t = 1.0; 2648 2715 int ba = (int)(220.0 * badge_t); // badge alpha 2649 2716