# Size optimization backlog Flash budget is **16 KB**. Read the real usage with: ```bash 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 draw `y`. - **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 of `sprites_gen.py`, point the blink/eat slots at `pana_idle`/`pana_happy` and 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 a `play(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_buffer` is mandatory (full framebuffer); don't touch.