3.5 KiB
Size optimization backlog
Flash budget is 16 KB. Read the real usage with:
riscv-none-elf-size tama.elf # flash = text+data, RAM = data+bss
(Ignore .elf/.hex file sizes — they include debug info / ASCII framing and
are not the flashed image. tama.bin is the true image.)
Current state (after the printf removal below): ~11.9 KB / 16 KB (~73%).
DONE
✅ Drop printf/snprintf — saved ~1.4 KB
Replaced every snprintf with tiny s_cat/u_cat string builders (in tama.c),
disabled both printf backends in funconfig.h
(FUNCONF_USE_DEBUGPRINTF/FUNCONF_USE_UARTPRINTF = 0), and stubbed the SSD1306
I2C driver's lone printf with #define printf(...) ((void)0) before its include.
Result: mini_vpprintf + mini_itoa + mini_pad + _write fully garbage-collected.
Readability: neutral/positive. No behaviour change (the stubbed printf only
logged an I2C timeout we can't recover from anyway).
TODO — ranked by value vs. effort
1. Crop sprite frames — ~0.5–0.7 KB · low risk
Every creature frame is stored as 32×32 = 128 bytes, but the art only fills
roughly the middle ~28 rows; the top/bottom rows are empty padding. ssd1306_drawImage
already takes explicit width/height, so we can store shorter frames.
- How: in
sprites_gen.py, crop each frame to e.g. 32×28 (width must stay a multiple of 8; height is free). Emit the real height and adjust the drawy. - Savings: ~4 rows × 4 bytes × ~18 frames ≈ 0.3–0.7 KB.
- Readability: art stays editable as ASCII; only the generator changes.
2. Alias more Panko frames — ~0.13–0.26 KB · trivial
Shell/Tmux already reuse 4 frames across the 7 expression slots. Panko (the panda)
still has 7 distinct frames. EXP_BLINK and EXP_EAT could alias idle/happy
with little visible loss.
- How: in the
species_frames[SP_PANKO]row ofsprites_gen.py, point the blink/eat slots atpana_idle/pana_happyand delete the now-unused frames. - Savings: 128 B per dropped frame (1–2 frames).
- Readability: neutral. (Trade-off: loses the dedicated blink/eat animation.)
3. Table-drive the beep jingles — ~0.1–0.2 KB · low risk
Many multi-call beep(...) beep(...) beep(...) sequences inline a lot of immediates.
- How: store jingles as small
{freq,ms}arrays and add aplay(jingle, n)helper; replace the inline sequences with one call each. - Savings: modest, scales with number of jingles (~8 today).
- Readability: arguably improves it (named jingles).
4. Trim the font table — up to ~1.5 KB · NOT recommended
fontdata in ssd1306.h is a full 256-char × 8-byte table = 2048 B; we only
use ASCII ~0x20–0x7A.
- Why not: requires editing the vendored
ch32v003fun/extralibs/ssd1306.h, which is fragile across library updates and hurts ease-of-use. Only worth it if we're truly out of space. If done, keep a local patched copy and document it.
5. RLE-compress sprites — ~1 KB · NOT recommended
Sprites are mostly runs of 0x00/0xFF and would compress well, but this needs a decoder in the draw path and makes the art opaque (no more ASCII editing). Net readability loss; only revisit under severe pressure.
Already optimal — don't bother
- Compiler flags: already
-Os -flto -ffunction-sections -fdata-sections -Wl,--gc-sections. GCC has no-Oz. - RAM: ~55% used, not the constraint. The 1 KB
ssd1306_bufferis mandatory (full framebuffer); don't touch.