Is there a way to output ANSI escape sequences using low level output?

元气小坏坏 提交于 2019-12-25 01:35:27

问题


I'm trying to make a graphical engine in console. I don't use any of the GLs, but soon hoping to start. It is written in C and as for now, it is capable of building semi-3D environment in color, but I found, that win cmd supports True color scheme, using ANSI escape sequences.

Throughout my research on this topic I've found WriteFile(), on which all the printfs and putcs are based in Win10. But for all goods it does not provide it is still slow. As internal code shows, writefile is essentially based on this code:

NtWriteFile:

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

it is good, but slow and inefficient. What do I mean: I'm passing output handle of my console to WriteFile() and the buffer, but for the screen of 160*60 (considering every character has its own ESC[48;2;r;g;bm, which is 20 bytes long) we get 192000 bytes. The system call has 84ms of execution.

Then I returned to my previous setup with WriteConsoleOutputW(). It uses the same output ptr of the console, but this time for the buffer of 320*84 (it uses CHAR_INFO ptr as a buffer, so 4 bytes each)-107 520 bytes it lasts only 1ms!

WriteConsoleOutputW() is based on similar looking syscall code:

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

but this time it outputs roughly similar amounts of info 80 times faster! My assumption, that it's just reallocating a pointer to console buffer, because when I start it with buffer of single character it outputs some strange symbols with colors

I've tried to output ESC sequences as a CHAR_INFO but it outputs them as a text. So the question is: Can I somehow output an escape sequence using WriteConsoleOutput or NtDeviceIoControlFile()

In Addition: my frame buffer will consist only of escape sequences and space symbol after it. The Width and Height of the buffer, as well as a rectangle is defined, all I need to do is output correct foreground colors on each of spaces.(so the length will be 20 * Height*Width)


回答1:


CMD is a VT100 emulator (that information is from the Telnet server app help).

I'm not sure why you keep talking about ANSI and the function not having features.

ANSI is not supported except for very recent versions of Windows 10.

Not using ANSI one uses SetConsoleTextAttribute (which means colour). And there are other functions to move the cursor.

    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)

To move the cursor use

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

The behaviour of writefile (and there are three ways to write) is controlled by SetConsoleMode (which also can turn ANSI on). See https://docs.microsoft.com/en-us/windows/console/setconsolemode.

The two high level modes are writefile and writeconsole. The low level is writeconsoleoutputcharacter.



来源:https://stackoverflow.com/questions/55560959/is-there-a-way-to-output-ansi-escape-sequences-using-low-level-output

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!