SchOS/.claude/memory/schunix-boot-splash-logo.md
Nexoniarz 57aff40228 docs: four directories, and a rule for when a thing leaves the roadmap
docs/ was ten files where a plan, a description, a guide and a bug report all
sat next to each other. It is now architecture/ (what SchOS is), plan/ (what it
will be), guides/ (how to work on it) and history/ (why it is like this), with
an index that states the one rule holding it together: when something is
finished it moves from plan/ to architecture/ and is rewritten as a description
of the thing rather than a record of building it.

A ticked checkbox says the work happened. It does not say what the work
*produced*, and six months later the checkbox is all that is left. The network
stack proved the point: finished, verified end to end, and for a month the only
description of it anywhere was a checkbox four levels of indentation deep.

So roadmap.md went from 534 lines to 181 -- nothing deleted, the done work
graduated. Seven subsystems that were finished and undescribed now have
descriptions: boot, kernel, syscalls, filesystem, networking, graphics, usb,
init. Every one ends with "What it does not do", which is the section that pays;
a document listing only strengths is marketing, and the reader who needs it most
is the one about to trip over a limitation nobody wrote down.

schfs.md still opened with "phases 1 through 3 1/2 are done, phase 4 is next"
long after all five had landed. It is a description now, with the phase record
and the hard-won bugs moved to history/.

Three corrections found on the way, all load-bearing:

  * projects/schcom/README.md claimed SCM_RIGHTS was done. There is no
    sendmsg/recvmsg in the kernel at all, and an entire GUI plan rested on it.
  * The root README said "No TCP/IP" months after the stack landed.
  * history/kernel.md sec.7 was marked "in progress" on a problem that process
    groups solved.

Also adds plan/1.0.md, which draws a finish line so the open list stops being
infinite, and marks schwm/ and schde/ superseded: in Wayland the compositor is
the window manager, so that split dissolves rather than being abandoned.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
2026-09-12 17:13:35 +02:00

61 lines
3.6 KiB
Markdown

---
name: schunix-boot-splash-logo
description: "The boot logo pipeline, why the loader draws it rather than the kernel, and the STAGE2_SECTORS trap that consolidating it exposed."
metadata:
node_type: memory
type: project
originSessionId: 9d8a2aef-bcf0-47a0-96c6-f706efab4a95
modified: 2026-08-08T12:04:49.027Z
---
The boot splash shows the `Assets/Schunix Small Logo.png` mark (an SX monogram in
a ring) above the `S C H U N I X` wordmark and its accent rule, all centred as
one group. Verified rendering correctly on 2026-08-08.
**The logo is drawn by the bootloader, not the kernel.** This is the
counter-intuitive part and it is a timing fact, not a preference: the kernel does
not reach `vga_init()` until roughly the last 300ms of a ~2.8s boot, so a
kernel-drawn logo appeared for about one frame before `console_takeover()` wiped
it. Drawn from `splash()` in `boot/stage2main.c` it is up for the whole boot.
`kernel/dev/vga.c` keeps the same drawing code against the same mask
(`vga_draw_logo`, `vga_logo_centered`) for things that want the mark *after*
boot — the crash screen, eventually `schinit`. Don't "fix" the duplication by
deleting the loader's copy.
**Pipeline:** `tools/mklogo.py` (host Python, has its own PNG inflate +
un-filter) crops to the mark, box-downscales, normalises to full strength, packs
to a 4-bit coverage mask, and writes `include/logo.h`. Run `make logo` — it is
*not* a build dependency, and `include/logo.h` is committed, on the same
reasoning as `include/font.h`. The mask is coverage, not colour, so the palette
stays in [[schunix-console-tty]]'s `include/theme.h`; the loader composites it in
`SCH_FG` because the source art is a silver gradient and the accent is reserved
for the one rule. 4 bits rather than 8 because the header is included by the
*bootloader*, where size is a boot constraint.
**`STAGE2_SECTORS` was encoded in five places, not the three `docs/guides/layout.md`
claimed.** Raising it 24 → 48 to fit the 8 KiB mask proved it: the `dd seek=25`
offset stayed behind and the kernel got written straight over stage2's tail.
The five were `boot/bootasm.S`, `boot/stage2main.c`, the `dd seek=`, and *twice*
inside `tools/mkiso.sh` (its size assertion and `-boot-load-size`). It now lives
only in the root Makefile, which passes `-DSTAGE2_SECTORS` and exports it to
mkiso; the `#define`s left in the boot sources are `#ifndef` fallbacks. Hard
ceiling is 65 sectors — stage2 loads at `0x7E00` and must not reach the
multiboot kernel-search buffer at `0x10000` — and `stage2main.c` now
static-asserts that. See also [[schunix-iso-boot]].
**`tools/splashshot.ps1`** captures a burst of QEMU screendumps across early
boot and reports each frame's distinct-colour count, because the splash window
is too short to hit with a single guessed delay. It uses `-snapshot` plus
`file.locking=off` so it runs while an interactive QEMU has the images open —
booting from copies also works but means duplicating all 153 MB of
`build/fs.img` per run. Colour counts are the
assertion: ~2 means text console or blank, 18 means the 4bpp logo is up. If it
ever reads 156 again, something is drawing an 8-bit mask.
**Two traps, both hit while doing this:**
- `$(shell expr $(N) \* 512)` in a Makefile does not work — make passes the
backslash through, sh globs the `*`, and expr receives a directory listing.
Make silently carries on with nonsense. Use `$$(( ))` in the recipe.
- `make iso` was failing when this was written, for unrelated reasons since
fixed — see [[schunix-ramdisk-root-sizing]]. `-boot-load-size 49` is now
verified: the ISO boots from optical media only.