OXYGENHUB
# 4c0b050e9a25 retro-remote-debug-controller / core / retro_control.h
3.7 KiB · Objective-C · last changed docs: full sweep to 0.3.0 / four platforms 3 months ago source blame history raw
961b3c61 Andy McCall 1
/* retro_control.h — portable emulator control server (see ../SPEC.md).
2
 *
3
 * A retro-platform emulator implements the small read-only backend below and
4
 * calls retro_control_start(). The shared server (retro_control.c) owns the
5
 * socket loop, HTTP parsing, PPM/JSON encoding, and control flow
4c0b050e Andy McCall ↶ 6
 * (pause / step / free-run). It always binds 127.0.0.1. Contract version is
7
 * RETRO_CONTROL_CONTRACT (below); the server advertises the highest level whose
8
 * backend callbacks are all present.
961b3c61 Andy McCall 9
 *
10
 * Integration is three calls in the emulator's main loop:
11
 *   retro_control_service();                 // once per iteration (cheap)
12
 *   if (!retro_control_running()) { idle; }  // gate advancing the machine
13
 *   ... run one instruction / frame ...
14
 *   if (frame_completed) retro_control_on_frame();
15
 *
16
 * Threading: the server runs on its own thread but never touches machine state
17
 * there. State-reading endpoints (/mem, /regs, /screenshot) are executed inside
18
 * retro_control_service() ON THE EMULATOR THREAD, so every read is consistent.
19
 * The backend callbacks are therefore called from the emulator thread (except
20
 * get_frame_count, which the server may also read for /status — make it a plain
21
 * atomic-ish counter read).
22
 */
23
#ifndef RETRO_CONTROL_H
24
#define RETRO_CONTROL_H
25
26
#include <stdint.h>
27
#include <stddef.h>
28
29
#define RETRO_CONTROL_CONTRACT "0.1.0"
30
31
/* Native framebuffer pixel layout; the server swizzles to PPM RGB. */
32
typedef enum {
33
    RETRO_PIX_RGB888 = 0,   /* 3 bytes/px: R,G,B                       */
34
    RETRO_PIX_RGBA8888,     /* 4 bytes/px: R,G,B,A                     */
35
    RETRO_PIX_BGRA8888      /* 4 bytes/px: B,G,R,A (x16 framebuffer)   */
36
} retro_pix_fmt_t;
37
38
typedef struct {
39
    const uint8_t *pixels;  /* start of the current complete frame     */
40
    int width;
41
    int height;
42
    retro_pix_fmt_t fmt;
43
} retro_framebuffer_t;
44
45
/* The emulator implements these. Any may be NULL: the matching endpoint then
46
 * returns 501 Not Implemented. */
47
typedef struct retro_control_backend {
48
    const char *platform;   /* "x16" | "neo6502" | "agon" | ...        */
49
    const char *emulator;   /* human name, e.g. "x16emu"               */
50
51
    /* Debug-read up to min(len, out_cap) bytes at addr into out, side-effect
52
     * free. bank is the optional bank selector (<0 = current bank). Returns the
53
     * number of bytes written. */
54
    uint32_t (*read_mem)(uint32_t addr, int32_t bank, uint32_t len,
55
                         uint8_t *out, uint32_t out_cap);
56
57
    /* Write a JSON object of registers into buf (NUL-terminated). */
58
    void (*get_regs_json)(char *buf, size_t cap);
59
60
    /* Report the current complete-frame framebuffer. */
61
    void (*get_framebuffer)(retro_framebuffer_t *out);
62
63
    /* Monotonic completed-frame counter. */
64
    uint64_t (*get_frame_count)(void);
65
} retro_control_backend_t;
66
67
/* Start the server thread bound to 127.0.0.1:port. Non-blocking; 0 on success,
68
 * negative on error. backend must outlive the server. */
69
int  retro_control_start(int port, const retro_control_backend_t *backend);
70
71
/* Drain a pending control request. Call once per main-loop iteration, at an
72
 * instruction/frame boundary. Cheap no-op when idle and when control is off. */
73
void retro_control_service(void);
74
75
/* Nonzero => the machine should advance this iteration. Returns 1 always when
76
 * control is off or the machine is free-running; 0 when paused with no steps
77
 * left. */
78
int  retro_control_running(void);
79
80
/* Call when a video frame completes. Drives /step (decrements the step budget,
81
 * halts and answers when it reaches zero). No-op when control is off. */
82
void retro_control_on_frame(void);
83
84
/* Stop the server (optional; process exit is fine too). */
85
void retro_control_stop(void);
86
87
#endif /* RETRO_CONTROL_H */