c - 有没有办法使用低级输出输出 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 * 高度 * 宽度)
解决方案
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。
两种高级模式是writefile
和writeconsole
。低电平是writeconsoleoutputcharacter
。
推荐阅读
- javascript - Bokeh - 如何在 JS 回调中更改字形属性?
- java - 在乐山服务器上接收观察到的对象变化
- php - 将 .htaccess 和 index.php 从公共复制到根目录后,laravel 资产文件未加载
- node.js - 如何使用 JS Babel API 处理多个文件
- javascript - 如何允许在链接中点击 svg
- google-apps-script - 用于表格的 Google 脚本 - 添加到日历时跳过日期格式不正确的行
- angular - NestJS,Typeorm - like 不返回任何记录
- batch-file - 如何将多个参数传递给批处理文件?
- php - PHP MySQL 查询到 Codeigniter
- mongodb - JEST 和 MongoDB 的异步问题