75 lines
3.5 KiB
Markdown
75 lines
3.5 KiB
Markdown
# 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.
|