SchOS/.claude/memory/schunix-crash-screen.md
Nexoniarz 953f9c5c3c branding: one mark, and PSOGM draws it
Guru and SchCotie are gone. Shift is the only mark, and the crash screen draws
it where the face used to be.

Guru was an icon -- a pictogram with a face, denoting one state -- that lived
on the crash screen and nowhere else. Its argument was identity: `:(` is
recognisably Microsoft's, and a crash screen is the single screenshot most
likely to leave the machine, so it is the worst place to be wearing somebody
else's face. That part holds, and it is kept in the branding README because it
is the argument against any second mark. What does not follow is that the
answer is a *new* mark. Shift already signs the system, it is already what the
machine drew on the splash it started with, and a reader who has seen it twice
before the crash recognises it faster than a face they have never seen.

SchCotie was a mascot, and never existed: the file said so itself under "what
this does not cover". A brief for a character nobody is about to draw is not
worth carrying.

So `draw_guru()` and its SVG-space geometry leave panic.c, the two `guru.svg`
files are deleted, and PSOGM calls gfx_draw_logo() -- the same include/logo.h
mask the loader splash and the boot console composite. At its native 128 px:
there is no resampler in the crash path, and the face was scalable in a place
that only ever drew it at one size.

The name stays. "Purple Screen of Guru Meditation" is the Amiga nod, which
panic.c's own header already called out as a separate thing from the mark.

**And taking the screenshot to check it caught a regression from the TTF
console work.** `gfx_draw_char()` -- the pixel-positioned path, which only
PSOGM uses -- still walked `font_data[c][row]` for `row < CHAR_HEIGHT`.
font_data has exactly 16 rows per glyph; CHAR_HEIGHT is the *TrueType* cell
height now, about 21. So every line of the crash report drew five rows of the
next character's bitmap underneath itself, and it looked like each line had
been printed twice. The grid path had been updated when the cell size stopped
being a constant; this one had not, because nothing routine draws text in pixel
coordinates. Both go through one draw_glyph_px() now, and the bitmap's own
geometry is spelled BITMAP_W/BITMAP_H so it cannot be mistaken for a cell size
again.

Two stale claims corrected while in there, in panic.c's header and in
graphics.md: PSOGM has not dimmed-and-floated over the old screen for a while
-- it clears to full purple, and the file's own code comment says why -- and
there is no longer "a face that is obviously a cartoon".

The website's crash section shows the mark in flat white rather than its own
violets, which is what the kernel actually draws: PSOGM composites a coverage
mask in one colour, and those violets sit close enough to #4B1D9A to
half-disappear against it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 21:35:58 +02:00

4 KiB

name description metadata
schunix-crash-screen PSOGM crash screen lives in kernel/core/panic.c; test it with `echo c > /proc/sysrq` and tools/crashshot.ps1
node_type type originSessionId modified
memory project a665e14b-86bd-4b41-a228-51377f3e9225 2026-08-03T15:09:42.189Z

The crash screen is kernel/core/panic.c (rewritten 2026-08-03; it used to live inside console.c). PSOGM — Purple Screen of Guru Meditation. Solid purple, big white :( drawn from primitives, Windows-style left-aligned headline and field table, then a raw call-chain dump. Nexoniarz picked this after a first attempt that dimmed the desktop and floated a dark panel with a cartoon emoji over it — the emoji and the muted palette read as out of place; the name says purple screen, so it is one.

A "Stop code" field is derived from the panic message (uppercased up to the first colon: "sysrq: crash requested" → SYSRQ), so no call site has to supply one.

To see it, crash on purpose:

echo c > /proc/sysrq          # from inside Schunix

To photograph it: pwsh -File tools/crashshot.ps1 (or make crashshot) after make ramroot. It boots, fills the screen with real output, crashes, and pulls a PPM out through QEMU's monitor on TCP 55555. Convert with convert build/crashscreen.ppm build/crashscreen.png — ImageMagick is in the WSL Fedora box as convert, not magick.

Why the trigger exists at all: the crash screen is the one part of the system you cannot look at by using the system, so without a deliberate trigger it is only ever seen when something is already wrong, and it quietly rots.

Three things that will bite anyone editing it:

  • There is no libm. isqrt in panic.c uses Newton's method iterated while the estimate decreases; the obvious "stop when it stops changing" version does not terminate, because on a non-square it settles into a two-cycle (isqrt(3) alternates 1, 2, 1, 2...). That shipped once and hung the panic handler with the screen half drawn — a hang with no way to find out why.

  • vga_draw_char fills the background of every glyph with vga_bg. Drawing panel text without setting vga_set_bg(PSOGM_PANEL) first puts every line in a cream-coloured box.

  • cprintf writes to the framebuffer as well as the serial line, so the serial report scrolls straight over the panel. cons_panic_mode() sets cons_serial_only, which is what keeps the two apart — paint order alone does not.

The serial copy is the one that survives, and it is what tools/bootcheck.ps1 reads. It is also all you get when the panic happens before there is a framebuffer. See schunix-verify-by-driving-shell.

2026-09-21: the face is gone, and a bug it exposed

PSOGM draws Shift, the system logo, where the Guru face used to be — gfx_draw_logo() from include/logo.h, the same mask the loader splash and the boot console use, at its native 128 px. draw_guru() and its geometry constants are deleted; so are docs/branding/guru.svg and the mascot brief. The name "Purple Screen of Guru Meditation" stays — that is the Amiga nod, which was always a separate thing from the mark.

Taking the screenshot to check it caught a real regression from the TTF console work: gfx_draw_char() still indexed the 8x16 bitmap with the TrueType cell height. font_data has 16 rows per glyph and CHAR_HEIGHT became ~21, so every line of PSOGM drew five rows of the next character's bitmap underneath itself — it looked like each line had been printed twice. The grid path (gfx_draw_cell) had been updated; this one had not, because nothing routine draws pixel-positioned text. Both now go through one draw_glyph_px(), and the bitmap's own geometry is spelled BITMAP_W/H so it cannot be confused with a cell size again.

A crash screen is only checked by looking at it, and nothing else in the system exercises gfx_text_at. Screenshot it after any font or console change: echo c > /proc/sysrq, then a QEMU monitor screendump.