首页 > 解决方案 > 有没有办法使用低级输出输出 ANSI 转义序列?

问题描述

我正在尝试在控制台中制作图形引擎。我不使用任何 GL,但很快希望开始。它是用 C 编写的,就目前而言,它能够构建彩色半 3D 环境,但我发现 win cmd 支持 True color scheme,使用 ANSI 转义序列。

在我对这个主题的研究中,我发现WriteFile()所有 printfs 和 putcs 都基于 Win10。但是对于它不提供的所有商品,它仍然很慢。如内部代码所示,writefile 本质上是基于以下代码:

NtWriteFile:

mov r10,rcx 
mov eax,8 
test byte ptr [7FFE0308h],1 
jne NtWriteFile+15h (07FFBA80CAAA5h) 
syscall                                 
ret

这很好,但速度慢且效率低。我是什么意思:我将控制台的输出句柄传递给WriteFile()和缓冲区,但是对于 160*60 的屏幕(考虑到每个字符都有自己的 ESC[48;2;r;g;bm,是 20 字节长)我们得到 192000 字节。系统调用的执行时间为84 毫秒

然后我使用WriteConsoleOutputW()返回到我之前的设置。它使用与控制台相同的输出 ptr,但这次是 320*84 的缓冲区(它CHAR_INFO ptr用作缓冲区,所以每个 4 字节)-107 520 字节它只持续 1毫秒

WriteConsoleOutputW() 基于类似的系统调用代码:

NtDeviceIoControlFile:

mov r10,rcx 
mov eax,7                           ; notice here is the 7 instead of 8 
test byte ptr [7FFE0308h],1 
jne NtDeviceIoControlFile+15h (07FFBA80CAAA5h) 
syscall                                 
ret

但这次它输出大致相似数量的信息,速度快了 80 倍!我的假设,它只是重新分配一个指向控制台缓冲区的指针,因为当我用单个字符的缓冲区启动它时,它会输出一些带有颜色的奇怪符号

我尝试将 ESC 序列输出为 a CHAR_INFO,但它将它们输出为文本。所以问题是:我可以使用 WriteConsoleOutput 或NtDeviceIoControlFile()以某种方式输出转义序列吗?

另外:我的帧缓冲区将仅包含转义序列和其后的空格符号。定义了缓冲区的宽度和高度,以及一个矩形,我需要做的就是在每个空格上输出正确的前景色。(所以长度将是 20 * 高度 * 宽度)

标签: cwindowscmdsystem-callsansi-escape

解决方案


CMD 是一个 VT100 仿真器(该信息来自 Telnet 服务器应用程序帮助)。

我不确定你为什么一直在谈论 ANSI 和没有特性的函数。

除最新版本的 Windows 10 外,不支持 ANSI。

不使用 ANSI 一种用途SetConsoleTextAttribute(这意味着颜色)。还有其他功能可以移动光标。

    Dim hOut as IntPtr
    Dim Ret as Integer
    hOut  = GetStdHandle(STD_OUTPUT_HANDLE)
    Ret = SetConsoleTextAttribute(hOut,  &hfA)
    Console.Out.Write("*")
    Ret = SetConsoleTextAttribute(hOut, &hfC)
    Console.Out.Write("WARNING")
    Ret = SetConsoleTextAttribute(hOut, &hfA)
    Console.Out.Write("*" & vbcrlf)

移动光标使用

Pos.X = CInt(Xpos)
Pos.Y= CInt(Ypos)
Ret = SetConsoleCursorPosition(hOut,  Pos)

的行为writefile(并且有三种编写方式)由SetConsoleMode(也可以打开 ANSI)控制。请参阅https://docs.microsoft.com/en-us/windows/console/setconsolemode

两种高级模式是writefilewriteconsole。低电平是writeconsoleoutputcharacter


推荐阅读