OXYGENHUB
# bed0f1e524fe retro-remote-debug-controller / CHANGELOG.md
3.6 KiB · Markdown · last changed 0.5.0: game controller injection (POST/GET /pad) 3 months ago renderedsource blame history raw
4c0b050e Andy McCall ↶ 1
# Changelog
2
3
Contract versions of the Retro Remote Debug Controller (see [SPEC.md]SPEC.md).
4
Semantic versioning: MAJOR = breaking change to an existing endpoint, MINOR =
5
additive (new endpoint / optional field), PATCH = clarification. Every minor so
6
far has been purely additive — older clients keep working, and a server
7
advertises the highest level whose backend callbacks are all present via
8
`/status.contract`.
9
bed0f1e5 Andy McCall ↶ 10
## 0.5.0
11
- `POST /pad?index=[&buttons=][&connected=]` — present a **virtual game
12
  controller** and set what is held. `buttons` is the canonical mask (bit0 LEFT,
13
  1 RIGHT, 2 UP, 3 DOWN, 4 A, 5 B, 6 X, 7 Y, 8 START, 9 SELECT, 10 L, 11 R —
14
  the SNES/Neo6502 native order, fixed across platforms). `connected=0` unplugs.
15
  Backend callback: `set_pad`.
16
- `GET /pad?index=` — read back `{index, connected, buttons}`, so a test can tell
17
  "the input never arrived" from "it arrived and was ignored". Backend callback:
18
  `get_pad`.
19
- A pad is a **level, not an event**: the held mask persists across `/step`
20
  frames until changed, unlike `/key`'s momentary tap. Conformance asserts this
21
  directly, because it is the property that makes `/pad` worth having rather
22
  than reusing `/key`.
23
- **Virtual, not SDL.** A backend presents a device its existing read path picks
24
  up rather than driving the host's joystick API. Headless CI has no joystick,
25
  and that is precisely the case this endpoint exists for.
26
- Motivation: a real bug that shipped. A port's pad read masked the firmware's
27
  merged controller down to its d-pad and tried to recover the buttons from the
28
  wrong controller index — movement worked, fire did nothing, and there was no
29
  way to catch it without a human holding hardware.
30
346ca3ee Andy McCall ↶ 31
## 0.4.0
32
- `POST /pointer?x=&y=[&buttons=]` (absolute) or `?dx=&dy=[&buttons=]` (relative)
33
  — inject a pointer move/click through the platform's native mouse path.
34
  `buttons` is a bitmask (bit0=primary, bit1=secondary); omit for a pure move.
35
  Backend callback: `set_pointer`.
36
- `GET /pointer` — read back the current pointer `{x, y, buttons}`, so a test can
37
  tell "input never arrived" from "wrong output drawn". Backend callback:
38
  `get_pointer`.
39
- First consumer: the Neo6502 fork (drives the firmware mouse), unblocking the
40
  pointer floor of the `rstar-api` RWM/RGM toolkit.
41
4c0b050e Andy McCall ↶ 42
## 0.3.0
43
- `POST /mem?addr=&bank=` — write (poke) memory; bytes in the request body,
44
  returns `{"written":n}`. Backend callback: `write_mem`.
45
- `GET /audio` — drain synthesised PCM since the last call as a self-describing
46
  WAV (the audio analogue of `/screenshot`); `X-Rrdc-Audio-Dropped` header on
47
  ring overflow. Backend callback: `capture_audio`.
48
- The NEC PC-FX (Mednafen) fork joins as the fourth conforming emulator, the
49
  second to vendor the C core as a git submodule.
50
51
## 0.2.0
52
- `POST /key?text=|code=[&down=]` — inject input (press / release / tap).
53
  Backend callback: `inject_key`.
54
- `POST /reset` — soft/cold reset. Backend callback: `reset`.
55
- Contract gating introduced: a NULL callback returns 501 for its endpoint and
56
  lowers the advertised contract, keeping partial backends honest.
57
58
## 0.1.0
59
- Initial contract: `GET /status`, `GET /screenshot` (PPM), `GET /mem`,
60
  `GET /regs`, `POST /step`, `POST /pause` / `POST /resume`.
61
- Shared C core (`core/retro_control.{c,h}`) — sockets, HTTP, PPM/JSON encoding,
62
  and cooperative pause/step, driven by three loop hooks. Backend callbacks:
63
  `read_mem`, `get_regs_json`, `get_framebuffer`, `get_frame_count`.
64
- Shared pytest client (`client/emu_control.py`) and the platform-agnostic
65
  conformance suite. Reference implementation: the Commander X16 fork.