用MAME实现实时VT102仿真

2020-06-27 23:33:52

作为一名软件开发人员,我花了很多时间使用终端,或者更确切地说,是“终端仿真器”。像iTerm2、PuTTY、GNOME终端、或者经典的xterm和rxvt这样的工具都是“终端仿真器”;它们接收原始文本和格式指令,并将其解释为在屏幕上显示漂亮的文本。但是,如果这些通常称为“终端”的工具实际上是“终端仿真器”,那么它们仿真的实际终端是什么?

如今,大多数终端仿真器实际上都在仿真xterm;它是最古老、功能最强大的终端仿真器之一,因此出于兼容性原因,其他终端仿真器往往会效仿它。但xterm的网页上说它“提供DEC VT102和Tektronix 4014兼容的终端”。也就是说,xterm是VT102终端的仿真器:

数字设备公司,简称DEC,制造了许多不同类型的终端,但真正腾飞的是VT100,所有后来的型号(VT220、VT320、VT420、VT520及其所有变种)都向后兼容它。由于它们是最古老和最有特色的终端家族之一,出于兼容性原因,xTerm决定效仿它们。

xTerm(及其所有更现代的竞争对手)效仿VT102(等等)。以基本上相同的方式:阅读文档,并逐个实现列出的每个功能。文档说,当终端接收到ESC[5 A]序列时,它会将光标向上移动5行,所以只要我们的终端做同样的事情,它就是正确的。但是,如果你是一名现代软件开发人员,这应该会让你感到紧张:面对一系列功能,你可以预期它们几乎肯定会以令人惊讶和难以预测的方式相互作用,你可能需要更多的文档,

遗憾的是,据我所知,目前还没有针对终端和终端仿真器的详细文档或测试套件,因为它们基本上是关于视觉输出的,所以很难对它们进行适当的测试。

一个特别的大喊答题节目集给VTTEST,它确实试图练习一些VTxxx仿真的角落案例。不幸的是,它只能真正地交互使用,所以它对自动化测试没有用处。

取而代之的是,它们通常以老式的方式进行测试:运行应用程序以查看是否有任何怪异之处。下一代应用程序是针对当前一代终端仿真器进行测试的,下一代终端仿真器是针对当前一代应用程序进行测试的,依此类推。这已经取得了令人惊讶的效果,但在此过程中存在一定的信息损失。例如,VT100支持呈现双角文本,xterm也支持它,但许多其他终端仿真器不支持,因此应用程序不使用它。

与其将每个终端仿真器与以前的终端仿真器进行比较,如果我们能直接与原始的VTxxx终端进行比较,那将是很棒的。但是,现在这种终端非常罕见,即使你想买一台二手的,它们也是沉重易碎的。

你可能听说过视频游戏中的MAME;毕竟,它最初是多拱廊机器仿真器。但是,许多拱廊机器是由类似的组件建造的,以相似的方式连接在一起,所以MAME最终成为一个相当通用的“计算机组件连接在一起”的系统,今天它模拟所有类型的计算机、游戏控制台、计算机化的小工具以及街机。特别是,与我们的兴趣相关的是,它模拟VT102。这不是像XTerm或其他终端仿真器那样的文档作为功能列表的实现(Documentation-as-Feature-List Implementation),如XTERM或其他终端仿真器:MAME。并用模拟CPU与模拟串口和模拟视频硬件对话来解释它。这大概是您在不占用半张桌子的情况下所能获得的VT102最好的再创造。

VT102固件ROM的副本这些都是受版权保护的,不能合法分发,但向您最喜欢的搜索引擎询问有关“Mame vt102ROM”的信息可能会有所帮助。

一旦您拥有了所有这些东西,就可以启动MAME了。下面是要使用的命令行:

-Window意味着Mame将像行为良好的终端仿真器一样在窗口中绘制其输出,而不是占据整个屏幕(对于Mame的正常街机游戏用例来说,这是一个明智的默认设置)。

-Nomouse表示Mame不会抢占鼠标的独占控制权(因为VT102不支持鼠标控制,这没问题)。

-VOL-15表示音量调整到-15分贝的级别。VT102有一个相当激进的蜂鸣器,它会发出很多蜂鸣音,所以调低音量是很重要的。

-RS232 PTY意味着VT102串行端口的另一端应该连接到PTY,PTY是内核为终端仿真器提供的仿真串行端口,用于与其内部的应用程序通信。

启动MAME后,您将看到一个关于仿真未完成的警告屏幕。按一个键可以通过它。接下来,会有一个关于被仿真硬件的信息屏幕。也可以按一个键通过它。最后,仿真的VT102应该会启动。首先,它会在左上角说“等待”,然后您会听到一些嘟嘟声,您会看到如下所示:

左上角的2表示硬件需要配置。很合理,它已经40年没有通电了。

为了配置VT102,您需要检查VT102键盘的图表。请参见键盘顶部数字上方的标签?这些标签告诉您数字键在设置屏幕中的作用。

您还会注意到键盘左上角有一个很大的“Setup”键。您的PC键盘没有Setup键,但Mame默认将其映射到F5键。按F5键,您应该进入“Setup A”模式:

你可以在设置屏幕上配置很多东西,包括“深色背景上的浅色文字或浅色背景上的深色文字”、“光标应该是块还是下划线”,以及“当我键入一个键时,键盘是否应该点击”。但是,我们只需要改变一件事就可以让事情正常工作。

在Mame窗口的底部,您将看到两个标签,“On line”和“LOCAL”。默认情况下,“LOCAL”亮起,这意味着在键盘上键入将直接进入显示器,而不是远程计算机。在键盘图上,您将看到“4”键被标记为“LINE/LOCAL”。现在我们处于设置模式,按4切换到“On line”模式。

完成后,按Shift-S保存您的设置。屏幕应该会清除,并在左上角显示“等待”一两秒钟,然后返回到设置A屏幕。请注意,VT102是一台专用的QWERTY机器-如果您使用的是其他键盘布局,则需要按QWERTY键盘上产生S的键。

很久以前,当我们启动Mame时,我们给它提供了命令行选项-rs232 pty,这使Mame创建了一个PTY设备来与外部世界通信。MAME在PTY的一端,我们将shell(或任何其他应用程序)连接到另一端,然后就可以了!这个应用程序在模拟的VT102中运行,问题是,这个Pty在哪里?Mame会告诉我们的,但我们必须先与之抗争一下。

传统上,要调出MAME的用户界面,请按Tab键。MAME通常用于模拟视频游戏,通常没有Tab键,因此工作正常-但VT102确实有Tab键,我们希望能够使用它。MAME的解决方案是支持多种键盘模式:默认情况下,MAME以“全仿真”模式启动,其中每个键都由VT102处理;如果您按下切换键盘模拟键,它将切换到“Partial Emulation”模式,在该模式下,大部分键由VT102处理,但有些键由Mame自己处理。传统上,切换键盘模拟键是Scroll Lock键,但在我的机器上,不管出于什么原因,它都是INSERT键。使用键盘上很少使用的键,最终您应该会看到一条关于Partial Emulation的消息:

进入部分仿真模式后,可以按相同的键返回到完全仿真,或按Tab键打开Mame的仿真菜单:

如果您使用非QWERTY键盘布局,您可能会对此菜单中的键盘模式项感兴趣。它允许您在仿真模式和自然模式之间切换Mame,在该模式中,键盘布局是VT102的标准QWERTY,而在自然模式中,Mame遵循操作系统的正常键盘布局。请注意,这与完全仿真和部分仿真模式无关。此外,VT102可能无法在自然模式下对某些键做出正确反应-如果您遇到问题,请尝试模拟模式。

在此菜单中,最重要的项目是“伪终端”,大约是向下的三分之一。您可以使用光标键、Enter和Escape来导航菜单。如果突出显示“伪终端”并按Enter,您将进入“伪终端”子菜单,其中显示连接到VT102的模拟串行端口的终端设备的路径:

记下终端设备的路径,然后再次按Tab键关闭Mame‘s Menu,再按键盘模式键切换回Full Emulation模式。

正如我前面提到的,PTY是终端和在其内部运行的应用程序之间的接口。要使用物理VT102,您需要将其连接到计算机上的物理串行端口,并且(像任何设备一样)您的操作系统有用于它的驱动程序和配置。当人们停止使用终端而开始使用终端仿真器时,PTY被发明为一种虚构的串行端口,它支持与真实串行端口相同的配置,但忽略了大部分配置。

大多数,但不是全部。当大多数终端仿真器创建PTY时,它们会给出标准的、合理的配置。MAME,不管出于什么原因,都没有-至少在我使用的版本中没有。幸运的是,我们可以在PTY上使用标准的Unix串行端口配置工具来匹配VT102期望的配置。下面是要使用的命令行:

SANE应用合理、合理的默认值例如,它将^C配置为发送中断信号,并将VT102的Return键(发送^M,“回车”控制码)转换为Unix程序所期望的^J控制码。

COLS 80告诉应用程序,终端每行显示80个字符VT102可以配置为显示132列,但我们现在仍使用默认值

Erase^H表示擦除前一个字符的键生成^H,“退格”控制代码linux约定是基于VT220的,它有一个“⌫”(删除)键发送^?而不是发送^H退格键。

Ixon的意思是,当终端接收的数据超过其处理能力时,它将发送^S以使内核暂停发送数据,并在积压清理完毕并准备好接收更多数据时发送^Q。VT102是在20世纪70年代末设计的,而您的笔记本或台式机的速度是它的数万亿倍;因此,它可能难以跟上也就不足为奇了。

<;/dev/pts/10告诉stty配置Mame连接到的终端,而不是正在运行stty的终端。

终端正在等待,PTY已配置,是时候启动shell了。下面是要使用的命令行:

Term=vt102告诉应用程序它们在VT102内运行,因此它们可以限制其输出以匹配终端的图形限制。

LC_ALL=C使C应用程序使用C语言环境,因此它们应该坚持纯ASCII输出(这基本上就是VT102所能理解的全部)。

COLUMNS=80 LINES=24告诉应用程序终端的尺寸是的,我们也在上面的PTY级别进行了配置,但是有些应用程序检查其中一个,有些应用程序检查另一个,所以我们需要同时设置这两个。

/bin/sh是我们想要运行的shell您可以尝试运行您的常规shell,但是/bin/sh通常更原始,这对于这种历史重现来说是合适的

此外,您的个人shell可能会进行调整,以使用颜色很好的提示符或表情符号,或者会让OLD‘VT102感到困惑的东西。

上面描述的设置运行得相当好,但不幸的是,仍然有一些问题我不知道如何解决。

VT102通过一个默认为9600波特的串口与外界交流,这大约是每秒1千字节,或者说每个字符略低于1毫秒。在我们这个千兆网络的现代时代,这听起来相当慢,但对于一台建于1981年、CPU为6 MHz的可怜的小机器来说,这可能有点吃力。拿一个传入的字符并将其绘制到屏幕上相当简单,但当终端必须首先滚动整个屏幕才能腾出空间时,

为了解决这个问题,VT102有一个128个字符的输入缓冲区。每个到达的字符都放在队列的后面,CPU从前面取出字符,并以最快的速度处理它们。当缓冲区满了四分之一时,VT102发送一个XOFF字符(^S),告诉另一端的计算机暂停传输。希望另一端将接收到XOFF并在缓冲区填满之前暂停传输-在9600bps。

不幸的是,模拟的VT102不是通过真正的串行端口连接的,它是通过PTY连接的(至少与VT102期望的相比)基本上是无限快的。因此,当您运行一个产生大量输出的命令时,即使XON/XOFF流控制已启用并且正在工作-该命令在XOFF字符生效之前也会产生足够的数据来填充缓冲区。

在这个屏幕截图中,您可以看到VT102用来表示“我错过了一些文本”的几个棋盘字形(▒)实例,其中一个在左上角,一个在左下角,还有一个在左中角,“中间”这个词的左边有几个单元格。

我真的不知道该怎么做。我认为理想情况下,应该更新Mame的串口仿真,强制限制输入速率以匹配配置的波特率,也许还应该手动实现流控制,因为显然内核不能可靠地做到这一点。我认为在Mame之外没有什么可以做的。

现代桌面操作系统通常运行一种称为“桌面外壳”的特殊应用程序,它允许用户启动其他应用程序(或“虚拟桌面”中的应用程序组),在它们之间切换,并强制关闭它们。

UNIX终端子系统支持类似的概念:命令行shell是一种特殊的应用程序,它允许用户启动其他应用程序(或“作业”中的应用程序组),在它们之间切换(使用^Z键以及fg和bg等命令),以及强制关闭它们(使用^C和^\)。

允许它工作的概念是“控制终端”,每个Unix进程都可能由某个终端控制;当终端向内核发送类似^C或^Z的击键时,内核可能会中断或挂起该终端的一些进程。为了让shell能够管理特定终端中的作业,该终端必须是shell的控制终端。但是,上述启动shell的指令导致shell的控制终端是启动它的终端,而不是Mame为用户创建的PTY。因此,它不能管理多个作业,并且某些应用程序(如LESS(1))将工作。

通常,终端仿真器有责任确保在其中运行的程序具有正确的控制终端设置。不幸的是,正如我们已经看到的,MAME不认为自己是终端仿真器,所以它不进行正常的设置。更不幸的是,没有标准的工具来自己设置控制终端,就像stty让我们自己配置终端的方式。当然,我们可以编写这样的工具-最重要的部分将是setsid(2)来清除当前的控制终端,但是我们也可以做所有静态的和环境可变的事情--但是在流量控制的情况得到解决之前,我不认为这是值得的。

实际上,我撒了个小谎:有一个设置控制终端的经典工具:getty。它通常用来管理真实的硬件串口,接听拨入调制解调器的呼叫,并启动登录过程。一旦Mame创建了Pty,我们就可以假装它是一个真实的硬件串口,在上面运行Getty,然后假装我们是80年代电影中的青少年黑客入侵大型机:

您必须先运行stty来设置erase^H,或者非常擅长键入您的登录名和密码。

Getty会删除Erase^H设置,还会删除Ixon设置,因此您必须在登录后再次运行stty。

Getty希望以root身份运行,因此您需要root(或sudo)才能运行它。

因为它运行完整的登录过程,所以您没有机会设置LC_ALL,也没有机会运行除登录Shell之外的Shell

最重要的是,尽管Getty设置了新的控制终端,但它不会清除旧的控制终端,因此无论如何您都需要一个自定义工具(或特定于Linux的setsid工具。

如果您想不管怎样都尝试一下,下面是要使用的命令行:

sudo以root身份运行命令的其余部分,因为登录需要切换到您以任何身份登录的用户,这需要root权限。

setsid是特定于Linux的工具,它在没有控制终端的上下文中运行命令。

Mame的VT102仿真作为一种新颖的、轻量级的交互式测试工作得足够好了,但我不想经常使用它。如果Mame仿真串行端口流量控制,如果有一个工具可以用特定的控制终端启动程序-或者更好的是,如果Mame的PTY支持包括启动它创建的PTY程序端,情况可能会好得多。

其中一些事情可能甚至不会太难做到,但现在我已经花了足够多的时间来处理这些事情,是时候继续前进了。