aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md48
1 files changed, 48 insertions, 0 deletions
diff --git a/README.md b/README.md
index 80151c4..b93446d 100644
--- a/README.md
+++ b/README.md
@@ -153,9 +153,57 @@ or decimal; **memory bytes are hex** (so `read` output feeds straight back into
| `delete <0xaddr\|#idx\|all>` | remove a breakpoint |
| `watch <addr>` | value-change watchpoint on a byte (no arg lists) |
| `unwatch <0xaddr\|#idx\|all>`| remove a watchpoint |
+| `record start <path> [everyN]` | capture frames to `<path>` (1 of every N); build a GIF with `tools/gbgif.py` |
+| `record stop` | finish the capture (replies with the frame count) |
+| `record` (`status`) | report whether a capture is active |
+| `input play <path> [reset]` | replay a synthesized input movie (frame-locked); `reset` = replay from a clean power-on |
+| `input stop` | stop movie playback (releases all buttons) |
+| `input` (`status`) | report movie playback state |
| `quit` | shut the emulator down |
| *(any button tokens)* | same vocabulary as the FIFO (tap/hold/release) |
+### Video capture & input replay (demo GIFs)
+
+Capture the RGB framebuffer to a flat file and turn it into a GIF:
+
+```
+./gbctl record start /abs/out.gbv 2 # capture 1 of every 2 frames (~30fps)
+...
+./gbctl record stop
+python3 tools/gbgif.py out.gbv out.gif --scale 3
+```
+
+Drive the ROM from a **synthesized input movie** instead of live input, for
+reproducible demos. A movie is a text file of `<frames> [buttons...]` lines
+(`a b start select up down left right`; none/`-` = released); the emulator
+applies one line's worth of joypad state per emulated frame, so replay is
+deterministic. Build one by hand or with `tools/gbmovie.py`:
+
+```python
+from gbmovie import Movie
+m = Movie()
+m.wait(340) # boot splash + fastboot -> overworld
+m.hold("select", 8) # open the SL0P menu
+m.tap("down", repeat=13) # cursor to the last item
+m.hold("a", 6); m.wait(600)
+m.save("demo.gbmv")
+```
+
+`input play <path> reset` gives a clean, repeatable power-on (keeps cart
+ROM+SRAM, zeroes all other state), so a movie replays byte-identically every
+time. For a frame-exact demo GIF, arm both while paused so they start on the
+same frame:
+
+```
+./gbctl pause
+./gbctl input play /abs/demo.gbmv reset
+./gbctl record start /abs/demo.gbv 2
+./gbctl continue
+... # let the movie play
+./gbctl record stop
+python3 tools/gbgif.py demo.gbv demo.gif --scale 3 --start 172
+```
+
When free-running (`continue`) hits a breakpoint or watchpoint, every connected
client receives an async line and the machine pauses: