From aae1e2c73a1506fb2feb68f30abdf170d8cda40d Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Sun, 12 Apr 2026 15:55:18 +0200 Subject: [PATCH] feat(live): v1.6.3 Plymouth 3D theme + kiosk fix Plymouth: - New secubox-3d theme with nested cubes + triple lemniscate - 3 cubes (outer/middle/inner) with desync rotation - AUTH/MIND/MESH colored lemniscates with glowing heads - SecuBox color palette integration Kiosk: - Fix session script: use --start-fullscreen (not --kiosk) - Allows Ctrl+Alt+Fn VT switching - Clean exec chromium (no background process issues) - Consistent session between build script and launcher Build: - Version bump to 1.6.3 - Plymouth theme set to secubox-3d Co-Authored-By: Claude Opus 4.5 --- image/build-live-usb.sh | 165 ++++-- image/plymouth/secubox-3d/progress-bg.png | Bin 0 -> 182 bytes image/plymouth/secubox-3d/progress-fg.png | Bin 0 -> 260 bytes image/plymouth/secubox-3d/secubox-3d.plymouth | 8 + image/plymouth/secubox-3d/secubox-3d.script | 429 +++++++++++++++ image/plymouth/secubox-3ds/cube-corner.png | Bin 0 -> 204 bytes image/plymouth/secubox-3ds/cube-edge.png | Bin 0 -> 162 bytes image/plymouth/secubox-3ds/divider.png | Bin 0 -> 176 bytes image/plymouth/secubox-3ds/lemniscate-dot.png | Bin 0 -> 210 bytes image/plymouth/secubox-3ds/progress-bg.png | Bin 0 -> 181 bytes image/plymouth/secubox-3ds/progress-fg.png | Bin 0 -> 253 bytes .../plymouth/secubox-3ds/secubox-3ds.plymouth | 8 + image/plymouth/secubox-3ds/secubox-3ds.script | 506 ++++++++++++++++++ .../secubox-cube/progress-bg-green.bak | Bin 0 -> 306 bytes image/plymouth/secubox-cube/progress-bg.png | Bin 306 -> 167 bytes .../secubox-cube/progress-fg-green.bak | Bin 0 -> 166 bytes image/plymouth/secubox-cube/progress-fg.png | Bin 166 -> 166 bytes .../plymouth/secubox-cube/secubox-cube.script | 292 +++++++--- image/sbin/secubox-kiosk-launcher | 22 +- 19 files changed, 1286 insertions(+), 144 deletions(-) create mode 100644 image/plymouth/secubox-3d/progress-bg.png create mode 100644 image/plymouth/secubox-3d/progress-fg.png create mode 100644 image/plymouth/secubox-3d/secubox-3d.plymouth create mode 100644 image/plymouth/secubox-3d/secubox-3d.script create mode 100644 image/plymouth/secubox-3ds/cube-corner.png create mode 100644 image/plymouth/secubox-3ds/cube-edge.png create mode 100644 image/plymouth/secubox-3ds/divider.png create mode 100644 image/plymouth/secubox-3ds/lemniscate-dot.png create mode 100644 image/plymouth/secubox-3ds/progress-bg.png create mode 100644 image/plymouth/secubox-3ds/progress-fg.png create mode 100644 image/plymouth/secubox-3ds/secubox-3ds.plymouth create mode 100644 image/plymouth/secubox-3ds/secubox-3ds.script create mode 100644 image/plymouth/secubox-cube/progress-bg-green.bak create mode 100644 image/plymouth/secubox-cube/progress-fg-green.bak diff --git a/image/build-live-usb.sh b/image/build-live-usb.sh index 3e957c30..051500df 100755 --- a/image/build-live-usb.sh +++ b/image/build-live-usb.sh @@ -14,7 +14,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" REPO_DIR="$(dirname "$SCRIPT_DIR")" # ── Version & Build Info ────────────────────────────────────────── -SECUBOX_VERSION="1.6.1" +SECUBOX_VERSION="1.6.3" BUILD_TIMESTAMP=$(date '+%Y-%m-%d %H:%M') BUILD_DATE=$(date '+%Y%m%d') @@ -260,11 +260,12 @@ DefaultTimeoutStartSec=30s DefaultTimeoutStopSec=30s EOF -# Disable console spam +# Disable console spam + enable SysRq for emergency recovery cat > "${ROOTFS}/etc/sysctl.d/99-secubox.conf" </dev/null || chroot "${ROOTFS}" systemctl disable systemd-networkd-wait-online.service 2>/dev/null || true chroot "${ROOTFS}" systemctl mask systemd-networkd-wait-online.service 2>/dev/null || true -# ── Plymouth Boot Splash Theme (SecuBox Cube) ────────────────────── -log "Installing Plymouth SecuBox-Cube boot splash..." +# ── Plymouth Boot Splash Theme (SecuBox 3DS) ────────────────────── +log "Installing Plymouth SecuBox-3DS boot splash..." -# Create SecuBox-Cube Plymouth theme directory -PLYMOUTH_DIR="${ROOTFS}/usr/share/plymouth/themes/secubox-cube" +# Create SecuBox-3DS Plymouth theme directory (primary theme) +PLYMOUTH_DIR="${ROOTFS}/usr/share/plymouth/themes/secubox-3d" mkdir -p "${PLYMOUTH_DIR}" -# Copy theme assets from source +# Copy 3DS theme assets from source +DS_SRC="${SCRIPT_DIR}/plymouth/secubox-3d" +if [[ -d "${DS_SRC}" ]]; then + cp "${DS_SRC}/secubox-3d.plymouth" "${PLYMOUTH_DIR}/" + cp "${DS_SRC}/secubox-3d.script" "${PLYMOUTH_DIR}/" + cp "${DS_SRC}"/*.png "${PLYMOUTH_DIR}/" 2>/dev/null || true + log " Copied 3DS theme assets from ${DS_SRC}" +fi + +# Also install legacy cube theme as fallback +CUBE_DIR="${ROOTFS}/usr/share/plymouth/themes/secubox-cube" +mkdir -p "${CUBE_DIR}" CUBE_SRC="${SCRIPT_DIR}/plymouth/secubox-cube" if [[ -d "${CUBE_SRC}" ]]; then - cp "${CUBE_SRC}/secubox-cube.plymouth" "${PLYMOUTH_DIR}/" - cp "${CUBE_SRC}/secubox-cube.script" "${PLYMOUTH_DIR}/" - cp "${CUBE_SRC}/logo.png" "${PLYMOUTH_DIR}/" - cp "${CUBE_SRC}/scanlines.png" "${PLYMOUTH_DIR}/" - cp "${CUBE_SRC}/progress-bg.png" "${PLYMOUTH_DIR}/" - cp "${CUBE_SRC}/progress-fg.png" "${PLYMOUTH_DIR}/" - cp "${CUBE_SRC}"/icon-*.png "${PLYMOUTH_DIR}/" + cp "${CUBE_SRC}/secubox-cube.plymouth" "${CUBE_DIR}/" + cp "${CUBE_SRC}/secubox-cube.script" "${CUBE_DIR}/" + cp "${CUBE_SRC}/logo.png" "${CUBE_DIR}/" + cp "${CUBE_SRC}/scanlines.png" "${CUBE_DIR}/" + cp "${CUBE_SRC}/progress-bg.png" "${CUBE_DIR}/" + cp "${CUBE_SRC}/progress-fg.png" "${CUBE_DIR}/" + cp "${CUBE_SRC}"/icon-*.png "${CUBE_DIR}/" log " Copied cube theme assets from ${CUBE_SRC}" else warn "Cube theme source not found at ${CUBE_SRC}, creating minimal theme..." @@ -813,19 +825,19 @@ Plymouth.SetMessageFunction(message_callback); PLYSCRIPT fi -# Set SecuBox-Cube theme as default +# Set SecuBox-3DS theme as default mkdir -p "${ROOTFS}/etc/plymouth" cat > "${ROOTFS}/etc/plymouth/plymouthd.conf" </dev/null || true +chroot "${ROOTFS}" plymouth-set-default-theme secubox-3d 2>/dev/null || true -ok "Plymouth SecuBox-Cube theme installed" +ok "Plymouth SecuBox-3DS theme installed" ok "Base configuration complete" @@ -1242,7 +1254,8 @@ lapi_key = "" interface = "wg0" listen_port = 51820 SECUBOXCONF -chmod 640 "${ROOTFS}/etc/secubox/secubox.conf" +chmod 644 "${ROOTFS}/etc/secubox/secubox.conf" +chroot "${ROOTFS}" chown root:secubox /etc/secubox/secubox.conf 2>/dev/null || true log "Created default secubox.conf (admin/secubox)" # Create users.json for portal authentication @@ -1264,7 +1277,8 @@ cat > "${ROOTFS}/etc/secubox/users.json" </dev/null || true log "Created users.json (admin/secubox, root/secubox)" # ── Restore real systemctl ───────────────────────────────────────── @@ -1626,27 +1640,33 @@ XCONF mkdir -p "${ROOTFS}/home/secubox-kiosk/.config" cat > "${ROOTFS}/home/secubox-kiosk/.xsession" <<'XSESSION' #!/bin/bash -# SecuBox Kiosk X Session - Minimal version -exec 2>&1 | logger -t secubox-kiosk & +# SecuBox Kiosk X Session v1.6.3 +export DISPLAY=${DISPLAY:-:0} -echo "Starting kiosk session..." +logger -t secubox-kiosk "Starting kiosk session..." # Basic X settings (ignore errors) -xset s off 2>/dev/null -xset -dpms 2>/dev/null +xset s off 2>/dev/null || true +xset -dpms 2>/dev/null || true +xset s noblank 2>/dev/null || true -# URL to display - use localhost for universal compatibility (works without network) +# URL to display - use localhost for universal compatibility URL="https://localhost/" -# Try Chromium with minimal flags +# Chromium with VT-switch-friendly flags (--start-fullscreen, not --kiosk) +# exec replaces shell with chromium - on exit, X session ends exec chromium \ - --kiosk \ + --start-fullscreen \ --no-first-run \ --no-sandbox \ --disable-gpu \ + --disable-pinch \ + --noerrdialogs \ + --disable-translate \ --ignore-certificate-errors \ + --disable-features=TranslateUI \ --window-position=0,0 \ - "$URL" || exec xterm -fullscreen -e "echo 'Chromium failed'; sleep 999" + "$URL" XSESSION chmod +x "${ROOTFS}/home/secubox-kiosk/.xsession" # Create symlink for xinit compatibility @@ -1726,9 +1746,10 @@ XCONF xinit /bin/bash -c " xset s off 2>/dev/null xset -dpms 2>/dev/null - exec chromium --kiosk --no-first-run --no-sandbox --disable-gpu \ + exec chromium --start-fullscreen --no-first-run --no-sandbox --disable-gpu \ + --disable-pinch --noerrdialogs --disable-translate \ --ignore-certificate-errors --window-position=0,0 '$URL' - " -- :0 vt7 -nolisten tcp 2>/dev/null & + " -- :0 vt7 -nolisten tcp -keeptty 2>/dev/null & sleep 3 chvt 7 2>/dev/null ) & @@ -2140,48 +2161,46 @@ rm -rf "${ROOTFS}/tmp"/* # ── CRT-Style Boot Banner with Colors and Emojis ────────────────────────────── log "Creating colorful boot banners..." -# Pre-login banner (/etc/issue) - shown before login prompt -cat > "${ROOTFS}/etc/issue" <:9443[0m -[38;5;250m 📡 SSH: [38;5;45mport 22[0m +\e[38;5;250m 🔐 Default: \e[38;5;214mroot\e[38;5;250m / \e[38;5;214msecubox\e[0m +\e[38;5;250m 🌐 Web UI: \e[38;5;45mhttps://:9443\e[0m +\e[38;5;250m 📡 SSH: \e[38;5;45mport 22\e[0m -[38;5;242m─────────────────────────────────────────────────────────────[0m +\e[38;5;242m─────────────────────────────────────────────────────────────\e[0m -ISSUE +" > "${ROOTFS}/etc/issue" -# Post-login MOTD with dynamic info (/etc/motd) -cat > "${ROOTFS}/etc/motd" <:9443[0m -[38;5;250m 🔐 Credentials: [38;5;214mroot[38;5;250m / [38;5;214msecubox[0m -[38;5;250m 📖 Docs: [38;5;45mhttps://secubox.in/docs[0m +\e[38;5;250m 🌐 Web UI: \e[38;5;45mhttps://:9443\e[0m +\e[38;5;250m 🔐 Credentials: \e[38;5;214mroot\e[38;5;250m / \e[38;5;214msecubox\e[0m +\e[38;5;250m 📖 Docs: \e[38;5;45mhttps://secubox.in/docs\e[0m -[38;5;242m Type [38;5;82msecubox-status[38;5;242m for system overview[0m +\e[38;5;242m Type \e[38;5;82msecubox-status\e[38;5;242m for system overview\e[0m -MOTD +" > "${ROOTFS}/etc/motd" # Dynamic status script for interactive use cat > "${ROOTFS}/usr/bin/secubox-status" <<'STATUS_SCRIPT' @@ -2261,6 +2280,34 @@ echo "" STATUS_SCRIPT chmod +x "${ROOTFS}/usr/bin/secubox-status" +# Password reset script for TTY recovery +cat > "${ROOTFS}/usr/bin/secubox-passwd" <<'PASSWD_SCRIPT' +#!/bin/bash +# SecuBox Password Reset +set -e +USERS_FILE="/etc/secubox/users.json" +CONF_FILE="/etc/secubox/secubox.conf" +echo "SecuBox Password Reset" +[[ $EUID -ne 0 ]] && echo "Error: Run as root" && exit 1 +read -sp "New password for admin: " NEW_PASS && echo +read -sp "Confirm password: " CONFIRM && echo +[[ "$NEW_PASS" != "$CONFIRM" ]] && echo "Passwords don't match" && exit 1 +[[ ${#NEW_PASS} -lt 4 ]] && echo "Password too short" && exit 1 +NEW_HASH=$(echo -n "$NEW_PASS" | sha256sum | cut -d' ' -f1) +if [[ -f "$USERS_FILE" ]]; then + sed -i "s/\"password_hash\": \"[^\"]*\"/\"password_hash\": \"${NEW_HASH}\"/g" "$USERS_FILE" + echo "Updated users.json" +fi +if [[ -f "$CONF_FILE" ]]; then + sed -i "s/^password = .*/password = \"${NEW_PASS}\"/" "$CONF_FILE" + echo "Updated secubox.conf" +fi +systemctl restart secubox-portal secubox-hub 2>/dev/null || true +echo "Password reset complete!" +PASSWD_SCRIPT +chmod +x "${ROOTFS}/usr/bin/secubox-passwd" +ok "Password reset script installed (secubox-passwd)" + # Also add a boot-time banner display script cat > "${ROOTFS}/usr/sbin/secubox-boot-banner" <<'BOOT_BANNER' #!/bin/bash diff --git a/image/plymouth/secubox-3d/progress-bg.png b/image/plymouth/secubox-3d/progress-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..42c389b1ee1b3fd3264241d5cb3f6a550d1c05b1 GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0y~yU}OQZ1(=wDWN+BZ1wcw6*(1o8fuTx`fuW&=f#DZW zsNn?zL#Y7+!>a@a2CEqi4B`cIb_Lo1B{&0oLR`6|1f;AK{{R19y5m+WP>?an+uemJ zjk_iV$YC$>^mS!_#lpj@#MS+1dmvCq#?!?y#Nu>v!UBnowjeeqH(v?U#49YbW;hr! ZFig(WT4DHs^%77WgQu&X%Q~loCIGr+F4q76 literal 0 HcmV?d00001 diff --git a/image/plymouth/secubox-3d/progress-fg.png b/image/plymouth/secubox-3d/progress-fg.png new file mode 100644 index 0000000000000000000000000000000000000000..d0b76f98c7c2f2749a16c2d759eca2e01e63796d GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5cm$Y$WRR)GULd8A>=ES4z)+>ez|hdb!0-zw z)bN6Vq11qZ;Z*_ygVhWM2JwP9y8>;15^PD{?k@kqfHUIz9iRw%iKnkC`zsb6UL~&X zN81B|LRFqFjv*Dd-rm~Cd)R=7#ew~SmFHsLH;IRjJ~hpbe{>K>}g(qGe#XGCMfmGgMurlR zR92P?K{1x4Kp#aiGMapiXMD-PaI13@6H~@Zc7|1YrwVddoPe%i@O1TaS?83{1OP#* BSS$bl literal 0 HcmV?d00001 diff --git a/image/plymouth/secubox-3d/secubox-3d.plymouth b/image/plymouth/secubox-3d/secubox-3d.plymouth new file mode 100644 index 00000000..8d7d8226 --- /dev/null +++ b/image/plymouth/secubox-3d/secubox-3d.plymouth @@ -0,0 +1,8 @@ +[Plymouth Theme] +Name=SecuBox 3D +Description=Triple lemniscate + nested cubes boot splash +ModuleName=script + +[script] +ImageDir=/usr/share/plymouth/themes/secubox-3d +ScriptFile=/usr/share/plymouth/themes/secubox-3d/secubox-3d.script diff --git a/image/plymouth/secubox-3d/secubox-3d.script b/image/plymouth/secubox-3d/secubox-3d.script new file mode 100644 index 00000000..ee3e940d --- /dev/null +++ b/image/plymouth/secubox-3d/secubox-3d.script @@ -0,0 +1,429 @@ +/* SecuBox 3D - Plymouth Theme Script + * Triple Lemniscate + Nested Cubes (gigognes) + * Matching secubox_v5_stereo.html aesthetic + * CyberMind - https://cybermind.fr + */ + +/* ═══════════════════════════════════════════════════════════════ + * SecuBox Color Palette (from FD[] face definitions) + * ═══════════════════════════════════════════════════════════════ */ +/* AUTH #FF6910 */ col_auth_r = 1.000; col_auth_g = 0.412; col_auth_b = 0.063; +/* WALL #FFB300 */ col_wall_r = 1.000; col_wall_g = 0.702; col_wall_b = 0.000; +/* BOOT #FF3333 */ col_boot_r = 1.000; col_boot_g = 0.200; col_boot_b = 0.200; +/* MIND #9B7EFF */ col_mind_r = 0.608; col_mind_g = 0.494; col_mind_b = 1.000; +/* ROOT #33FF33 */ col_root_r = 0.200; col_root_g = 1.000; col_root_b = 0.200; +/* MESH #3AB4FF */ col_mesh_r = 0.227; col_mesh_g = 0.706; col_mesh_b = 1.000; + +/* ═══════════════════════════════════════════════════════════════ + * Screen Setup - Dark cyber background (#07080f) + * ═══════════════════════════════════════════════════════════════ */ +Window.SetBackgroundTopColor(0.027, 0.031, 0.059); +Window.SetBackgroundBottomColor(0.012, 0.016, 0.035); + +screen_width = Window.GetWidth(); +screen_height = Window.GetHeight(); +center_x = screen_width / 2; +center_y = screen_height / 2; + +/* ═══════════════════════════════════════════════════════════════ + * Load Assets + * ═══════════════════════════════════════════════════════════════ */ +progress_bg = Image("progress-bg.png"); +progress_fg = Image("progress-fg.png"); + +/* ═══════════════════════════════════════════════════════════════ + * 3 Nested Cubes Configuration (gigognes) + * Outer=0, Middle=1, Inner=2 + * ═══════════════════════════════════════════════════════════════ */ + +/* Cube sizes (matching web: 256/2, 128/2, 64/2 scaled for plymouth) */ +cube_size[0] = 110; /* Outer - largest */ +cube_size[1] = 70; /* Middle */ +cube_size[2] = 40; /* Inner - smallest */ + +/* Desynchronized rotation speeds (BASE_SPD from web) */ +/* Outer: slowest, most majestic */ +spd_x[0] = 0.004; spd_y[0] = 0.006; spd_z[0] = 0.003; +/* Middle: medium */ +spd_x[1] = 0.007; spd_y[1] = 0.005; spd_z[1] = 0.006; +/* Inner: fastest, most dynamic */ +spd_x[2] = 0.012; spd_y[2] = 0.010; spd_z[2] = 0.008; + +/* Rotation angles (offset for visual interest at start) */ +rot_x[0] = 0.0; rot_y[0] = 0.0; rot_z[0] = 0.0; +rot_x[1] = 0.8; rot_y[1] = 0.4; rot_z[1] = 0.2; +rot_x[2] = 1.6; rot_y[2] = 1.2; rot_z[2] = 0.6; + +/* Cube edge colors (gradient from outer to inner) */ +/* Outer: dim green-cyan */ +cube_r[0] = 0.15; cube_g[0] = 0.45; cube_b[0] = 0.35; +/* Middle: brighter cyan */ +cube_r[1] = 0.20; cube_g[1] = 0.60; cube_b[1] = 0.50; +/* Inner: bright SecuBox green */ +cube_r[2] = 0.25; cube_g[2] = 0.85; cube_b[2] = 0.45; + +/* 8 vertices per cube × 3 cubes = 24 vertex sprites */ +for (c = 0; c < 3; c++) { + for (v = 0; v < 8; v++) { + idx = c * 8 + v; + cube_verts[idx] = Sprite(); + cube_verts[idx].SetZ(10 + c * 3); + } +} + +/* 12 edges per cube × 3 cubes = 36 edge midpoint sprites */ +for (c = 0; c < 3; c++) { + for (e = 0; e < 12; e++) { + idx = c * 12 + e; + cube_edges[idx] = Sprite(); + cube_edges[idx].SetZ(9 + c * 3); + } +} + +/* ═══════════════════════════════════════════════════════════════ + * Triple Lemniscate Configuration + * 3 branches: AUTH (orange), MIND (purple), MESH (blue) + * ═══════════════════════════════════════════════════════════════ */ +lemniscate_scale = 95; + +/* Branch colors */ +lem_r[0] = col_auth_r; lem_g[0] = col_auth_g; lem_b[0] = col_auth_b; /* AUTH orange */ +lem_r[1] = col_mind_r; lem_g[1] = col_mind_g; lem_b[1] = col_mind_b; /* MIND purple */ +lem_r[2] = col_mesh_r; lem_g[2] = col_mesh_g; lem_b[2] = col_mesh_b; /* MESH blue */ + +/* Head speeds (desynchronized) */ +lem_speed[0] = 0.028; +lem_speed[1] = 0.022; +lem_speed[2] = 0.019; + +/* Head positions (start offset for visual variety) */ +lem_pos[0] = 0.0; +lem_pos[1] = 2.094; /* 2π/3 */ +lem_pos[2] = 4.188; /* 4π/3 */ + +/* Trail dots per branch */ +trail_len = 15; + +/* Lemniscate sprites: 3 branches × (trail_len + 1 head) */ +for (b = 0; b < 3; b++) { + for (d = 0; d < trail_len; d++) { + idx = b * trail_len + d; + lem_trail[idx] = Sprite(); + lem_trail[idx].SetZ(5); + } + lem_head[b] = Sprite(); + lem_head[b].SetZ(8); +} + +/* ═══════════════════════════════════════════════════════════════ + * Progress Bar + * ═══════════════════════════════════════════════════════════════ */ +progress_bg_sprite = Sprite(); +progress_fg_sprite = Sprite(); +if (progress_bg) { + progress_bg_sprite.SetImage(progress_bg); +} +progress_bg_sprite.SetX(center_x - 130); +progress_bg_sprite.SetY(center_y + 170); +progress_bg_sprite.SetZ(50); + +if (progress_fg) { + progress_fg_sprite.SetImage(progress_fg); +} +progress_fg_sprite.SetX(center_x - 128); +progress_fg_sprite.SetY(center_y + 172); +progress_fg_sprite.SetZ(51); + +/* Status message */ +message_sprite = Sprite(); +message_sprite.SetZ(52); + +/* ═══════════════════════════════════════════════════════════════ + * Animation State + * ═══════════════════════════════════════════════════════════════ */ +frame = 0; +boot_progress = 0; + +/* ═══════════════════════════════════════════════════════════════ + * Unit Cube Vertices (±1, ±1, ±1) + * ═══════════════════════════════════════════════════════════════ */ +uv_x[0] = -1; uv_y[0] = -1; uv_z[0] = -1; +uv_x[1] = 1; uv_y[1] = -1; uv_z[1] = -1; +uv_x[2] = 1; uv_y[2] = 1; uv_z[2] = -1; +uv_x[3] = -1; uv_y[3] = 1; uv_z[3] = -1; +uv_x[4] = -1; uv_y[4] = -1; uv_z[4] = 1; +uv_x[5] = 1; uv_y[5] = -1; uv_z[5] = 1; +uv_x[6] = 1; uv_y[6] = 1; uv_z[6] = 1; +uv_x[7] = -1; uv_y[7] = 1; uv_z[7] = 1; + +/* Edge definitions (vertex pairs) */ +edge_a[0]=0; edge_b[0]=1; edge_a[1]=1; edge_b[1]=2; edge_a[2]=2; edge_b[2]=3; edge_a[3]=3; edge_b[3]=0; +edge_a[4]=4; edge_b[4]=5; edge_a[5]=5; edge_b[5]=6; edge_a[6]=6; edge_b[6]=7; edge_a[7]=7; edge_b[7]=4; +edge_a[8]=0; edge_b[8]=4; edge_a[9]=1; edge_b[9]=5; edge_a[10]=2; edge_b[10]=6; edge_a[11]=3; edge_b[11]=7; + +/* ═══════════════════════════════════════════════════════════════ + * 3D Rotation Function + * ═══════════════════════════════════════════════════════════════ */ +fun rotate3d(px, py, pz, ax, ay, az) { + /* Rotate X */ + cx = Math.Cos(ax); sx = Math.Sin(ax); + y1 = py * cx - pz * sx; + z1 = py * sx + pz * cx; + + /* Rotate Y */ + cy = Math.Cos(ay); sy = Math.Sin(ay); + x2 = px * cy + z1 * sy; + z2 = -px * sy + z1 * cy; + + /* Rotate Z */ + cz = Math.Cos(az); sz = Math.Sin(az); + x3 = x2 * cz - y1 * sz; + y3 = x2 * sz + y1 * cz; + + result[0] = x3; + result[1] = y3; + result[2] = z2; + return result; +} + +/* ═══════════════════════════════════════════════════════════════ + * Lemniscate Parametric (Bernoulli) + * x = a * cos(t) / (1 + sin²(t)) + * y = a * sin(t) * cos(t) / (1 + sin²(t)) + * ═══════════════════════════════════════════════════════════════ */ +fun lem_x(t, scale) { + st = Math.Sin(t); + ct = Math.Cos(t); + d = 1 + st * st; + return scale * ct / d; +} + +fun lem_y(t, scale) { + st = Math.Sin(t); + ct = Math.Cos(t); + d = 1 + st * st; + return scale * st * ct / d; +} + +/* ═══════════════════════════════════════════════════════════════ + * Draw Single Cube + * ═══════════════════════════════════════════════════════════════ */ +fun draw_cube(cube_idx) { + ax = global.rot_x[cube_idx]; + ay = global.rot_y[cube_idx]; + az = global.rot_z[cube_idx]; + size = global.cube_size[cube_idx] / 2; + + cr = global.cube_r[cube_idx]; + cg = global.cube_g[cube_idx]; + cb = global.cube_b[cube_idx]; + + /* Compute projected vertices */ + for (v = 0; v < 8; v++) { + px = global.uv_x[v] * size; + py = global.uv_y[v] * size; + pz = global.uv_z[v] * size; + + rot = rotate3d(px, py, pz, ax, ay, az); + + /* Store projected coords */ + proj_x[v] = global.center_x + rot[0]; + proj_y[v] = global.center_y + rot[1]; + proj_z[v] = rot[2]; + + /* Depth-based brightness */ + depth = (rot[2] + size) / (size * 2); + bright = 0.4 + depth * 0.6; + + /* Draw vertex dot */ + idx = cube_idx * 8 + v; + dot_img = Image.Text("●", cr * bright, cg * bright, cb * bright, 1); + global.cube_verts[idx].SetImage(dot_img); + global.cube_verts[idx].SetX(proj_x[v] - 4); + global.cube_verts[idx].SetY(proj_y[v] - 4); + global.cube_verts[idx].SetOpacity(0.6 + depth * 0.4); + } + + /* Draw edges (midpoints) */ + for (e = 0; e < 12; e++) { + va = global.edge_a[e]; + vb = global.edge_b[e]; + + /* Edge midpoint */ + mx = (proj_x[va] + proj_x[vb]) / 2; + my = (proj_y[va] + proj_y[vb]) / 2; + mz = (proj_z[va] + proj_z[vb]) / 2; + + depth = (mz + size) / (size * 2); + bright = 0.3 + depth * 0.5; + + idx = cube_idx * 12 + e; + edge_img = Image.Text("·", cr * bright, cg * bright, cb * bright, 1); + global.cube_edges[idx].SetImage(edge_img); + global.cube_edges[idx].SetX(mx - 2); + global.cube_edges[idx].SetY(my - 2); + global.cube_edges[idx].SetOpacity(0.4 + depth * 0.3); + } +} + +/* ═══════════════════════════════════════════════════════════════ + * Draw Triple Lemniscate + * ═══════════════════════════════════════════════════════════════ */ +fun draw_lemniscates() { + /* Gentle twist animation */ + twist = Math.Sin(global.frame * 0.008) * 0.3; + + for (b = 0; b < 3; b++) { + /* Update head position */ + global.lem_pos[b] += global.lem_speed[b]; + if (global.lem_pos[b] > 6.28318) { + global.lem_pos[b] -= 6.28318; + } + + lr = global.lem_r[b]; + lg = global.lem_g[b]; + lb = global.lem_b[b]; + + /* Draw trail */ + for (d = 0; d < global.trail_len; d++) { + t = global.lem_pos[b] - d * 0.25; + + /* 3D lemniscate with twist */ + lx = lem_x(t, global.lemniscate_scale); + ly = lem_y(t, global.lemniscate_scale); + lz = Math.Sin(t * 2 + twist) * 15; /* Z oscillation */ + + /* Simple rotation for 3D effect */ + rot = rotate3d(lx, ly, lz, twist * 0.5, global.frame * 0.003, 0); + + sx = global.center_x + rot[0]; + sy = global.center_y + rot[1]; + + /* Fade trail */ + fade = 1.0 - (d / global.trail_len); + + idx = b * global.trail_len + d; + dot_img = Image.Text("•", lr * fade, lg * fade, lb * fade, 1); + global.lem_trail[idx].SetImage(dot_img); + global.lem_trail[idx].SetX(sx - 3); + global.lem_trail[idx].SetY(sy - 3); + global.lem_trail[idx].SetOpacity(fade * 0.7); + } + + /* Draw glowing head */ + ht = global.lem_pos[b]; + hx = lem_x(ht, global.lemniscate_scale); + hy = lem_y(ht, global.lemniscate_scale); + hz = Math.Sin(ht * 2 + twist) * 15; + + hrot = rotate3d(hx, hy, hz, twist * 0.5, global.frame * 0.003, 0); + + hsx = global.center_x + hrot[0]; + hsy = global.center_y + hrot[1]; + + /* Pulsing glow */ + pulse = 0.85 + Math.Sin(global.frame * 0.15 + b) * 0.15; + + head_img = Image.Text("◉", lr * pulse, lg * pulse, lb * pulse, 1); + global.lem_head[b].SetImage(head_img); + global.lem_head[b].SetX(hsx - 5); + global.lem_head[b].SetY(hsy - 5); + global.lem_head[b].SetOpacity(1.0); + } +} + +/* ═══════════════════════════════════════════════════════════════ + * Main Animation Loop + * ═══════════════════════════════════════════════════════════════ */ +fun refresh_callback() { + global.frame++; + + /* Update cube rotations (desynchronized) */ + for (c = 0; c < 3; c++) { + global.rot_x[c] += global.spd_x[c]; + global.rot_y[c] += global.spd_y[c]; + global.rot_z[c] += global.spd_z[c]; + + if (global.rot_x[c] > 6.28318) global.rot_x[c] -= 6.28318; + if (global.rot_y[c] > 6.28318) global.rot_y[c] -= 6.28318; + if (global.rot_z[c] > 6.28318) global.rot_z[c] -= 6.28318; + + draw_cube(c); + } + + /* Draw triple lemniscate */ + draw_lemniscates(); +} + +Plymouth.SetRefreshFunction(refresh_callback); + +/* ═══════════════════════════════════════════════════════════════ + * Plymouth Callbacks + * ═══════════════════════════════════════════════════════════════ */ + +fun boot_progress_callback(duration, progress_val) { + global.boot_progress = progress_val; + + if (progress_fg) { + bar_width = Math.Int(progress_val * 256); + if (bar_width > 0) { + scaled = progress_fg.Scale(bar_width, 12); + progress_fg_sprite.SetImage(scaled); + } + } +} + +Plymouth.SetBootProgressFunction(boot_progress_callback); + +fun message_callback(text) { + /* SecuBox green text */ + msg_img = Image.Text(text, 0.2, 0.85, 0.4, "Mono 10"); + message_sprite.SetImage(msg_img); + message_sprite.SetX(center_x - msg_img.GetWidth() / 2); + message_sprite.SetY(center_y + 195); +} + +Plymouth.SetMessageFunction(message_callback); + +fun display_normal_callback() { + /* Normal boot display */ +} + +fun display_password_callback(prompt, bullets) { + /* LUKS password prompt */ + prompt_img = Image.Text(prompt, col_mesh_r, col_mesh_g, col_mesh_b, "Sans Bold 11"); + message_sprite.SetImage(prompt_img); + message_sprite.SetX(center_x - prompt_img.GetWidth() / 2); + message_sprite.SetY(center_y + 150); +} + +Plymouth.SetDisplayNormalFunction(display_normal_callback); +Plymouth.SetDisplayPasswordFunction(display_password_callback); + +fun quit_callback() { + /* Fade out */ + for (c = 0; c < 3; c++) { + for (v = 0; v < 8; v++) { + idx = c * 8 + v; + global.cube_verts[idx].SetOpacity(0); + } + for (e = 0; e < 12; e++) { + idx = c * 12 + e; + global.cube_edges[idx].SetOpacity(0); + } + } + + for (b = 0; b < 3; b++) { + for (d = 0; d < global.trail_len; d++) { + idx = b * global.trail_len + d; + global.lem_trail[idx].SetOpacity(0); + } + global.lem_head[b].SetOpacity(0); + } + + progress_bg_sprite.SetOpacity(0); + progress_fg_sprite.SetOpacity(0); + message_sprite.SetOpacity(0); +} + +Plymouth.SetQuitFunction(quit_callback); diff --git a/image/plymouth/secubox-3ds/cube-corner.png b/image/plymouth/secubox-3ds/cube-corner.png new file mode 100644 index 0000000000000000000000000000000000000000..db1df44b75dea1796692b884cb15341afd5ef0ca GIT binary patch literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^93afX3?$7I7w-U43dtTpz6=aiY77hwEes65fImjw9*GjQ}S zT(;30$Yo6Oc6VXv&$t-~a+F#;$g>*?Yc!f`!0!GS?hnURex mHJO!-EjgK4gIkA?NMQuI#T^c(~-5Ud>C4019z?x;Tb#Tu)AD0CG4O81)tI8Uk4ip00i_>zopr0KJMO Ag8%>k literal 0 HcmV?d00001 diff --git a/image/plymouth/secubox-3ds/divider.png b/image/plymouth/secubox-3ds/divider.png new file mode 100644 index 0000000000000000000000000000000000000000..ac6e02fb99c6eac7f8bdd580e2762f67b863af7b GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0y~yU{(OKS(uoCB=_mfZa_*Q*(1o8fuTx`fuW&=f#DZW zsNn?zL#Y7+!>a@a2CEqi4B`cIb_Lo1B{&0oLR`7{a+F#;$g=IP=XqH#VsL4viJr-e`0;KD->Qw9cGBd1K( So-OS_6%3xPelF{r5}E+ko++yU literal 0 HcmV?d00001 diff --git a/image/plymouth/secubox-3ds/lemniscate-dot.png b/image/plymouth/secubox-3ds/lemniscate-dot.png new file mode 100644 index 0000000000000000000000000000000000000000..8c215b931241f774163e07fe30845695de943ca8 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^93afX3?$7I7w-U43dtTpz6=aiY77hwEes65fIK|NYLkZ2$@}mjw9*GsrHp zTE9*n$Yo6Oc6VXv&$t-~a+F#;&0?CIhd!f`!0fq_|3nUT#c sIoX*_Ejd}4EiE}YnS)!0Z4xVkT@Lfgo$GQ7fyx;?UHx3vIVCg!04@qO2LJ#7 literal 0 HcmV?d00001 diff --git a/image/plymouth/secubox-3ds/progress-bg.png b/image/plymouth/secubox-3ds/progress-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..7a34499245d6d99165be093ec87977e2b264d6b5 GIT binary patch literal 181 zcmeAS@N?(olHy`uVBq!ia0vp^AAneZi5WWAJqKb6Mw<&;$TM^ep`V literal 0 HcmV?d00001 diff --git a/image/plymouth/secubox-3ds/progress-fg.png b/image/plymouth/secubox-3ds/progress-fg.png new file mode 100644 index 0000000000000000000000000000000000000000..b9c26f917e4e6dd64d76cfe1165994c69873e9e6 GIT binary patch literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^Z-AIbfC)(MOO`ns~eV&UPEXL>a+ zF#;%5?CIhdQgQ3;El1wN4m_?0!;HEn@GOlj(CxbQQc>ZbqA^F!rg=L1`ybn^f6eOP z@paza`(Gp&&WCQU`l@crcA!`@sbRzJ4&9`N8MAC}XEG@)uj*A|<5+cbZ3kmhmWZLl sl=Ykq8)jX7{oI66pt#;w1E|pcORM#yL$|ryfYvj3y85}Sb4q9e0G+W}vH$=8 literal 0 HcmV?d00001 diff --git a/image/plymouth/secubox-3ds/secubox-3ds.plymouth b/image/plymouth/secubox-3ds/secubox-3ds.plymouth new file mode 100644 index 00000000..f43b1884 --- /dev/null +++ b/image/plymouth/secubox-3ds/secubox-3ds.plymouth @@ -0,0 +1,8 @@ +[Plymouth Theme] +Name=SecuBox 3DS +Description=Nintendo 3DS dual-screen aesthetic with nested cubes and lemniscates +ModuleName=script + +[script] +ImageDir=/usr/share/plymouth/themes/secubox-3ds +ScriptFile=/usr/share/plymouth/themes/secubox-3ds/secubox-3ds.script diff --git a/image/plymouth/secubox-3ds/secubox-3ds.script b/image/plymouth/secubox-3ds/secubox-3ds.script new file mode 100644 index 00000000..f9951be7 --- /dev/null +++ b/image/plymouth/secubox-3ds/secubox-3ds.script @@ -0,0 +1,506 @@ +/* SecuBox 3DS - Plymouth Theme Script + * Nintendo 3DS dual-screen aesthetic + * Upper: 3 nested cubes + 2 lemniscates + * Lower: Kernel log + progress bar + * CyberMind - https://cybermind.fr + */ + +/* ═══════════════════════════════════════════════════════════════ + * 3DS Color Palette + * ═══════════════════════════════════════════════════════════════ */ +/* Deep blue gradient: #0033aa (dark) → #1a6fff (bright) */ +blue_dark_r = 0.000; blue_dark_g = 0.200; blue_dark_b = 0.667; /* #0033aa */ +blue_mid_r = 0.082; blue_mid_g = 0.333; blue_mid_b = 0.835; /* #1555d5 */ +blue_bright_r = 0.102; blue_bright_g = 0.435; blue_bright_b = 1.0; /* #1a6fff */ + +/* Log colors */ +log_blue_r = 0.4; log_blue_g = 0.6; log_blue_b = 1.0; /* info */ +log_green_r = 0.4; log_green_g = 1.0; log_green_b = 0.6; /* ok */ +log_amber_r = 1.0; log_amber_g = 0.8; log_amber_b = 0.3; /* warn */ + +/* ═══════════════════════════════════════════════════════════════ + * Screen Setup - Dual screen simulation + * ═══════════════════════════════════════════════════════════════ */ +Window.SetBackgroundTopColor(0.02, 0.02, 0.04); /* Near black */ +Window.SetBackgroundBottomColor(0.01, 0.01, 0.02); + +screen_width = Window.GetWidth(); +screen_height = Window.GetHeight(); + +/* 3DS aspect simulation - upper screen takes 55% height */ +upper_height = screen_height * 0.55; +lower_height = screen_height * 0.45; +divider_y = upper_height; + +/* Centers for each "screen" */ +upper_center_x = screen_width / 2; +upper_center_y = upper_height / 2; +lower_center_x = screen_width / 2; +lower_center_y = divider_y + (lower_height / 2); + +/* ═══════════════════════════════════════════════════════════════ + * Load Assets + * ═══════════════════════════════════════════════════════════════ */ +/* Cube wireframe edges - rendered as sprites */ +cube_edge = Image("cube-edge.png"); +cube_corner = Image("cube-corner.png"); +lemniscate_dot = Image("lemniscate-dot.png"); +divider_line = Image("divider.png"); +progress_bg = Image("progress-bg.png"); +progress_fg = Image("progress-fg.png"); + +/* ═══════════════════════════════════════════════════════════════ + * Screen Divider (3DS hinge simulation) + * ═══════════════════════════════════════════════════════════════ */ +divider_sprite = Sprite(); +divider_img = Image.Text("", 1, 1, 1, 1); /* Placeholder if no image */ +if (divider_line) { + divider_sprite.SetImage(divider_line); +} else { + /* Create a simple dark blue line */ + divider_sprite.SetImage(divider_img); +} +divider_sprite.SetX(0); +divider_sprite.SetY(divider_y - 2); +divider_sprite.SetZ(50); +divider_sprite.SetOpacity(0.8); + +/* ═══════════════════════════════════════════════════════════════ + * UPPER SCREEN - 3 Nested Cubes + * ═══════════════════════════════════════════════════════════════ */ + +/* Cube sizes (nested: large → medium → small) */ +cube_sizes[0] = 100; /* Outer */ +cube_sizes[1] = 65; /* Middle */ +cube_sizes[2] = 35; /* Inner */ + +/* Rotation speeds (desynchronized) */ +cube_speed_x[0] = 0.004; cube_speed_y[0] = 0.007; cube_speed_z[0] = 0.003; +cube_speed_x[1] = 0.009; cube_speed_y[1] = 0.005; cube_speed_z[1] = 0.008; +cube_speed_x[2] = 0.015; cube_speed_y[2] = 0.012; cube_speed_z[2] = 0.006; + +/* Rotation angles */ +cube_angle_x[0] = 0; cube_angle_y[0] = 0; cube_angle_z[0] = 0; +cube_angle_x[1] = 1.0; cube_angle_y[1] = 0.5; cube_angle_z[1] = 0.3; +cube_angle_x[2] = 2.0; cube_angle_y[2] = 1.5; cube_angle_z[2] = 1.0; + +/* Cube edge sprites (12 edges × 3 cubes = 36 sprites) */ +/* We'll draw simplified: 8 corner dots per cube */ +for (c = 0; c < 3; c++) { + for (v = 0; v < 8; v++) { + idx = c * 8 + v; + cube_vertices[idx] = Sprite(); + cube_vertices[idx].SetZ(20 + c * 5); + } +} + +/* ═══════════════════════════════════════════════════════════════ + * UPPER SCREEN - 2 Lemniscates (∞ curves) + * ═══════════════════════════════════════════════════════════════ */ + +/* Lemniscate parameters */ +lemniscate_scale = 80; /* Size of the infinity symbol */ +lemniscate_y_offset[0] = -30; /* Above center */ +lemniscate_y_offset[1] = 30; /* Below center */ + +/* Each lemniscate has multiple trail dots + 1 bright head */ +dots_per_curve = 12; +head_speed[0] = 0.025; +head_speed[1] = 0.018; /* Different speed for visual interest */ +head_pos[0] = 0; +head_pos[1] = 3.14159; /* Start opposite */ + +/* Lemniscate dot sprites */ +for (l = 0; l < 2; l++) { + for (d = 0; d < dots_per_curve; d++) { + idx = l * dots_per_curve + d; + lem_dots[idx] = Sprite(); + lem_dots[idx].SetZ(15); + } + /* Bright head */ + lem_heads[l] = Sprite(); + lem_heads[l].SetZ(18); +} + +/* ═══════════════════════════════════════════════════════════════ + * LOWER SCREEN - Kernel Log Area + * ═══════════════════════════════════════════════════════════════ */ + +/* Log line sprites (scrolling buffer) */ +max_log_lines = 8; +for (i = 0; i < max_log_lines; i++) { + log_sprites[i] = Sprite(); + log_sprites[i].SetZ(30); +} +log_texts[0] = ""; +log_texts[1] = ""; +log_texts[2] = ""; +log_texts[3] = ""; +log_texts[4] = ""; +log_texts[5] = ""; +log_texts[6] = ""; +log_texts[7] = ""; +log_index = 0; + +/* Progress bar */ +progress_bg_sprite = Sprite(); +progress_fg_sprite = Sprite(); +if (progress_bg) { + progress_bg_sprite.SetImage(progress_bg); +} +progress_bg_sprite.SetX(lower_center_x - 120); +progress_bg_sprite.SetY(lower_center_y + 70); +progress_bg_sprite.SetZ(35); + +if (progress_fg) { + progress_fg_sprite.SetImage(progress_fg); +} +progress_fg_sprite.SetX(lower_center_x - 118); +progress_fg_sprite.SetY(lower_center_y + 72); +progress_fg_sprite.SetZ(36); + +/* Phase message */ +phase_sprite = Sprite(); +phase_sprite.SetZ(40); +current_phase = "Initializing..."; + +/* ═══════════════════════════════════════════════════════════════ + * Animation State + * ═══════════════════════════════════════════════════════════════ */ +frame = 0; +boot_progress = 0; + +/* ═══════════════════════════════════════════════════════════════ + * 3D Math - Cube vertex projection + * ═══════════════════════════════════════════════════════════════ */ + +/* Unit cube vertices (±1, ±1, ±1) */ +unit_cube_x[0] = -1; unit_cube_y[0] = -1; unit_cube_z[0] = -1; +unit_cube_x[1] = 1; unit_cube_y[1] = -1; unit_cube_z[1] = -1; +unit_cube_x[2] = 1; unit_cube_y[2] = 1; unit_cube_z[2] = -1; +unit_cube_x[3] = -1; unit_cube_y[3] = 1; unit_cube_z[3] = -1; +unit_cube_x[4] = -1; unit_cube_y[4] = -1; unit_cube_z[4] = 1; +unit_cube_x[5] = 1; unit_cube_y[5] = -1; unit_cube_z[5] = 1; +unit_cube_x[6] = 1; unit_cube_y[6] = 1; unit_cube_z[6] = 1; +unit_cube_x[7] = -1; unit_cube_y[7] = 1; unit_cube_z[7] = 1; + +fun rotate_point(px, py, pz, ax, ay, az) { + /* Rotate around X */ + cos_x = Math.Cos(ax); + sin_x = Math.Sin(ax); + y1 = py * cos_x - pz * sin_x; + z1 = py * sin_x + pz * cos_x; + + /* Rotate around Y */ + cos_y = Math.Cos(ay); + sin_y = Math.Sin(ay); + x2 = px * cos_y + z1 * sin_y; + z2 = -px * sin_y + z1 * cos_y; + + /* Rotate around Z */ + cos_z = Math.Cos(az); + sin_z = Math.Sin(az); + x3 = x2 * cos_z - y1 * sin_z; + y3 = x2 * sin_z + y1 * cos_z; + + result[0] = x3; + result[1] = y3; + result[2] = z2; + return result; +} + +/* ═══════════════════════════════════════════════════════════════ + * Lemniscate parametric curve (Bernoulli lemniscate) + * x = a * cos(t) / (1 + sin²(t)) + * y = a * sin(t) * cos(t) / (1 + sin²(t)) + * ═══════════════════════════════════════════════════════════════ */ + +fun lemniscate_x(t, scale) { + sin_t = Math.Sin(t); + cos_t = Math.Cos(t); + denom = 1 + sin_t * sin_t; + return scale * cos_t / denom; +} + +fun lemniscate_y(t, scale) { + sin_t = Math.Sin(t); + cos_t = Math.Cos(t); + denom = 1 + sin_t * sin_t; + return scale * sin_t * cos_t / denom; +} + +/* ═══════════════════════════════════════════════════════════════ + * Animation Functions + * ═══════════════════════════════════════════════════════════════ */ + +fun draw_cube(cube_idx) { + ax = global.cube_angle_x[cube_idx]; + ay = global.cube_angle_y[cube_idx]; + az = global.cube_angle_z[cube_idx]; + size = global.cube_sizes[cube_idx] / 2; + + /* Brightness based on cube layer (inner = brightest) */ + brightness = 0.3 + (2 - cube_idx) * 0.3; + + for (v = 0; v < 8; v++) { + /* Get unit cube vertex */ + px = global.unit_cube_x[v] * size; + py = global.unit_cube_y[v] * size; + pz = global.unit_cube_z[v] * size; + + /* Rotate */ + rotated = rotate_point(px, py, pz, ax, ay, az); + + /* Project to screen (simple orthographic) */ + screen_x = global.upper_center_x + rotated[0]; + screen_y = global.upper_center_y + rotated[1]; + + /* Depth-based opacity */ + depth = (rotated[2] + size) / (size * 2); + opacity = brightness * (0.5 + depth * 0.5); + + /* Create vertex dot */ + idx = cube_idx * 8 + v; + dot_size = 4 + (2 - cube_idx) * 2; /* Inner cube has bigger dots */ + + dot_img = Image.Text("*", global.blue_mid_r * brightness, + global.blue_mid_g * brightness, + global.blue_bright_b * brightness, 1); + global.cube_vertices[idx].SetImage(dot_img); + global.cube_vertices[idx].SetX(screen_x - dot_size/2); + global.cube_vertices[idx].SetY(screen_y - dot_size/2); + global.cube_vertices[idx].SetOpacity(opacity); + } +} + +fun draw_lemniscates() { + for (l = 0; l < 2; l++) { + /* Update head position */ + global.head_pos[l] += global.head_speed[l]; + if (global.head_pos[l] > 6.28318) { + global.head_pos[l] -= 6.28318; + } + + y_off = global.lemniscate_y_offset[l]; + + /* Draw trail dots */ + for (d = 0; d < global.dots_per_curve; d++) { + /* Position along curve (behind the head) */ + t = global.head_pos[l] - d * 0.4; + + lx = lemniscate_x(t, global.lemniscate_scale); + ly = lemniscate_y(t, global.lemniscate_scale); + + screen_x = global.upper_center_x + lx; + screen_y = global.upper_center_y + y_off + ly; + + /* Fade trail */ + fade = 1.0 - (d / global.dots_per_curve) * 0.8; + + idx = l * global.dots_per_curve + d; + dot_img = Image.Text(".", global.blue_dark_r + fade * 0.1, + global.blue_dark_g + fade * 0.2, + global.blue_bright_b * fade, 1); + global.lem_dots[idx].SetImage(dot_img); + global.lem_dots[idx].SetX(screen_x - 2); + global.lem_dots[idx].SetY(screen_y - 2); + global.lem_dots[idx].SetOpacity(fade * 0.7); + } + + /* Draw bright head */ + hx = lemniscate_x(global.head_pos[l], global.lemniscate_scale); + hy = lemniscate_y(global.head_pos[l], global.lemniscate_scale); + + head_screen_x = global.upper_center_x + hx; + head_screen_y = global.upper_center_y + y_off + hy; + + /* Pulsing head */ + pulse = 0.8 + Math.Sin(global.frame * 0.2) * 0.2; + head_img = Image.Text("O", global.blue_bright_r * pulse, + global.blue_bright_g * pulse, + global.blue_bright_b, 1); + global.lem_heads[l].SetImage(head_img); + global.lem_heads[l].SetX(head_screen_x - 4); + global.lem_heads[l].SetY(head_screen_y - 4); + global.lem_heads[l].SetOpacity(1.0); + } +} + +fun update_log_display() { + line_height = 16; + start_y = global.divider_y + 15; + left_margin = 30; + + for (i = 0; i < global.max_log_lines; i++) { + if (global.log_texts[i] != "") { + /* Simple color based on content */ + if (String(global.log_texts[i]).Find("OK") >= 0 || + String(global.log_texts[i]).Find("Started") >= 0) { + r = global.log_green_r; + g = global.log_green_g; + b = global.log_green_b; + } else if (String(global.log_texts[i]).Find("warn") >= 0 || + String(global.log_texts[i]).Find("WARN") >= 0) { + r = global.log_amber_r; + g = global.log_amber_g; + b = global.log_amber_b; + } else { + r = global.log_blue_r; + g = global.log_blue_g; + b = global.log_blue_b; + } + + txt_img = Image.Text(global.log_texts[i], r, g, b, "Mono 9"); + global.log_sprites[i].SetImage(txt_img); + global.log_sprites[i].SetX(left_margin); + global.log_sprites[i].SetY(start_y + i * line_height); + global.log_sprites[i].SetOpacity(0.9); + } + } +} + +fun update_phase() { + phase_img = Image.Text(global.current_phase, + global.blue_bright_r, + global.blue_bright_g, + global.blue_bright_b, "Sans Bold 11"); + global.phase_sprite.SetImage(phase_img); + global.phase_sprite.SetX(global.lower_center_x - phase_img.GetWidth() / 2); + global.phase_sprite.SetY(global.lower_center_y + 50); +} + +/* ═══════════════════════════════════════════════════════════════ + * Main Animation Loop + * ═══════════════════════════════════════════════════════════════ */ + +fun refresh_callback() { + global.frame++; + + /* Update cube rotations */ + for (c = 0; c < 3; c++) { + global.cube_angle_x[c] += global.cube_speed_x[c]; + global.cube_angle_y[c] += global.cube_speed_y[c]; + global.cube_angle_z[c] += global.cube_speed_z[c]; + + /* Keep in bounds */ + if (global.cube_angle_x[c] > 6.28318) global.cube_angle_x[c] -= 6.28318; + if (global.cube_angle_y[c] > 6.28318) global.cube_angle_y[c] -= 6.28318; + if (global.cube_angle_z[c] > 6.28318) global.cube_angle_z[c] -= 6.28318; + + draw_cube(c); + } + + /* Draw lemniscates */ + draw_lemniscates(); + + /* Update phase display */ + update_phase(); +} + +Plymouth.SetRefreshFunction(refresh_callback); + +/* ═══════════════════════════════════════════════════════════════ + * Plymouth Callbacks + * ═══════════════════════════════════════════════════════════════ */ + +fun boot_progress_callback(duration, progress_val) { + global.boot_progress = progress_val; + + /* Update progress bar */ + if (progress_fg) { + bar_width = Math.Int(progress_val * 236); + if (bar_width > 0) { + scaled = progress_fg.Scale(bar_width, 12); + progress_fg_sprite.SetImage(scaled); + } + } + + /* Update phase message based on progress */ + if (progress_val < 0.15) { + global.current_phase = "Loading kernel modules..."; + } else if (progress_val < 0.30) { + global.current_phase = "Initializing hardware..."; + } else if (progress_val < 0.50) { + global.current_phase = "Starting system services..."; + } else if (progress_val < 0.70) { + global.current_phase = "Configuring network..."; + } else if (progress_val < 0.90) { + global.current_phase = "Starting SecuBox modules..."; + } else { + global.current_phase = "System ready"; + } +} + +Plymouth.SetBootProgressFunction(boot_progress_callback); + +fun message_callback(text) { + /* Add to log buffer (scrolling) */ + /* Shift existing lines up */ + for (i = global.max_log_lines - 1; i > 0; i--) { + global.log_texts[i] = global.log_texts[i-1]; + } + + /* Add timestamp prefix */ + timestamp = Math.Int(global.frame / 60); + ts_str = "[" + timestamp + "] "; + global.log_texts[0] = ts_str + text; + + update_log_display(); +} + +Plymouth.SetMessageFunction(message_callback); + +fun display_normal_callback() { + /* Normal boot display */ +} + +fun display_password_callback(prompt, bullets) { + /* LUKS password prompt */ + prompt_img = Image.Text(prompt, + global.blue_bright_r, + global.blue_bright_g, + global.blue_bright_b, "Sans Bold 12"); + global.phase_sprite.SetImage(prompt_img); + global.phase_sprite.SetX(global.lower_center_x - prompt_img.GetWidth() / 2); + global.phase_sprite.SetY(global.lower_center_y + 30); + + /* Show bullet dots for password */ + bullet_str = ""; + for (i = 0; i < bullets; i++) { + bullet_str += "*"; + } + bullet_img = Image.Text(bullet_str, 1.0, 1.0, 1.0, "Mono 14"); + /* Could add another sprite for bullets */ +} + +Plymouth.SetDisplayNormalFunction(display_normal_callback); +Plymouth.SetDisplayPasswordFunction(display_password_callback); + +fun quit_callback() { + /* Fade out animation */ + for (c = 0; c < 3; c++) { + for (v = 0; v < 8; v++) { + idx = c * 8 + v; + global.cube_vertices[idx].SetOpacity(0); + } + } + + for (l = 0; l < 2; l++) { + for (d = 0; d < global.dots_per_curve; d++) { + idx = l * global.dots_per_curve + d; + global.lem_dots[idx].SetOpacity(0); + } + global.lem_heads[l].SetOpacity(0); + } + + global.phase_sprite.SetOpacity(0); + progress_bg_sprite.SetOpacity(0); + progress_fg_sprite.SetOpacity(0); + divider_sprite.SetOpacity(0); + + for (i = 0; i < global.max_log_lines; i++) { + global.log_sprites[i].SetOpacity(0); + } +} + +Plymouth.SetQuitFunction(quit_callback); diff --git a/image/plymouth/secubox-cube/progress-bg-green.bak b/image/plymouth/secubox-cube/progress-bg-green.bak new file mode 100644 index 0000000000000000000000000000000000000000..aa0543e363d8a0fdbc88b57b86578a10d7d308c8 GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!MFg0Da@a2CEqi4B`cIb_Lo1CD@X@-Ch2J0cXVbJ3tZk5>H=O_E#*N+(Hsl z{A#j*LMuF7978H@y}i0n^pJr>>%}R-!L8}c%U0=e8!&S>biNG9X>bo^3p~su@bR7L z$)8t??+18gZxv(cFnM==%N)Jy?(Yp5KG@%WT)JQP@%PM#`>(&fvE^Z?TYdI;rPcfY z&Oq4d!YS9X-r6!V{QALg Y(@ALh<14oDKsPgZy85}Sb4q9e05W`Ov;Y7A literal 0 HcmV?d00001 diff --git a/image/plymouth/secubox-cube/progress-bg.png b/image/plymouth/secubox-cube/progress-bg.png index aa0543e363d8a0fdbc88b57b86578a10d7d308c8..7c2839e5e3107d0eda809adb8dbb0f1165841aea 100644 GIT binary patch delta 106 zcmdnQw48B*1Scai0|Nu^+euCn6%E1yd_r8M3yxm>?g8^s6_d7rd_7YEDSN2ydoZLbZQ~YYO zfI=%gT^vIyZoR#_Q1p<2MC-*V!NINR%*$5kaT_pmH*~%X$!Ty8WeYsaB=GT_>B*m0 zi|+?`Wp5Q@=rDPAe#;!a>+bIj89vzGeq6d=_wo14i2JXa@a2CEqi4B`cIb_Lo1CD;OdLR=aC&-wrV{|s$5pe_c+ByV>Y#{W#Z z_kbMs5>H=O_E#*N+(Hsl{A#j*Lj0aCjv*T7lM^IZ7dMnKFfb)BFbe$GbQ37W;OXk; Jvd$@?2>{ZyD3bsH literal 0 HcmV?d00001 diff --git a/image/plymouth/secubox-cube/progress-fg.png b/image/plymouth/secubox-cube/progress-fg.png index e381b245d679e73f459e0fa15b67318d7e6f6852..627a8c5243571ac51570f7a13a1b7d4158ab38e5 100644 GIT binary patch delta 32 ocmZ3+xQuZ^C|BBnH~;?qOBCZ%oER^`!NVoZ{asJy$HaPd0NzOqtN;K2 delta 32 ocmZ3+xQuZ^C>O*3IsgCvpP|j>J275@gOgiGVv1i)*2H>s0NBI~IRF3v diff --git a/image/plymouth/secubox-cube/secubox-cube.script b/image/plymouth/secubox-cube/secubox-cube.script index 70b46d4e..340b1509 100644 --- a/image/plymouth/secubox-cube/secubox-cube.script +++ b/image/plymouth/secubox-cube/secubox-cube.script @@ -1,127 +1,266 @@ -/* SecuBox Cube - Plymouth Theme Script - * 3D Rotating Cube with Module Icons +/* SecuBox Dice 3D - Plymouth Theme Script + * Rotating 3D Cube with Module Icons on Faces + * Nintendo 3DS aesthetic - dark blue autostereoscopic style * CyberMind - https://cybermind.fr */ -/* Screen setup */ -Window.SetBackgroundTopColor(0.0, 0.0, 0.0); -Window.SetBackgroundBottomColor(0.02, 0.04, 0.02); +/* ═══════════════════════════════════════════════════════════════ + * Screen Setup - 3DS dark blue gradient background + * ═══════════════════════════════════════════════════════════════ */ +Window.SetBackgroundTopColor(0.063, 0.082, 0.165); /* #101529 - 3DS top screen dark */ +Window.SetBackgroundBottomColor(0.039, 0.055, 0.118); /* #0a0e1e - 3DS deeper blue */ screen_width = Window.GetWidth(); screen_height = Window.GetHeight(); center_x = screen_width / 2; center_y = screen_height / 2; -/* Load images */ +/* ═══════════════════════════════════════════════════════════════ + * Load Assets + * ═══════════════════════════════════════════════════════════════ */ logo = Image("logo.png"); scanlines = Image("scanlines.png"); - -/* Module icons - 6 faces of the cube */ -icon_root = Image("icon-root.png"); -icon_boot = Image("icon-boot.png"); -icon_mesh = Image("icon-mesh.png"); -icon_wall = Image("icon-wall.png"); -icon_auth = Image("icon-auth.png"); -icon_mind = Image("icon-mind.png"); - -/* Progress bar images */ progress_bg = Image("progress-bg.png"); progress_fg = Image("progress-fg.png"); -/* Create sprites */ +/* 6 face icons - one per cube face */ +face_images[0] = Image("icon-root.png"); /* Front - Root/System */ +face_images[1] = Image("icon-wall.png"); /* Back - Firewall */ +face_images[2] = Image("icon-boot.png"); /* Top - Boot */ +face_images[3] = Image("icon-mesh.png"); /* Bottom - Mesh Network */ +face_images[4] = Image("icon-auth.png"); /* Right - Auth */ +face_images[5] = Image("icon-mind.png"); /* Left - CyberMind */ + +/* ═══════════════════════════════════════════════════════════════ + * Create Sprites + * ═══════════════════════════════════════════════════════════════ */ + +/* Logo at top */ logo_sprite = Sprite(logo); logo_sprite.SetX(center_x - logo.GetWidth() / 2); -logo_sprite.SetY(center_y - 180); +logo_sprite.SetY(center_y - 200); logo_sprite.SetZ(10); -/* Scanline overlay */ +/* Scanline overlay - subtle 3DS parallax barrier simulation */ scanline_sprite = Sprite(scanlines); scanline_sprite.SetX(0); scanline_sprite.SetY(0); scanline_sprite.SetZ(100); -scanline_sprite.SetOpacity(0.15); +scanline_sprite.SetOpacity(0.04); /* Lighter for 3DS glass effect */ -/* Module icon sprites - arranged in hexagon */ -icon_size = 64; -radius = 100; -icons[0] = Sprite(icon_root); -icons[1] = Sprite(icon_boot); -icons[2] = Sprite(icon_mesh); -icons[3] = Sprite(icon_wall); -icons[4] = Sprite(icon_auth); -icons[5] = Sprite(icon_mind); - -/* Initial positions */ +/* Face sprites - we'll show up to 3 visible faces */ for (i = 0; i < 6; i++) { - icons[i].SetZ(5); - icons[i].SetOpacity(0.8); + face_sprites[i] = Sprite(face_images[i]); + face_sprites[i].SetOpacity(0); + face_sprites[i].SetZ(5); } +/* Edge glow sprites - green wireframe effect */ +/* We'll draw edges as thin colored lines using scaled images */ + /* Progress bar */ progress_bg_sprite = Sprite(progress_bg); progress_bg_sprite.SetX(center_x - 150); -progress_bg_sprite.SetY(center_y + 140); +progress_bg_sprite.SetY(center_y + 160); progress_bg_sprite.SetZ(8); progress_sprite = Sprite(progress_fg); progress_sprite.SetX(center_x - 148); -progress_sprite.SetY(center_y + 142); +progress_sprite.SetY(center_y + 162); progress_sprite.SetZ(9); -/* Status text */ -status_text = ""; +/* Status message */ message_sprite = Sprite(); -message_sprite.SetPosition(center_x, center_y + 180, 10); +message_sprite.SetPosition(center_x, center_y + 195, 10); -/* Animation state */ -angle = 0; +/* ═══════════════════════════════════════════════════════════════ + * Animation State + * ═══════════════════════════════════════════════════════════════ */ +angle_x = 0; +angle_y = 0; +angle_z = 0; frame = 0; progress = 0; -/* Animation function - rotate icons in 3D-like pattern */ -fun animate_cube() { - global.angle += 0.02; - global.frame++; +/* Cube size */ +cube_size = 80; - for (i = 0; i < 6; i++) { - /* Calculate 3D-like position */ - base_angle = global.angle + (i * 3.14159 / 3); +/* Rotation speeds - 3DS-style smooth, elegant rotation */ +speed_x = 0.006; +speed_y = 0.012; +speed_z = 0.004; - /* X position - circular motion */ - x = center_x + Math.Sin(base_angle) * radius - icon_size / 2; +/* ═══════════════════════════════════════════════════════════════ + * 3D Math Functions + * ═══════════════════════════════════════════════════════════════ */ - /* Y position - elliptical for 3D effect */ - y = center_y + Math.Cos(base_angle) * (radius * 0.4) - icon_size / 2; +/* Face normals in local space (which way each face points) */ +/* Face 0: Front (+Z) */ +/* Face 1: Back (-Z) */ +/* Face 2: Top (+Y) */ +/* Face 3: Bottom (-Y) */ +/* Face 4: Right (+X) */ +/* Face 5: Left (-X) */ - /* Z-depth simulation via opacity and scale */ - depth = Math.Cos(base_angle); - opacity = 0.4 + (depth + 1) * 0.3; +fun get_face_visibility(face_index, ax, ay, az) { + /* Calculate if face is visible (normal pointing toward camera) */ + /* Camera is at +Z looking at origin */ - icons[i].SetX(x); - icons[i].SetY(y); - icons[i].SetOpacity(opacity); + /* Simplified: calculate rotated normal Z component */ + /* If > 0, face is visible (pointing toward us) */ - /* Bring front icons to top */ - if (depth > 0) { - icons[i].SetZ(6); - } else { - icons[i].SetZ(4); - } + cos_x = Math.Cos(ax); + sin_x = Math.Sin(ax); + cos_y = Math.Cos(ay); + sin_y = Math.Sin(ay); + cos_z = Math.Cos(az); + sin_z = Math.Sin(az); + + /* Normal vectors for each face */ + if (face_index == 0) { + /* Front (+Z): normal = (0, 0, 1) */ + nz = cos_x * cos_y; + } else if (face_index == 1) { + /* Back (-Z): normal = (0, 0, -1) */ + nz = -cos_x * cos_y; + } else if (face_index == 2) { + /* Top (+Y): normal = (0, 1, 0) */ + nz = sin_x; + } else if (face_index == 3) { + /* Bottom (-Y): normal = (0, -1, 0) */ + nz = -sin_x; + } else if (face_index == 4) { + /* Right (+X): normal = (1, 0, 0) */ + nz = -sin_y * cos_x; + } else { + /* Left (-X): normal = (-1, 0, 0) */ + nz = sin_y * cos_x; } + + return nz; } -/* Progress callback */ +fun get_face_center(face_index, ax, ay, size) { + /* Calculate projected 2D center of each face */ + cos_x = Math.Cos(ax); + sin_x = Math.Sin(ax); + cos_y = Math.Cos(ay); + sin_y = Math.Sin(ay); + + half = size / 2; + + if (face_index == 0) { + /* Front: center at (0, 0, +half) */ + x = sin_y * half; + y = -sin_x * cos_y * half; + z = cos_x * cos_y * half; + } else if (face_index == 1) { + /* Back: center at (0, 0, -half) */ + x = -sin_y * half; + y = sin_x * cos_y * half; + z = -cos_x * cos_y * half; + } else if (face_index == 2) { + /* Top: center at (0, +half, 0) */ + x = 0; + y = cos_x * half; + z = sin_x * half; + } else if (face_index == 3) { + /* Bottom: center at (0, -half, 0) */ + x = 0; + y = -cos_x * half; + z = -sin_x * half; + } else if (face_index == 4) { + /* Right: center at (+half, 0, 0) */ + x = cos_y * half; + y = 0; + z = -sin_y * half; + } else { + /* Left: center at (-half, 0, 0) */ + x = -cos_y * half; + y = 0; + z = sin_y * half; + } + + /* Return as pseudo-struct (array) */ + result[0] = x; + result[1] = y; + result[2] = z; + return result; +} + +/* ═══════════════════════════════════════════════════════════════ + * Animation Loop + * ═══════════════════════════════════════════════════════════════ */ +fun animate_cube() { + /* Update rotation angles */ + global.angle_x += global.speed_x; + global.angle_y += global.speed_y; + global.angle_z += global.speed_z; + global.frame++; + + /* Keep angles in bounds */ + if (global.angle_x > 6.28318) global.angle_x -= 6.28318; + if (global.angle_y > 6.28318) global.angle_y -= 6.28318; + if (global.angle_z > 6.28318) global.angle_z -= 6.28318; + + /* Update each face */ + for (i = 0; i < 6; i++) { + /* Check visibility */ + visibility = get_face_visibility(i, global.angle_x, global.angle_y, global.angle_z); + + if (visibility > 0) { + /* Face is visible */ + pos = get_face_center(i, global.angle_x, global.angle_y, global.cube_size); + + /* Project to screen (orthographic with slight perspective feel) */ + depth_scale = 0.8 + (pos[2] / global.cube_size) * 0.2; + + /* Scale icon based on depth */ + icon_scale = 0.6 + visibility * 0.4; + icon_size = 64 * icon_scale * depth_scale; + + /* Calculate screen position */ + screen_x = center_x + pos[0] * 1.5 - icon_size / 2; + screen_y = center_y + pos[1] * 1.5 - icon_size / 2; + + /* Scale the image */ + scaled = face_images[i].Scale(icon_size, icon_size); + face_sprites[i].SetImage(scaled); + + /* Position */ + face_sprites[i].SetX(screen_x); + face_sprites[i].SetY(screen_y); + + /* Opacity based on how directly it faces us + green tint simulation */ + opacity = 0.5 + visibility * 0.5; + face_sprites[i].SetOpacity(opacity); + + /* Z-order based on depth */ + face_sprites[i].SetZ(5 + pos[2] / 10); + } else { + /* Face not visible */ + face_sprites[i].SetOpacity(0); + } + } + + /* 3DS-style gentle glow pulse - slower, more elegant */ + pulse = 0.90 + Math.Sin(global.frame * 0.03) * 0.10; + logo_sprite.SetOpacity(pulse); +} + +/* ═══════════════════════════════════════════════════════════════ + * Plymouth Callbacks + * ═══════════════════════════════════════════════════════════════ */ + fun refresh_callback() { animate_cube(); } Plymouth.SetRefreshFunction(refresh_callback); -/* Boot progress */ fun boot_progress_callback(duration, progress_val) { global.progress = progress_val; - /* Scale progress bar */ if (progress_fg) { scaled = progress_fg.Scale(progress_val * 296, 16); progress_sprite.SetImage(scaled); @@ -130,26 +269,23 @@ fun boot_progress_callback(duration, progress_val) { Plymouth.SetBootProgressFunction(boot_progress_callback); -/* Message display */ fun message_callback(text) { - global.status_text = text; - - msg_image = Image.Text(text, 0, 1, 0.61, "JetBrains Mono"); + /* 3DS cyan/light blue text */ + msg_image = Image.Text(text, 0.400, 0.753, 0.925, "JetBrains Mono"); /* #66c0ec */ message_sprite.SetImage(msg_image); message_sprite.SetX(center_x - msg_image.GetWidth() / 2); - message_sprite.SetY(center_y + 180); + message_sprite.SetY(center_y + 195); } Plymouth.SetMessageFunction(message_callback); -/* Display normal/password prompts */ fun display_normal_callback() { - /* Nothing special */ + /* Normal display mode */ } fun display_password_callback(prompt, bullets) { - /* Show password prompt */ - prompt_image = Image.Text(prompt, 0, 1, 0.61, "JetBrains Mono"); + /* Password prompt - 3DS cyan accent */ + prompt_image = Image.Text(prompt, 0.400, 0.753, 0.925, "JetBrains Mono"); /* #66c0ec */ message_sprite.SetImage(prompt_image); message_sprite.SetX(center_x - prompt_image.GetWidth() / 2); } @@ -157,13 +293,13 @@ fun display_password_callback(prompt, bullets) { Plymouth.SetDisplayNormalFunction(display_normal_callback); Plymouth.SetDisplayPasswordFunction(display_password_callback); -/* Quit callback */ fun quit_callback() { - /* Fade out */ + /* Fade out all elements */ for (i = 0; i < 6; i++) { - icons[i].SetOpacity(0); + face_sprites[i].SetOpacity(0); } logo_sprite.SetOpacity(0); + scanline_sprite.SetOpacity(0); } Plymouth.SetQuitFunction(quit_callback); diff --git a/image/sbin/secubox-kiosk-launcher b/image/sbin/secubox-kiosk-launcher index fce6a992..56f3f64f 100755 --- a/image/sbin/secubox-kiosk-launcher +++ b/image/sbin/secubox-kiosk-launcher @@ -133,25 +133,33 @@ create_session() { chown -R "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.config" # Minimal session script - just Chromium, no optional tools + # Use --start-fullscreen (not --kiosk) for better VT switching compatibility cat > "$KIOSK_HOME/.xsession" </dev/null || true xset -dpms 2>/dev/null || true +xset s noblank 2>/dev/null || true -# Launch Chromium directly +# Chromium flags for kiosk mode +# --start-fullscreen: allows Ctrl+Alt+Fn VT switching (better than --kiosk) +# --disable-gpu: avoid GPU issues in VMs +# --no-sandbox: required in chroot/container environments +# exec replaces shell with chromium - on exit, X session ends exec chromium \\ - --kiosk \\ + --start-fullscreen \\ --no-first-run \\ --no-sandbox \\ --disable-gpu \\ - --disable-software-rasterizer \\ + --disable-pinch \\ + --noerrdialogs \\ + --disable-translate \\ --ignore-certificate-errors \\ --disable-features=TranslateUI \\ --window-position=0,0 \\ @@ -201,7 +209,7 @@ start_display() { # ══════════════════════════════════════════════════════════════════ main() { log "════════════════════════════════════════════════" - log "SecuBox Kiosk Launcher v2.0" + log "SecuBox Kiosk Launcher v2.1 (1.6.3)" log "════════════════════════════════════════════════" check_prerequisites