RVVM
RVVM copied to clipboard
Virtual Terminal as UART backend
Hello I'd like to add VT support to RVVM.
Exact requirements
I think it should:
- compatible with
TERM=xterm, with a good score fromvttest, https://www.invisible-island.net/vttest/ - takeover
fb_windowfor input/output, a keyboard shortcut can be used to switch between VT and original mode - support UTF-8, has built-in font for ASCII, can load external font file for CJK etc.
- maybe color support, so compatible with
TERM=xterm-256color - maybe bold and itatic support, with seperated font files
Suggested solution
My current plan are:
-
use
libvtermfor VT emulation, can be switch out later.. -
support
pcbasic / hexfont format, pre-made (.hex) fonts: https://github.com/robhagemans/pcbasic/tree/master/pcbasic/data/fonts tools: https://github.com/robhagemans/monobit -
implement a
chardevVT backend, withfb_windowtakeover and switch logic
Expected results and side effects
The showcase can be TERM=xterm-mono emacs -nw running in OpenBSD editing UTF-8 text, via RetroArch...
How does this sound?
Very good idea, some more things I'd love to add:
- Intermediate API to look at VT contents as a character array with color attributes. I need this for one of my side projects, and it also can bring proper VT state saving and VT support on older Windows hosts.
- Perhaps some way to build it in-tree without fetching separate repos or relying on lib presence in the system at build or run time (A directory like
deps/orsrc/deps/may be used) - @nebulka1 almost finished an inhouse VT100 emulation but didn't complete it, and maybe we could have some kind of authentic inhouse retro VT at some point if that work has some traction again
Very good idea, some more things I'd love to add:
- Intermediate API to look at VT contents as a character array with color attributes. I need this for one of my side projects, and it also can bring proper VT state saving and VT support on older Windows hosts.
libvterm has those:
typedef struct {
uint32_t chars[VTERM_MAX_CHARS_PER_CELL];
char width;
VTermScreenCellAttrs attrs;
VTermColor fg, bg;
} VTermScreenCell;
size_t vterm_screen_get_chars(const VTermScreen *screen, uint32_t *chars, size_t len, const VTermRect rect);
size_t vterm_screen_get_text(const VTermScreen *screen, char *str, size_t len, const VTermRect rect);
int vterm_screen_get_cell(const VTermScreen *screen, VTermPos pos, VTermScreenCell *cell);
which seems fine.
Now I'm trying to implement "input takeover" by hook hid_keyboard with:
+PUBLIC void hid_keyboard_hook(hid_keyboard_t* kb,
+ bool (*on_press)(hid_key_t key),
+ bool (*on_release)(hid_key_t key))
+{
+ kb->on_press = on_press;
+ kb->on_release = on_release;
+}
+
PUBLIC void hid_keyboard_press(hid_keyboard_t* kb, hid_key_t key)
{
bool is_input_avail = false;
+ if (kb->on_press && kb->on_press(key))
+ return;
spin_lock(&kb->lock);
// key is guaranteed to be 1 byte according to HID spec
if (key != HID_KEY_NONE) {
@@ -188,6 +204,8 @@ PUBLIC void hid_keyboard_press(hid_keyboard_t* kb, hid_key_t key)
PUBLIC void hid_keyboard_release(hid_keyboard_t* kb, hid_key_t key)
{
bool is_input_avail = false;
+ if (kb->on_release && kb->on_release(key))
+ return;
spin_lock(&kb->lock);
if (key != HID_KEY_NONE) {
kb->keys[key/32] &= ~(1U << (key%32));
So in fb_window (instead of in sdl_window, etc.) I can handle input with:
+static bool keyboard_press(hid_key_t key)
+{
+ rvvm_info("key pressed: %d", key);
+ return false; // !! return true to stop propagate event to the guest
+}
+
+static bool keyboard_release(hid_key_t key)
+{
+ rvvm_info("key released: %d", key);
+ return false;
+}
+
bool fb_window_init_auto(rvvm_machine_t* machine, uint32_t width, uint32_t height)
{
fb_window_t* window = safe_calloc(sizeof(fb_window_t), 1);
@@ -125,15 +137,17 @@ bool fb_window_init_auto(rvvm_machine_t* machine, uint32_t width, uint32_t heigh
window->machine = machine;
window->keyboard = hid_keyboard_init_auto(machine);
window->mouse = hid_mouse_init_auto(machine);
+ hid_keyboard_hook(window->keyboard, keyboard_press, keyboard_release);
Does this look reasonable? :thinking:
I think we shouldn't pollute the hid_api itself, or the actual devices (reinventing something inside the device would be bad).
What I think should be done is more refining for fb_window, it is purposed as a middle-ground between raw machine APIs (framebuffer, hid_api) and native windowing backends (SDL, X11, Win32, Haiku).
Perhaps you could implement something like gui_keypress() with same semantics as the hid call, and then translate it to whatever you like.
Okay, that gui_keypress seems more clearly to me too.
Haven't got much time to works on this yet, hope to pick this up later...