diff options
| author | gbc dev <gbc@localhost> | 2026-07-15 23:44:28 +0200 |
|---|---|---|
| committer | gbc dev <gbc@localhost> | 2026-07-15 23:44:28 +0200 |
| commit | 24a015ff047d4b7bb955ba4bc61d5793d7492878 (patch) | |
| tree | ebaf323a5c530400c81f9ce13db828e9bf6b35e1 /slop_drive.sh | |
| parent | control: video frame capture + deterministic input-movie replay (diff) | |
| download | sl0pboy-24a015ff047d4b7bb955ba4bc61d5793d7492878.tar.gz sl0pboy-24a015ff047d4b7bb955ba4bc61d5793d7492878.tar.xz sl0pboy-24a015ff047d4b7bb955ba4bc61d5793d7492878.zip | |
serial: headless mode tying serial port to stdio for OS debugging
- --headless: no rendering/TUI; serial TX -> stdout, RX <- stdin (nonblocking)
- generalize serial: serial_out_fd/serial_in_fd on the GB; internal-clock
transfer now shifts in a real RX byte (from stdin) instead of always 0xFF
- paced to native speed by default, --uncapped for turbo; pipes/scripts cleanly
- README: document headless serial console
Diffstat (limited to 'slop_drive.sh')
| -rw-r--r-- | slop_drive.sh | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/slop_drive.sh b/slop_drive.sh new file mode 100644 index 0000000..3ca019d --- /dev/null +++ b/slop_drive.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# Robust driver for the SL0P menu: verify each state transition via WRAM +# sidechannels before sending more input, instead of racing the menu poll. +# sidechannels: +# 0xCFCA wUpdateSpritesEnabled : 01 = overworld, ff = SL0P menu / EXPLORE / saver +# 0xCC26 wCurrentMenuItem : menu cursor index (valid while a menu is open) +# 0xD35D wCurMap 0xD360 wYCoord 0xD361 wXCoord +SOCK=$(./gbctl list | grep -o 'sock=[^ ]*' | cut -d= -f2) +rd(){ ./gbctl read "$1" "${2:-1}" | cut -d' ' -f5- | tr -d ' '; } +# reliable sidechannels: player sprite present in OAM => overworld; the "SL0P +# MENU" title glyph at wTileMap(5,0)=0xC3A5 == 0x92 ('S') => the SL0P menu is up. +# (wUpdateSpritesEnabled is NOT reliable: the top menu leaves it at 01.) +in_ow(){ [ "$(rd 0xC300 1)" != "00" ]; } +menu_up(){ [ "$(rd 0xC3A5 1)" = "92" ]; } +cursor(){ printf '%d' "0x$(rd 0xCC26 1)"; } + +# back out to the overworld (press B until the player sprite is drawn again) +reset_ow(){ + for _ in $(seq 1 10); do + in_ow && return 0 + ./gbctl press b:6 >/dev/null; sleep 0.5 + done + echo "reset_ow: FAILED" >&2; return 1 +} + +# confirm we're actually in the overworld and idle (coords stable across a beat) +wait_ow(){ + for _ in $(seq 1 40); do + if in_ow; then + a=$(rd 0xD360); sleep 0.25; b=$(rd 0xD360) + [ "$a" = "$b" ] && { echo "overworld ready: map=$(rd 0xD35D) Y=$(rd 0xD360) X=$(rd 0xD361)"; return 0; } + fi + sleep 0.25 + done + echo "wait_ow: FAILED" >&2; return 1 +} + +# open the SL0P menu (hold SELECT, verify via the title glyph, retry if not) +open_menu(){ + for _ in $(seq 1 12); do + menu_up && { echo "menu open"; return 0; } + ./gbctl press select:6 >/dev/null; sleep 0.6 + done + echo "open_menu: FAILED" >&2; return 1 +} + +# move the menu cursor to index $1, one press at a time, verifying each step +menu_to(){ + local target=$1 c + for _ in $(seq 1 50); do + c=$(cursor) + [ "$c" -eq "$target" ] && { echo "cursor=$target"; return 0; } + if [ "$c" -lt "$target" ]; then ./gbctl press down:4 >/dev/null; else ./gbctl press up:4 >/dev/null; fi + sleep 0.4 + done + echo "menu_to: FAILED (cursor=$c want $target)" >&2; return 1 +} + +# press A on the current menu item +menu_select(){ ./gbctl press a:5 >/dev/null; sleep 0.9; } |
