From e83b3c462c532f07e09b4ecd42610e24a7fdbe9a Mon Sep 17 00:00:00 2001 From: "lukasz@orzechowski.eu" Date: Tue, 24 Mar 2026 00:53:30 +0100 Subject: [PATCH] Add Spectre-style boot intro with decrypt animation + version system Animated splash: boot lines with system detection, ASCII logo with character-by-character decrypt effect. --no-intro to skip. v1.0.0. Co-Authored-By: Claude Opus 4.6 (1M context) --- systats.py | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/systats.py b/systats.py index 1aaed70..dff7b64 100755 --- a/systats.py +++ b/systats.py @@ -1214,9 +1214,166 @@ class Renderer: curses.color_pair(C_POPUP_HL) | curses.A_BOLD) +# ─── Intro ────────────────────────────────────────────────────────── + +VERSION = "1.0.0" + +LOGO_ART = [ + " ███████╗██╗ ██╗███████╗████████╗ █████╗ ████████╗███████╗", + " ██╔════╝╚██╗ ██╔╝██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██╔════╝", + " ███████╗ ╚████╔╝ ███████╗ ██║ ███████║ ██║ ███████╗", + " ╚════██║ ╚██╔╝ ╚════██║ ██║ ██╔══██║ ██║ ╚════██║", + " ███████║ ██║ ███████║ ██║ ██║ ██║ ██║ ███████║", + " ╚══════╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝", +] + +BOOT_LINES = [ + ("> SYSTATS v{ver}", 0.0), + ("> initializing system probes... OK", 0.3), + ("> scanning CPU cores... {cores} detected", 0.6), + ("> GPU subsystem... {gpu}", 0.9), + ("> network interfaces... ONLINE", 1.1), + ("> thermal sensors... {temps}", 1.3), + ("> process table... READY", 1.5), + ("> Electric Entropy Lab // SYSTATS", 1.8), +] + +import random as _random + + +def intro_splash(stdscr): + """Animated boot splash inspired by Spectre/Pulse.""" + curses.curs_set(0) + stdscr.nodelay(False) + stdscr.timeout(30) + init_colors() + + h, w = stdscr.getmaxyx() + if h < 15 or w < 60: + return # skip intro on tiny terminals + + # Gather system info for boot lines + cores = psutil.cpu_count() + gpu_str = "NVIDIA" if NVIDIA_AVAILABLE else ("AMD" if os.path.exists(AMD_GPU_PATH) else "NONE") + try: + temps_count = sum(len(v) for v in psutil.sensors_temperatures().values()) + temps_str = f"{temps_count} sensors" + except Exception: + temps_str = "N/A" + + glitch_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#$%&*!?<>/\\|{}[]~^" + + # Phase 1: Boot lines + boot_start = time.time() + shown_lines = [] + + for line_tpl, delay in BOOT_LINES: + line = line_tpl.format(ver=VERSION, cores=cores, gpu=gpu_str, temps=temps_str) + target_time = boot_start + delay + while time.time() < target_time: + stdscr.getch() # drain input + time.sleep(0.02) + + shown_lines.append(line) + stdscr.erase() + start_y = (h - len(BOOT_LINES) - len(LOGO_ART) - 4) // 2 + for i, sl in enumerate(shown_lines): + col = C_LOW if "OK" in sl or "READY" in sl or "ONLINE" in sl or "detected" in sl else C_DIM + if "Electric Entropy" in sl: + col = C_ACCENT + safe_addstr(stdscr, start_y + i, (w - len(sl)) // 2, sl, + curses.color_pair(col)) + stdscr.refresh() + + time.sleep(0.3) + + # Phase 2: Decrypt logo animation + logo_start_y = (h - len(LOGO_ART)) // 2 + # Find max logo width + max_logo_w = max(len(l) for l in LOGO_ART) + + # Initialize with random chars for non-space positions + logo_state = [] + for line in LOGO_ART: + row = [] + for ch in line: + if ch == ' ' or ch == '\u2500': + row.append(ch) + else: + row.append(_random.choice(glitch_chars)) + logo_state.append(row) + + # Decrypt columns left to right + total_cols = max_logo_w + decrypt_steps = 20 # frames for full decrypt + chars_per_step = max(1, total_cols // decrypt_steps) + + revealed = [set() for _ in LOGO_ART] + + for step in range(decrypt_steps + 5): + stdscr.erase() + + # Reveal columns up to this step + reveal_up_to = min(step * chars_per_step, total_cols) + + for row_idx, line in enumerate(LOGO_ART): + lx = (w - max_logo_w) // 2 + for col_idx, ch in enumerate(line): + if col_idx < reveal_up_to: + revealed[row_idx].add(col_idx) + + display = [] + for col_idx in range(len(line)): + if col_idx in revealed[row_idx]: + display.append(line[col_idx]) + elif line[col_idx] == ' ': + display.append(' ') + else: + display.append(_random.choice(glitch_chars)) + + text = "".join(display) + # Color: revealed chars in cyan, glitch in dim + for col_idx, ch in enumerate(text): + if col_idx >= w - lx - 1: + break + if ch == ' ': + continue + if col_idx in revealed[row_idx]: + attr = curses.color_pair(C_TITLE) | curses.A_BOLD + else: + attr = curses.color_pair(C_DIM) | curses.A_DIM + try: + stdscr.addch(logo_start_y + row_idx, lx + col_idx, ch, attr) + except curses.error: + pass + + # Version + brand below logo + if step > decrypt_steps - 3: + ver_str = f"v{VERSION} // Electric Entropy Lab" + safe_addstr(stdscr, logo_start_y + len(LOGO_ART) + 1, (w - len(ver_str)) // 2, + ver_str, curses.color_pair(C_ACCENT) | curses.A_BOLD) + + stdscr.refresh() + stdscr.getch() # drain + time.sleep(0.05) + + time.sleep(0.5) + + # Phase 3: Flash and clear + stdscr.erase() + stdscr.refresh() + time.sleep(0.1) + + # ─── Main ─────────────────────────────────────────────────────────── +show_intro = True + + def main(stdscr): + if show_intro: + intro_splash(stdscr) + curses.curs_set(0) stdscr.nodelay(True) stdscr.timeout(int(REFRESH_INTERVAL * 1000)) @@ -1430,6 +1587,8 @@ if __name__ == "__main__": help=f"UI language: {lang_help}") parser.add_argument("--reset-lang", action="store_true", help="Reset saved language preference and ask again") + parser.add_argument("--no-intro", action="store_true", + help="Skip the boot intro animation") args = parser.parse_args() if args.reset_lang: @@ -1458,6 +1617,9 @@ if __name__ == "__main__": save_lang(lang) current_lang = lang + if args.no_intro: + show_intro = False + try: curses.wrapper(main) except KeyboardInterrupt: