Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Virtual Terminal as UART backend #103

Open
ghost opened this issue Jun 28, 2023 · 4 comments
Open

Virtual Terminal as UART backend #103

ghost opened this issue Jun 28, 2023 · 4 comments
Labels
enhancement New feature or request

Comments

@ghost
Copy link

ghost commented Jun 28, 2023

Hello I'd like to add VT support to RVVM.

Exact requirements

I think it should:

  • compatible with TERM=xterm, with a good score from vttest, https://www.invisible-island.net/vttest/
  • takeover fb_window for 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:

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?

@ghost ghost added the enhancement New feature or request label Jun 28, 2023
@LekKit
Copy link
Owner

LekKit commented Jun 28, 2023

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/ or src/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

@ghost
Copy link
Author

ghost commented Jul 1, 2023

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? 🤔

@LekKit
Copy link
Owner

LekKit commented Jul 1, 2023

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.

@ghost
Copy link
Author

ghost commented Jul 26, 2023

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...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant