Skip to content

Commit d2c4c2d

Browse files
committed
TheDraw-font splash; fix startup stall and phonebook write-on-every-launch
Splash Replaces the pre-login rotating cube with the product name in TheDraw fonts: four copies drifting independently at real stereo depth, each respawning in a new random font. Plain C2D over the CP437 atlas rather than the citro3d scene layer, which stays reserved for BBS content. Only the finished renderings ship, never the fonts — 206 of them in ~95KB. assets/gen_tdf_splash.py parses a .tdf collection at build time and emits cell grids, so the console needs no TDF parser and no font files on the card. Over half the library cannot render the name: TheDraw indexes ASCII 33..126 through a 94-entry offset table and a great many mark the digits absent (0xFFFF), so 1867 of 3474 fonts are dropped — without the filter they silently render "D BBS". The collections also ship greyscale "silver" variants beside the colour originals, which made the splash drab; those are scored at bake time and tinted at runtime by multiplying a hue through their grey levels, keeping the shading characters intact instead of excluding the fonts. Two things that had to be got right: placement is chosen in screen space and divided back out by depth, because multiplying world-space offsets by perspective collapses every far spawn onto the vanishing point (banners appeared bunched centre-screen whatever range they were given); and the 3D slider hands out iod in 0..1/3, not 0..1, so a pixel constant multiplied by it directly was worth about three pixels of disparity — a flat animation with a scale ramp. Fix: every launch rewrote phonebook.txt half a second in ensureLocalTest() called markDirty() unconditionally, so pbTick flushed the whole file 30 frames after start — a blocking SD write on the main thread, landing on top of the splash animation, with nothing changed. Now it marks dirty only when an entry, a migration or the v2 marker actually changed. migrateDefaults() reports whether it did anything. Also added `mx` to the perf overlay: the longest single frame since the last report. A frame-time average hides exactly this kind of one-off stall. Docs README gains the splash section and drops the "works once public" caveat on the install QR now that the repository is public; DESIGN.md 7.7 records the projection and disparity mistakes so they are not repeated.
1 parent b9c0819 commit d2c4c2d

10 files changed

Lines changed: 5169 additions & 16 deletions

File tree

DESIGN.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,26 @@ drawing when its vertex buffer fills and an overflowing GPU command buffer
297297
svcBreaks outright, so raising the clamp means raising both buffers with
298298
it. Hand-edited `size` fields are clamped on load rather than trusted.
299299

300+
## 7.7 Pre-login splash
301+
302+
The splash draws the product name in TheDraw fonts as plain C2D over the
303+
CP437 atlas, deliberately *not* through the citro3d scene layer — that stays
304+
reserved for BBS-driven content, and a splash has no business competing for
305+
it. Fonts are parsed by `assets/gen_tdf_splash.py` at build time and baked
306+
as cell grids (`source/gfx/tdf_splash_data.c`), so no TDF parser ships.
307+
308+
Two non-obvious things, both learned the hard way:
309+
310+
- **Position must be chosen in screen space, then divided by depth.**
311+
Picking world-space x/y and multiplying by perspective on the way out
312+
collapses every far spawn onto the vanishing point, so banners appear
313+
bunched in the centre no matter how wide the spawn range is. Relatedly,
314+
`FOCAL` is large relative to the depth range: a short focal length makes
315+
that collapse severe.
316+
- **The 3D slider hands you `iod` in 0..1/3, not 0..1.** Multiplying a
317+
pixel constant by it directly produced about three pixels of disparity —
318+
a flat animation with a scale ramp. It is normalised before use.
319+
300320
## 8. Roadmap
301321

302322
- **Phase 0 — scaffold:** toolchain install, hello-triangle + hello-sockets .3dsx running in Azahar

README.md

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ release over the air (CFW required):
2222
The QR points at
2323
`https://github.com/hmderdoc/3dBBS/releases/latest/download/3dBBS.cia`,
2424
which always resolves to the newest release — it never needs regenerating.
25-
(Note: works once the repository is public; private release assets require
26-
authentication that FBI can't provide.)
2725

2826
## Documentation
2927

@@ -156,6 +154,35 @@ keys are accepted without verification in v1: the wire is encrypted, but
156154
the far end is not authenticated yet (TOFU pinning is a TODO). Builds
157155
without libssh2 fail SSH dials cleanly.
158156

157+
## Splash screen
158+
159+
Before you dial, the top screen shows the product name rendered in
160+
**TheDraw fonts** — the ANSI-scene bitmap fonts BBSes have used for banner
161+
art since the early 90s — with four copies drifting independently through
162+
3D space at real stereo depth, each respawning in a new random font.
163+
164+
Only the finished renderings are compiled in, never the fonts: 206 of them
165+
in about 95 KB. `assets/gen_tdf_splash.py` parses a `.tdf` collection at
166+
build time (Synchronet's `ctrl/tdfonts/` is the canonical one) and emits
167+
`source/gfx/tdf_splash_data.c` as CP437 cell grids, so the console needs no
168+
TDF parser and no font files on the SD card. Regenerate with a different
169+
string via `--text`.
170+
171+
Two things that shaped the result and are worth knowing if you re-run it:
172+
173+
- **Over half the library can't render the name.** TheDraw fonts index
174+
ASCII 33..126 through a 94-entry offset table, and a great many mark the
175+
digits absent (`0xFFFF`). "3D BBS" needs a `3`, so 1,867 of 3,474 fonts
176+
are unusable and are dropped — without that filter they silently render
177+
"D BBS".
178+
- **The collections ship greyscale "silver" variants** beside the colour
179+
originals, and they made the splash look drab. Each banner is scored for
180+
colour at bake time; the monochrome ones get a random hue multiplied
181+
through their grey levels at runtime, which keeps the `░▒▓█` shading
182+
intact rather than dropping those fonts.
183+
184+
Font credits are in [assets/TDF-FONTS-CREDITS.md](assets/TDF-FONTS-CREDITS.md).
185+
159186
## Terminal size
160187

161188
Each board carries its own geometry, because boards disagree: some draw for
@@ -233,7 +260,7 @@ JIT streaming, sixel with correct scroll/overwrite lifetime, 3D scene
233260
protocol v1, text depth layers (protocol 0.3 — terminal text at real stereo
234261
depths, PROTOCOL.md §7), three-thread architecture (net+render / APC worker /
235262
SD flush), telnet/rlogin/SSH, per-board terminal geometry, effective-speed
236-
readout, lid-close keepalive, RGB LED data indicator.
263+
readout, lid-close keepalive, RGB LED data indicator, TheDraw-font splash.
237264

238265
Dev builds (`make`) include scaffolding: perf overlay, UDP telemetry
239266
beacon, L-button test probe, `LocalTest`/`FL-Proxy` phonebook entries with

assets/TDF-FONTS-CREDITS.md

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# TheDraw font credits
2+
3+
The pre-login splash renders the product name in TheDraw
4+
(`.tdf`) fonts drawn by ANSI-scene artists, mostly in the
5+
1990s. Only the finished renderings of one string are
6+
compiled in (see `assets/gen_tdf_splash.py`); no font file
7+
is redistributed.
8+
9+
Fonts come from the collection shipped with Synchronet
10+
(`ctrl/tdfonts/` in SynchronetBBS/sbbs), which is where
11+
the artwork has been redistributed for decades. Font names
12+
are as recorded in each file's header; where a name carries
13+
an artist or group tag it is preserved verbatim.
14+
15+
If you are an author here and want a font removed, open an
16+
issue and it will be dropped from the next release.
17+
18+
| Font | Source file | Size |
19+
|---|---|---|
20+
| HgSierraTC | hgsierax.tdf | 11x4 |
21+
| City Blue | cityx.tdf | 17x5 |
22+
| LINE!Limpy | limpyset.tdf | 12x6 |
23+
| DescentSmBlu | descntsx.tdf | 27x7 |
24+
| Darrell | darrell.tdf | 22x8 |
25+
| Supreme Cyan | suprem2x.tdf | 22x9 |
26+
| Breach Blue | breachx.tdf | 30x10 |
27+
| Cybercrime | cybrcrme.tdf | 27x11 |
28+
| Crossroads B | crosroax.tdf | 17x12 |
29+
| HgSierraTG | hgsierax.tdf | 11x4 |
30+
| City Cyan | cityx.tdf | 17x5 |
31+
| STAMPBR | stampx.tdf | 29x6 |
32+
| DescentSmCya | descntsx.tdf | 27x7 |
33+
| Darrell Cyan | darrellx.tdf | 22x8 |
34+
| Supreme Gree | suprem2x.tdf | 22x9 |
35+
| Breach Green | breachx.tdf | 30x10 |
36+
| Hemi | hemi.tdf | 27x11 |
37+
| Crossroads C | crosroax.tdf | 17x12 |
38+
| HgSierraTP | hgsierax.tdf | 11x4 |
39+
| City Green | cityx.tdf | 17x5 |
40+
| STAMPRED | stampx.tdf | 29x6 |
41+
| DescentSmGre | descntsx.tdf | 27x7 |
42+
| Darrell Gree | darrellx.tdf | 22x8 |
43+
| Supreme Purp | suprem2x.tdf | 22x9 |
44+
| Breach Marge | breachx.tdf | 30x10 |
45+
| ThievesSmall | thievsml.tdf | 35x11 |
46+
| Crossroads G | crosroax.tdf | 17x12 |
47+
| HgSierraTR | hgsierax.tdf | 11x4 |
48+
| City Purple | cityx.tdf | 17x5 |
49+
| STAMPUR | stampx.tdf | 29x6 |
50+
| DescentSmPur | descntsx.tdf | 27x7 |
51+
| Darrell Purp | darrellx.tdf | 22x8 |
52+
| Supreme Red | suprem2x.tdf | 22x9 |
53+
| Breach Purpl | breachx.tdf | 30x10 |
54+
| Thieves1ShB | thivsmlx.tdf | 35x11 |
55+
| Crossroads P | crosroax.tdf | 17x12 |
56+
| HgSierraTS | hgsierax.tdf | 11x4 |
57+
| City Red | cityx.tdf | 17x5 |
58+
| Blocktronics | blcktrnc.tdf | 31x6 |
59+
| DescentSmRed | descntsx.tdf | 27x7 |
60+
| Darrell Red | darrellx.tdf | 22x8 |
61+
| Supreme Silv | suprem2x.tdf | 22x9 |
62+
| Breach Red | breachx.tdf | 30x10 |
63+
| Thieves1ShC | thivsmlx.tdf | 35x11 |
64+
| Crossroads R | crosroax.tdf | 17x12 |
65+
| SCD-Lines Cy | scd-l2x.tdf | 12x4 |
66+
| City Silver | cityx.tdf | 17x5 |
67+
| Crimering Cy | crimrinx.tdf | 31x6 |
68+
| DescentSmSil | descntsx.tdf | 27x7 |
69+
| Falcons Blue | falconsx.tdf | 25x8 |
70+
| Nation Blue | nationx.tdf | 23x9 |
71+
| Breach Silve | breachx.tdf | 30x10 |
72+
| Thieves1ShG | thivsmlx.tdf | 35x11 |
73+
| Crossroads S | crosroax.tdf | 17x12 |
74+
| SCD-Lines Gr | scd-l2x.tdf | 12x4 |
75+
| Nightmare | nghtmare.tdf | 21x5 |
76+
| Crimering Gr | crimrinx.tdf | 31x6 |
77+
| Font 48 Sols | font48.tdf | 32x7 |
78+
| Falcons Gree | falconsx.tdf | 25x8 |
79+
| Nation Cyan | nationx.tdf | 23x9 |
80+
| Unchained Cy | unchainx.tdf | 32x10 |
81+
| Thieves1ShP | thivsmlx.tdf | 35x11 |
82+
| SKINNY!Limpy | limpyset.tdf | 22x12 |
83+
| SCD-Lines Pu | scd-l2x.tdf | 12x4 |
84+
| Psycho Neuro | psyneuro.tdf | 21x5 |
85+
| Crimering Pu | crimrinx.tdf | 31x6 |
86+
| AfterHoursB | aftrhoux.tdf | 33x7 |
87+
| Falcons Marg | falconsx.tdf | 25x8 |
88+
| Nation Green | nationx.tdf | 23x9 |
89+
| Unchained Gr | unchainx.tdf | 32x10 |
90+
| Thieves1ShS | thivsmlx.tdf | 35x11 |
91+
| Euphoria Blu | euphorix.tdf | 28x12 |
92+
| SCD-Lines Re | scd-l2x.tdf | 12x4 |
93+
| Atom Blue | atomx.tdf | 22x5 |
94+
| Crimering Re | crimrinx.tdf | 31x6 |
95+
| AfterHoursG | aftrhoux.tdf | 33x7 |
96+
| Falcons Purp | falconsx.tdf | 25x8 |
97+
| Nation Purpl | nationx.tdf | 23x9 |
98+
| Unchained Pu | unchainx.tdf | 32x10 |
99+
| KissMy | kissmy.tdf | 37x11 |
100+
| Euphoria Gre | euphorix.tdf | 28x12 |
101+
| SCD-Lines | scd-line.tdf | 13x4 |
102+
| Atom Cyan | atomx.tdf | 22x5 |
103+
| Crimering Si | crimrinx.tdf | 31x6 |
104+
| AfterHoursM | aftrhoux.tdf | 33x7 |
105+
| Falcons Red | falconsx.tdf | 25x8 |
106+
| Nation Red | nationx.tdf | 23x9 |
107+
| Unchained Re | unchainx.tdf | 32x10 |
108+
| Kiss My ...C | kissmyx.tdf | 37x11 |
109+
| Euphoria Mar | euphorix.tdf | 28x12 |
110+
| Cartoon | cartoon.tdf | 17x4 |
111+
| Atom Green | atomx.tdf | 22x5 |
112+
| BrickFntBlu | brickx.tdf | 32x6 |
113+
| AfterHoursO | aftrhoux.tdf | 33x7 |
114+
| Font 81 Cyan | font81x.tdf | 32x8 |
115+
| Nation Silve | nationx.tdf | 23x9 |
116+
| Unchained Si | unchainx.tdf | 32x10 |
117+
| Kiss My ...G | kissmyx.tdf | 37x11 |
118+
| Euphoria Pur | euphorix.tdf | 28x12 |
119+
| Review | review.tdf | 17x4 |
120+
| Atom Purple | atomx.tdf | 22x5 |
121+
| BrickFntBrn | brickx.tdf | 32x6 |
122+
| AfterHoursP | aftrhoux.tdf | 33x7 |
123+
| Font 81 Gree | font81x.tdf | 32x8 |
124+
| Resistance 2 | resista2.tdf | 26x9 |
125+
| CrestColBlu | crestclx.tdf | 37x10 |
126+
| Kiss My ...P | kissmyx.tdf | 37x11 |
127+
| Euphoria Red | euphorix.tdf | 28x12 |
128+
| ExplorationB | explorax.tdf | 22x4 |
129+
| Atom Red | atomx.tdf | 22x5 |
130+
| BrickFntCyn | brickx.tdf | 32x6 |
131+
| AfterHoursR | aftrhoux.tdf | 33x7 |
132+
| Font 81 Purp | font81x.tdf | 32x8 |
133+
| Evolution Br | evolutx.tdf | 31x9 |
134+
| CrestColCyn | crestclx.tdf | 37x10 |
135+
| Kiss My ...R | kissmyx.tdf | 37x11 |
136+
| Pandemonium | pandemon.tdf | 35x12 |
137+
| ExplorationC | explorax.tdf | 22x4 |
138+
| Atom Silver | atomx.tdf | 22x5 |
139+
| BrickFntGrn | brickx.tdf | 32x6 |
140+
| AfterHoursS | aftrhoux.tdf | 33x7 |
141+
| Font 81 Red | font81x.tdf | 32x8 |
142+
| Evolution Cy | evolutx.tdf | 31x9 |
143+
| CrestColGrn | crestclx.tdf | 37x10 |
144+
| Kiss My ...S | kissmyx.tdf | 37x11 |
145+
| Phiber2 | phiber2.tdf | 37x12 |
146+
| ExplorationG | explorax.tdf | 22x4 |
147+
| Font 11 | font11.tdf | 22x5 |
148+
| BrickFntPpl | brickx.tdf | 32x6 |
149+
| Font 77 | font77.tdf | 36x7 |
150+
| Font 81 Silv | font81x.tdf | 32x8 |
151+
| Evolution Gr | evolutx.tdf | 31x9 |
152+
| CrestColPpl | crestclx.tdf | 37x10 |
153+
| Prophecy | prophecy.tdf | 37x11 |
154+
| Obsession Sh | obsesss.tdf | 42x12 |
155+
| ExplorationP | explorax.tdf | 22x4 |
156+
| Font 8 | font8.tdf | 22x5 |
157+
| BrickFntRed | brickx.tdf | 32x6 |
158+
| Blow Torch G | blwtorcx.tdf | 37x7 |
159+
| Font 84 Blue | font84x.tdf | 32x8 |
160+
| Evolution Pu | evolutx.tdf | 31x9 |
161+
| CrestColRed | crestclx.tdf | 37x10 |
162+
| Underground | undrgrnd.tdf | 37x11 |
163+
| Channel Blue | channelx.tdf | 44x12 |
164+
| ExplorationR | explorax.tdf | 22x4 |
165+
| Stupid Cyan | stupidx.tdf | 22x5 |
166+
| BrickFntSlv | brickx.tdf | 32x6 |
167+
| Blow Torch M | blwtorcx.tdf | 37x7 |
168+
| Font 84 Brow | font84x.tdf | 32x8 |
169+
| Evolution Re | evolutx.tdf | 31x9 |
170+
| CrestColSlv | crestclx.tdf | 37x10 |
171+
| Unknown Blue | unknownx.tdf | 37x11 |
172+
| Channel Cyan | channelx.tdf | 44x12 |
173+
| ExplorationS | explorax.tdf | 22x4 |
174+
| Stupid Green | stupidx.tdf | 22x5 |
175+
| Tower2 | tower2.tdf | 32x6 |
176+
| Blow Torch P | blwtorcx.tdf | 37x7 |
177+
| Font 84 Cyan | font84x.tdf | 32x8 |
178+
| Argdn Blue | armagdnx.tdf | 32x9 |
179+
| LostSouls | lstsouls.tdf | 37x10 |
180+
| Unknown Gray | unknownx.tdf | 37x11 |
181+
| Channel Gree | channelx.tdf | 44x12 |
182+
| Memory Blue | memoryx.tdf | 22x4 |
183+
| Stupid Purpl | stupidx.tdf | 22x5 |
184+
| DevelopBlu | developx.tdf | 33x6 |
185+
| Blow Torch R | blwtorcx.tdf | 37x7 |
186+
| Font 84 D Cy | font84x.tdf | 32x8 |
187+
| Argdn Cyan | armagdnx.tdf | 32x9 |
188+
| Outpost 2 | outpost2.tdf | 37x10 |
189+
| Unknown Gree | unknownx.tdf | 37x11 |
190+
| Channel Purp | channelx.tdf | 44x12 |
191+
| Memory Green | memoryx.tdf | 22x4 |
192+
| Stupid Red | stupidx.tdf | 22x5 |
193+
| DevelopGre | developx.tdf | 33x6 |
194+
| Blow Torch S | blwtorcx.tdf | 37x7 |
195+
| Font 84 D Gr | font84x.tdf | 32x8 |
196+
| Argdn Fire | armagdnx.tdf | 32x9 |
197+
| Sanitarium B | sanitarx.tdf | 37x10 |
198+
| Unknown Mage | unknownx.tdf | 37x11 |
199+
| Channel Red | channelx.tdf | 44x12 |
200+
| Memory Marge | memoryx.tdf | 22x4 |
201+
| Stupid Silve | stupidx.tdf | 22x5 |
202+
| DevelopMar | developx.tdf | 33x6 |
203+
| Digit Cyan | digitx.tdf | 37x7 |
204+
| Font 84 D Pu | font84x.tdf | 32x8 |
205+
| Argdn Gray | armagdnx.tdf | 32x9 |
206+
| Sanitarium G | sanitarx.tdf | 37x10 |
207+
| Unknown Purp | unknownx.tdf | 37x11 |
208+
| Channel Silv | channelx.tdf | 44x12 |
209+
| Memory Purpl | memoryx.tdf | 22x4 |
210+
| Blender 1 Cy | blendr1x.tdf | 25x5 |
211+
| DevelopOrg | developx.tdf | 33x6 |
212+
| Digit Green | digitx.tdf | 37x7 |
213+
| Font 84 D Re | font84x.tdf | 32x8 |
214+
| Argdn Green | armagdnx.tdf | 32x9 |
215+
| Sanitarium P | sanitarx.tdf | 37x10 |
216+
| Unknown Red | unknownx.tdf | 37x11 |
217+
| Syndrome | syndrome.tdf | 45x12 |
218+
| Memory Red | memoryx.tdf | 22x4 |
219+
| Blender 1 Gr | blendr1x.tdf | 25x5 |
220+
| DevelopPur | developx.tdf | 33x6 |
221+
| Digit Purple | digitx.tdf | 37x7 |
222+
| Font 84 Gree | font84x.tdf | 32x8 |
223+
| Argdn Purple | armagdnx.tdf | 32x9 |
224+
| Sanitarium R | sanitarx.tdf | 37x10 |
225+
| Memory Silve | memoryx.tdf | 22x4 |

0 commit comments

Comments
 (0)