Kitty – a fast, featureful, GPU based terminal emulator(sw.kovidgoyal.net) |
Kitty – a fast, featureful, GPU based terminal emulator(sw.kovidgoyal.net) |
Increase background opacity ctrl+shift+a>m
There are a few pointers for Linux solutions in the issue.
I do wish creators of these tools would search for existing names to see if they are already in use. I would not mind if they were tools with sufficiently different purpose. But this just confuses users (and potential users) of either one.
I likewise thought this was KiTTY. Had to look up the actual homepage for it to confirm that I was looking at a different tool.
https://github.com/kovidgoyal/kitty/issues/9#issuecomment-41...
If this is progress... I'm not sure I want it
And the GPUs were character-based, with only 256 different characters, usually 16 colors/each. That's the main reason for the hardware requirements. Essentially, these shaders emulate a character-based fixed function GPU from 30 years ago, adding features like more colors, Unicode, and custom fonts.
Modern displays at 1920x1080 in millions of colors.
30 years ago a terminal was the whole display and nothing more. Now its a single window amid dozens of other windows including content ranging from high definition video to real-time rasterized 3D graphics.
Yes, that's progress.
VGA was introduced 31 years ago, in 1987. The text mode was 80x25 characters, 9x16 pixels/each, so the effective output resolution was 720x400 pixels. I currently develop a device with similar one, 800x480, only now I have GPU and GLES 3.2.
Back to the old times, because RAM was so expensive, that high resolution only worked in text mode, where the frame buffer only had 2 bytes per character, one for character itself, another for attributes i.e. background and foreground colors.
Graphic modes had way lower resolution, indeed.
I wish Alacritty had better scrollback, I'd give that a go as well. But for now, I am sticking to Kitty.
Data analysis and data science comes to mind.
Edit: I did some basic tests using slow motion recording on my phone, and this is how long I found it took a few terminal emulators to start: (Recorded in 240FPS)
- rxvt-unicode 33 frames
- kitty 298 frames
- lilyterm 20 frames
- sakura 55 frames
Alacritty apparently accepts input before it is able to display anything. It took 53 frames before it would take input, and 180 frames (total from startup) before it displayed anything.
but fast? on an intel haswell graphics card Im seeing input latency. Sure, its technically beautiful, but the st terminal from suckless.org is lightning fast compared to this.
update: this is on a 2015 macbook with retina running funtoo, so this may be a performance consideration specific to the hardware.
Clone it/download the .zip and replace the kitty.exe with a recent one
makes this hardly usable
https://sw.kovidgoyal.net/kitty
2. There is a resize option for text. Hell, in my experience, Kitty seems to have the most powerful font management of any terminal. See:
https://sw.kovidgoyal.net/kitty/conf.html#conf-kitty-fonts
3. That's because the machine you're SSHing into doesn't have Kitty's terminfo files. That's easily fixed by running "kitty +kitten ssh myserver" where "myserver" is the IP/domain of your server. See:
https://sw.kovidgoyal.net/kitty/faq.html#i-get-errors-about-...
I quite like Kitty compared to urxvt, which I was using before. Just looking at cmatrix, you can tell the difference. Smooth characters dropping down in kitty, sketchy 10fps on urxvt.
The only thing that bothers me is the theme being set in the config file. For urxvt, I put the theme separately in xresources and have a shell alias to change it (which then requires opening a new terminal, but that's what I use tmux for).
Maybe I can do something similar for Kitty, haven't really read the docs.
I prefer it to iTerm because it's so. Damn. Fast. It's the only software (besides Sublime) I run on my laptop that actually feels like it's using the 40 years of transistor improvements I'm paying for.
I know iTerm recently added a Metal renderer but I need ligature support, which iTerm Metal doesn't have.
Maintainer has also been responsive on GitHub.
I wish more software fell into this category. It's still a little odd to me that something as conceptually simple as a terminal emulator should require a full blown GPU in order to perform smoothly.
Yup, I was also pretty surprised by this. I switched to Kitty recently, after terminology broke for me after an update. It's surprisingly hard to find terminal emulators that run on Xorg and on Wayland without making a fuzz.
Kitty does this beautifully and I had a real a-ha moment because of its speed the first time I tried it.
One thing is, I don't get its layout, is it possible to create a vertical/horizontal split like what (shift+)cmd+d does in iTerm 2?
Ctrl-Shift-L goes through all enabled layouts. A layout specifies how the "windows" are arranged. Simple splits are available among others. I like the stacked layout: window 1 fills the full height on the left half of the screen, all other windows are stacked on the right half.
There does not seem to be a way to control the borders within the layout with the mouse; e.g. temporarily resize window 1 in the example above to be 80% of the width. That's something I sometimes miss. It's configurable, of course, but not ad hoc.
How are you attributing speed to Kitty over iTerm? Wouldn't most of the sluggishness of anything be more attributed to the programs you're running in the terminal?
I mean, I love how user friendly (meaning configuration and all) kitty is out of the box. That's how tools made by programmers for programmers should look like.
That said, kitty behaves a little weird when scrolling back and forth in vim — at least on my laptop with my vim colorscheme. It leaves out background of a line black until I jump on that specific line or simple refresh the screen. I wonder what might be the issue here.
Just look at how often a new product - like this one - is compared to existing products on HN, and how many comments are about what features other products have that are dealbreakers.
It's not new. Just one example from the 1980s is NeXTStep, which did away with the cryptic Unix directory names (/opt/sfw, /usr/ccs, /usr/mbin, /usr/rbin, /usr/5bin, and so on) in favour of /Library , /LocalLibrary , /Apps , /NextApps , and so forth.
Although it has a lot less features than kitty and really is only usable with tmux (or GNU screen, whatever), it is more or less perfect for people who want their terminal to do just one thing and that one thing pretty fast.
Disclaimer: Haven't tried kitty yet and using alacritty for a nearly a year now.
This seems to be a general issue on macOS with any terminal emulator, according to [0].
It's actually very, very slow.
It even looks like he has his own pre-jquery compliance library written about 18 years ago: https://kovidgoyal.net/scripts/VisualDocumentAPI.js
> W A R N I N G! Your browser is not supported by this site.I cannot guarantee that things will work as they should. Consider downloading either Mozilla >=1.4 or Internet Explorer >= 6
takes me back!
It would seem prudent for this kitty to consider changing it's name to help alleviate confusion.
For instance, iTerm supports italic, which Terminal.app doesn't. Gnome's terminal (vte, actually) does support overline (I volunteered adding it to iTerm, but I'm nowhere near close), which is handy for status lines, as well. I think there is one that takes ANSI codes seriously enough to support double-height and width.
To see what's missing, you can look into https://en.wikipedia.org/wiki/ANSI_escape_code
If you're a light user, probably not much.
I spend probably 2/3rds of my day at a command line, and iTerm has a ton of handy usability features that make life a little nicer. With kitchen-sink apps like this, everyone uses them differently, but things that make my life easier include:
- command-up arrow to scroll up by command - programmable appearance changing (using the server-side shell integration) to visually prompt me when I'm not my usual UID and to show machine names in the background of the window - Deeply customizable minor usability details, like the ability to copy-on-select, which I use all the time but some people hate
Nothing that is going to empower you do do things you can't now; rather just nice features that make address the quirky needs of heavy shell users.
Text rendering is basically just blitting cached glyph bitmaps into a buffer, and CPUs have been more than overly fast doing that for eons. And CPU rendering has none of the compatibility problems/quirks that GPUs have. I can fire up a Gnome Terminal onto an unaccelerated Vesa X11 display if my graphics card doesn't work or I haven't configured it yet.
For better responsivity I suppose a terminal that behaves like mosh would be a good approach. It would maintain the tty state in memory and only render the latest view, dropping the rendering of any intermediate diffs in the buffer. I would guess most terminal emulators do work like that these days but I haven't checked.
A pity, maybe some day either the author changes his mind or Alacritty will be less buggy to make it a straight upgrade to Kitty. In the meantime, Termite it is.
https://github.com/kovidgoyal/kitty/issues/106
Obviously using the truetype version (which isn't pixel perfect but a mess) is not an option.
Too bad. I'll stick to libvte (sakura).
time find ~
/dev/null takes 8 secondsalacritty takes 8.5 seconds and uses 75% CPU
kitty takes 15 seconds and uses 100% CPU
konsole takes 16 seconds and uses 100% CPU
time for i in {1..2000000}; do echo $i; done
/dev/null takes 8 secondsalacritty takes 16 seconds and uses 75% CPU
kitty takes 17 seconds and uses 100% CPU
konsole takes 16 seconds and uses 98% CPU
Locking how? He can keep his tmux configuration and use it when he needs to in the future.
I wish this were all unified into a single window/tab/keybinding model. That was easy to code against and write your own interactions for.
I keep hoping I'll see a boundary-pushing project like Kitty do something new in this space.
> I'm widely known for my extreme stupidity.
Loving the zero <expletives> given approach from the maintainer. Installing now.
> Not a smart move, imho.
a library that I can feed data directly into (without a pty)
LGPL, MIT, or BSD
able to quickly serialize its internal state (make me a blob)
able to restore state if I feed it a blob of saved state, even across different software builds
portable to recent versions of Linux and Windows
Moreover, the session state saving is not possible either since you need to save the internal state of running programs as well as their cached output (saving the output is really very easy but it's the least of your worries given the specifications you've described).
You might also find this problem is better solved with a $SHELL replacement rather than a terminal emulator.
So the emulator gets bytes from the emulated virtual machine, and then what? This needs to get fed into a terminal. While it is possible to invoke xterm with the very buggy -S option, there is no way for the emulator to suck the state back out of xterm for coherent snapshots. Simics uses xterm with the -S option. It sucks.
A library interface is required. The whole point of a library interface is to allow session state saving. Using a $SHELL replacement is way off. That has nothing to do with the problem.
So, if you were hacking on an emulator (qemu, MAME, Simics, VirtualBox, etc.) and you were trying to emulate a device with a serial port or even a modem, how would you get snapshots to contain the terminal state? To make this work, you need that state within the emulator. Passing stuff over a PTY is not going to work.
It is useful for virtual machine snapshots. You can restore the virtual machine with the terminal state intact.
Linux desktop in 2018 is incredible though. On my desktop, I'm running an RX 580 on AMD's open source drivers and I can play modern Windows games at >= 60fps using WINE + dxvk. Steam is even officially supporting it now. Just wait 2-3 years and GNU / Linux will be the way to go.
(compared to Apple's Terminal.app, which I found to be the fastest and least problematic on a Mac)
From the performance page: https://sw.kovidgoyal.net/kitty/performance.html
WSL desperately needs a good terminal.
I've switched to kitty and am much happier.
I'm not sure if Kitty is using GPU specifically to minimize latency, but it would be a good reason.
That being said I think it is valuable to have a reasonably fast terminal because it's not uncommon to have applications slow down dramatically if they output a lot of information on stdout/stderr while the terminal struggles to render everything.
It's depressing that he's only ever tried for throughput, when that's irrelevant next to latency. And it does have abysmal latency as per your link.
I've been using iterm for years; when they introduced their metal rendering backend the impact was very subtle but noticable. Anyway, given the amount of time I spend using cli stuff, it kind of matters.
Smooth scrolling is inherently bounded by the vsync rate of the display. As long as you can render the terminal's pixel buffer with new characters and send it to front for the next flip, all within some portion of the time you have between frames, it's as smooth as it can get. Missing a frame will cause stutter, and make it non-smooth. Given the fact that terminal doesn't necessarily need to render if there are no changes, using GPU seems like an overkill for regular use.
It does vaguely measure two things:
1) How big the buffer is on the terminal when it reads in lots of output. If the buffer is as big as the output then your test reports a figure close to the `/dev/null` test. Not useful.
2) How well the terminal is in SKIPPING the rendering of lots of output. No normal terminal tries to render all of the text on screen.
How long between key press and character render? That's all I care about. 24 cores and still have lag when I type. My 7mhz Amiga 500 had a more fluid GUI than modern PCs. It's disgusting.
Still, I wonder if the terminal emulators could use less CPU and be faster if they refreshed only with the frequency of the monitor.
An interesting insight from the tests is that the execution speed of a program can depend on the speed of the terminal emulator.
EDIT: alacritty took 4.15 and 54% cpu.
I should note these results are all from second runs.
But it does have a comprehensive documentation page: https://sw.kovidgoyal.net/kitty/index.html#scrolling
There's a huge configuration doc[1], and the homepage already does a very good job of introducing you to its features. You have to read that, yeah, but maybe you can get a screen reader to read it for you. Dunno.
More importantly, making a video probably takes more time that having a nice write-up about anything.
I am 26, BTW.
However, there are several behaviors that are atypical for OSX applications such as missing conventional system shortcuts and some things I consider confusing such as the fact that there are OS windows and then there are "windows" which are similar to panes in iTerm, but are not actually windows. Perhaps for other terminals or systems this is normal, but it isn't exactly par for the course for the tools I've worked with prior.
One of the best things about OSX is that every item that is available in the menu bar has a clear shortcut associated with it and a very helpful search box available via the cmd+? key combo which works as a shortcut for anything you don't happen to know the shortcut to offhand. Menus happen to be one of the fastest ways to navigate OSX with a keyboard for me. This app does not have any menus to speak of, which is fine, but it just makes it that much harder to figure things out on your own.
As for the video suggestion: some things just don't translate as well as text for me (I am legally blind: not afraid to RTFM, but sometimes reading is asking a bit more for me than others). Sometimes it's nice to see how someone else does it because it helps when you don't know how to do something on your own. Even an asciinema style demo is quite helpful for certain tools here and there.
Most of what terminals have to do is blitting of prerendered text bitmaps, which is relatively slow on CPU and does benefit from the much faster memory bandwidth of the GPU. Core Graphics generally does not use the GPU for text blitting in most Mac apps, so having a custom renderer can help here. Font rasterization on the Mac does not use the GPU either, but the glyph cache hit rate for a terminal emulator is so high that it ends up pretty much irrelevant.
On Windows, Microsoft ships multiple rendering stacks for legacy compatibility. Most terminals are old Win32 programs that use classic GDI, which as far as I know is partially accelerated but mostly CPU (and implemented in the kernel!) Direct2D, the newer API, does use the GPU for blitting text. Like macOS, Windows still does all font rasterization on CPU. In GDI, font rasterization is done on CPU in the kernel (!) (except on Windows 10, in which the kernel calls out to a userspace fontdrvhost.exe). In Direct2D, font rasterization is done on CPU in userspace.
Also kitty definitely feels snappier to me in terms of latency.
Btw I'm big fan of your games, like Link to the Past! 16-bit era was best era.
Which is odd, cause Kitty does, IIUC.
This also makes me weary of statements that criticize how e.g. windows does it wrong, “except in the current three years old version”.
EDIT/Whinging: Welp, scratch that, kitty requires an OS X one version higher than what apple will allow me to install. And while it is an older MBP from 2010, at least it's fast and reliable. AND it has the multitude of ports that I like. And the magsafe.
I'm sure I'm venting into an echo changer, but, here goes. Why won't Apple simply provide me (an option to buy) a modern solid mid-level 15" rMBP for under $2000. I bought mine for $1700 and it came with a $200 ipod as a gift (sold on eBay).
Give me that. A rMBP, with all the ports, plus the new USB-C. They could leave out some of the stuff that's pricy.
Ya, give me a new version of what I have, and will last at least another 8 years (fully supported by MacOS releases), and price it under $2000. That I would buy. When I replace this one, I'm just going to have to buy something to linux or Windows (probably both, realistically), since I've been priced out the product I would have normally purchased and recommended.
> To elaborate, the GL driver is incorrectly treating const variables in the shaders as uniforms.
That's a pretty serious bug in the driver. I might also simply refuse to work around something that colossally flawed.
And to which someone declares "not a smart move", and he said, roughly, "okay, I'm stupid then ┐_(ツ)_┌". Yeah. Okay. This isn't exactly flaming someone out.
(The calibre/setuid things are a little less impressive. Though on the other hand, again, I can almost see the sense; I also have some serious beefs with the core design of the linux mount API right down to the syscall level.)
On the other hand he actually fixes things.
Even if you actually were paying money for his services, which most of us are not, which would you prefer an obsequious kind person who didn't fix your problem or a dick that did.
I would take the dick every day of the week.
When I'm asked a question whether it's better to hire a dickhead that is an expert in some field, or a normal person that isn't an expert of this field but showing promises, I'm probably always going with the non-dickhead person.
Dickheads are hard to communicate with, they are lowering team morale, make teamwork harder so in the end expert dickheads are less valuable than non-dickheads.
The beauty of open source is you can look at the code and even the issue tracker. I dare you to look at even `setup.py`, a file that's usually quite straight forward in Python, and tell me what it's doing. But if you're happy using kitty as your daily driver, great.
I guess you can dismiss all this as "haters gonna hate" and "what have you made?". Which is why in the comment, I refrained from stating my opinion and linked to other people's experiences/opinions instead. Just don't say you didn't know. And good luck getting the things you want fixed.
That came out wrong...
It isn't true if the VM is communicating over an emulated serial port. In that case, the VM software must provide a terminal as hardware. Typically the VM software only provides a serial port to the VM, which the user will then associate with something else via the VM configuration. This fails when loading a snapshot because the terminal isn't part of the snapshot.
For example, suppose that the VM is a PC-AT running DR-DOS and a BBS. (from the pre-internet days, with a modem for users to dial in on) At minimum, the VM software must provide a serial port for the VM. You could configure this to connect with a real physical modem and then connect to that with another modem and some dial-up software, but then you'd have a problem with snapshots. Loading a snapshot would place the BBS in a state that is inconsistent with the dial-up software. What you really need is for the terminal emulator to be part of the hardware that the VM is emulating. It would then be properly snapshotted.
If you want to see just how fast it can be, grab a linux instance, press ctrl+f1 to drop to a GUI free terminal and see just how responsive and how fast it can run.
It's kind of nuts that we have to rely on something as powerful as hardware acceleration via GPU to make plain text rendering on a screen in a GUI approach the same speed as CPU rendered text in a straight terminal console.
Use a full screen terminal with a 12pt font on a 4K display. Split the tmux window into quarters and pull up some logs in each pane. Now use the mouse to click and drag on the center vertical border; quickly resize it from left to right. The border takes about half a second to catch up with the mouse cursor as tmux repeatedly reflows all the text on the screen.
I'm using macOS and unfortunately not familiar with how I'd do that, but I'm sure it would be easy with something like i3wm on linux (which I still miss after moving away from linux 3 years ago :/), but I don't know what I could use in macOS.
Maybe I could find some third-party solution just to show/hide a particular application. I think if I had that + if I could figure out tabbing/tiling behaviour of Kitty, I would switch to it. Those two things are the main things that I need from iterm.
Input was just so .... immediate? It’s really hard to describe, but it was surprisingly obviou.
I can definitely tell you that while I can't see the actual letter appearing on the screen - the letter on the calculator would feel as if it appeared right at the bottom position of the button, while on my PC the key would have travelled some distance off the ground before I see the letter.
It's not uncomfortable, but I could easily tell the two apart in a blind test would something like that come up.
I would much prefer a terminal that still provided interactivity when text was scrolling in other parts than raw speed. Open up two panes in tmux or your favorite split screen with text scrolling in one and measure latency in the other pane with typometer and I will use whatever comes up to the top.
START=`date +%S.%N` && find ~ && echo $START && date +%S.%NHowever I do agree with your point that this "shouldn't" happen in practice (ie any decent hardware you'd expect to have buffers to prevent that kind of write errors).
I use i3 (a tiling WM) though, so tmux is redundant for me unless I work on remote machines.
And I really don't want tmux running on top just for scrolling. It hurts performance quite a bit.
The state of an entire OS, with all running programs, gets saved. It's more complete than when a laptop/notebook does suspend-to-disk. The emulator saves the CPU registers, the RAM, the disks, the parallel port mode, etc.
The trouble is that a connected terminal is not included in that list.
You keep trying to reinvent terminals with features that already exist to solve a problem that needs to be fixed in the server itself.
You can then also forward any output to a file/terminal emulator/whatever is convenient, but relying on the terminal emulator to save part of your emulator's state seems weird to me, unless you are going to ship the two bundled together.
The point of a library is that the two are more than just bundled together. They are linked together, making one executable. The terminal window is a part of the emulator.
The only thing that wouldn't be inlined via control characters nor escape sequences would be the PTY operating mode (which are defined via kernal syscalls). Im talking about stuff like local echo, flow control, how CR/LF characters are handled, etc. However that's solved with a multiplexer (screen or tmux type thing) or a custom shell, thus you could save that running state and reset it when needed (shells actually already need to do this to some extent so they can pass control of the TTY to forked processes. But we'd obviously need to take things a step further and store any state changes made by forked processes as well). However now we are back to my original solution you dismissed.
I Wouldn't think that the terminal is the actual problem, but running the same job side by side consistently failed on the gnome terminal and finished successfully on urxvt.
On a side note, OP remark on CD-ROMs was regarding writing, CD-ROMs write feed had to be an uninterrupted, continuous stream, and the smallest hiccup would blow the operation and render the media useless.
The emulator needs to pop up 2 terminal windows so that we can log in to the BBS. We do that, and a colorful menu is displayed on each of them. At this point, we save a snapshot and shut down the host computer. Later, we start the host computer, then start the emulator, and then try to resume the snapshot. Each terminal window remains blank, which is not the correct state. The guest OS (a DOS BBS) is in the state where it is showing a colorful menu, but we can't see it at all. Our terminals, being separate from the emulator and without an ability to save/restore snapshots, are inconsistent with the emulated guest OS.
In the above example, the guest OS (a DOS BBS) never did any kernel syscalls related to PTY operating mode. It directly acted on serial port hardware. There is no PTY, and adding one (where?) doesn't help.
Fundamentally, the emulator needs to be able to save/restore all terminal state. That even includes stuff like incomplete escape sequences, such as when just the first byte of the escape sequence has been passed to the terminal.
I don't know why you even mentioned PTYs (now I understand your requirements). A PTY is just a detachable interface for local terminals, but since you're connecting via serial anyway there's no need for a PTY. There's also no need for a special emulated serial interface like you suggested because the DOS VM would have one already baked into it, just use that and have the BBS listen on a couple of COM ports.
Regarding storing the previous session, there are already terminal emulators out there that will restore the scroll back session from a previous instance, so you might find your idlogical terminal already exists.
It still seems like a daft problem you're trying to solve though. Putting aside you're suspending a server for no apparent reason (why would you even want to do this?), you're effectively running a forum for one local user. But I'm sure you also have your own reasons for these anti-patterns as well.
I have implemented (wrote C code for) what you refer to as "a special emulated serial interface" and thus "the DOS VM would have one already baked into it". That is my code and it works fine, and I do indeed "have the BBS listen on a couple of COM ports".
I mentioned PTYs because I don't want them. Most terminal emulators will only accept data from a PTY, with themselves on the master side and a shell on the slave side. This alone makes these terminal emulators essentially worthless; to use them I'd really need to have my emulator act as a telnet server and then ask the user to telnet into the server! Perhaps a really screwy $SHELL could perform that automatically, but it still doesn't solve the replay/snapshot issue.
An xterm is very special because xterm supports the -S option. With this, my emulator can fork off a process and then exec an xterm with a file descriptor that I can feed data into. This works OK until I want to load a snapshot.
There may be "terminal emulators out there that will restore the scroll back session from a previous instance", but this gets unusable. My emulator supports multiple named snapshots. Using a terminal program with distinct snapshot functionality would require that the user save/restore snapshots both in my emulator and in each of the terminal programs. I have a case (other than a DOS BBS) where my emulator has dozens of serial ports, so this would place a heavy burden on the user.
Suspending a server is good for debugging it. I can go back to before a crash. I can load a snapshot to bypass slow and annoying start-up.
I emulate lots of different things. I'll make up an extra-simple case to illustrate the problem.
The guest OS running in the emulator is just a bootable floppy image for testing. All it does is print a counter to the serial port, once per hour. Just after 3 hours it has written 0, 1, 2, 3. At this point I make a snapshot file named 0123.snap and let the software continue running. More numbers get printed. Eventually the terminal is showing 0, 1, 2, 3, 4, 5, 6. I decide that I wish to go back in time, so I issue a command to load the 0123.snap file into the emulator. The internal state of the emulator warps back to the point at which I took the snapshot. The CPU registers, the RAM, and everything else within the emulator are now as they were earlier. The terminal retains the old state however, because it is a separate program with no awareness of the fact that I just loaded the 0123.snap file into my emulator. The guest OS carries on from the original point of course, since that is what the CPU and RAM state dictates, so a "4" will be printed next. The terminal then shows 0, 1, 2, 3, 4, 5, 6, 4. The numbers are simply wrong. They should be 0, 1, 2, 3, 4.
I can only avoid this fate by saving full terminal state whenever I save the emulator state, and of course restoring it at the same time too. There is no reasonable way to extract terminal state from a separate terminal program. (attacking it with ptrace is not reasonable) I thus conclude that the terminal must be built into the emulator.
It's called a "terminal multiplexer" and that is exactly what I suggested with the tmux solution right from the bloody start. I've lost track of how many times I've said this needed to be solved on the server yet you repeatedly pushed back on both points when they were made, insisting it was a terminal emulator issue on the client side.
I don't see tmux being available as a library that I could link into my emulator. If it can be a library, then yes my emulator could implement the tmux protocol. This turns out to be almost exactly what I was proposing, with the terminal state implemented by a library within the emulator. I'd just be missing the user-friendly aspect of automatically popping up the terminal windows when my emulator starts, but perhaps that could be arranged by having the emulator start xterm running tmux.
This is comparable to using vnc protocol for VGA. I have this implemented, but nobody likes to use it. Everybody prefers the built-in video window to show the guest's VGA.
If you meant to not link in the tmux code though, that won't work.
Instead of insisting that there is a terminal emulator issue on the client side, I insist that there not be a distinct client. The code that tracks terminal state (cursor position, current character attributes, etc.) pretty much needs to live in the emulator. That is the only reasonable way to ensure that the state can be saved and restored by the emulator. Actually displaying this state could be done by connecting a client (annoying) or just by popping up a window.
Another nice thing about having the terminal windows built into the emulator is that they all go away when the emulator does, even if that is a crash.
The serial port is an emulated 16550 chip. It is much more than a PTY. It has clock divider registers, an interrupt cause register, a transmit holding register, etc.
Scroll back buffer history won't let me untype something. If I take a snapshot, then a character is output to the terminal, and then I load that snapshot, the character needs to disappear from the screen. Of course, "character" could be something more destructive, like a scrolling operation or the clearing of a line.
If you disable local echo and have the server side software handle that (like how the SSH protocol works) then it becomes even easier because you then also manage the terminal state (to some degree) via the server as well.
I've written quite a bit of software around this kind of area and I really doesn't sound like a problem that hasn't already largely been solved. I mean if you're feeling really lazy you could just build a terminal server that supports detachable sessions (eg tmux or screen) and that would get around the scroll back issues without you having to write a single line of code.
Like I said, I've done a lot of work with serial interfaces much more archaic than what you've described and have been able to get them working without having to write too much magic. So I suspect you've over thought your problem because it still seems really straightforward to solve from this latest description. Like I said before, terminals literally are just flows of text (ironically there's even less complexity there since you're dealing with serial interfaces rather than PTYs) so all you actually need to do is ensure your terminals output is persistent - which is actually a surprisingly easy job.
The reason I commented about hacking the BBS software is because that's the only way to solve the weird requirements you're asking. You can complain about my suggestion all you like but it's your unusual requirements that are at fault The fault here, not my solution.
Maybe you need to stop and think for a moment that perhaps what you're asking is silly rather than just assuming that everyone else on the internet is stupid.
The closest work around you're going to get (and is buildable with your experience) would be to build a terminal server (like a minimal Linux distribution running on a VM or Raspberry Pi) which you can SSH onto from Linux or Windows (eg via PuTTY) and which has a serial interface to your BBS software (be that virtualized or physical). Install 'tmux' or 'screen' onto the terminal server and when you SSH onto the terminal server reattach to your screen session. That screen session will be connected to your BBS and you'll then have your detachable but persistent terminal sessions.
Edit: If your terminal server is a VM and the BBS software is a DOSbox instance running on the terminal server then you also only need to snapshot one host and have persistent scroll back PLUS the ability to restore from random snapshots. The only thing you would lose is your TCP/IP handshake to the xterm / PuTTY session but they're detachable anyway via tmux / screen so you'd just have to SSH back into the host and reattach to your multiplexer (screen / tmux).
I do restore snapshots in random orders, and I really want my terminal to know exactly where to resume. I don't expect the terminal to guess. I expect it to accept a blob of serialized state data, and of course I also need it to produce that sort of data on demand. I want that data in the snapshot files that my emulator creates.
I could indeed put the emulator, along with separate terminals (xterm) and the OS they require, within an emulator. This works, but adds the overhead of a whole extra OS. It gets confusing to use, takes up lots of memory, runs slowly, and takes up extra space on the screen.
Honestly, just stick this stuff behind a terminal multiplexer and move on with your life. You're trying to over-engineer a solution to a problem you're inventing.
It is typical for emulator authors to just give up, letting the terminal be inconsistent after loading a snapshot.
So far I've done just that... but my users love loading snapshots.