Есть ли способ вывести escape-последовательности ANSI, используя низкоуровневый вывод? - PullRequest
0 голосов
/ 07 апреля 2019

Я пытаюсь сделать графический движок в консоли.Я не использую ни один из GL, но скоро надеюсь начать.Он написан на C и на данный момент способен создавать цветную полу-3D среду, но я обнаружил, что win cmd поддерживает цветовую схему True, используя escape-последовательности ANSI.

В ходе моих исследований по этой теме я обнаружил WriteFile(), на котором основаны все printfs и putcs в Win10.Но для всех товаров это не обеспечивает, это все еще медленно.Как показывает внутренний код, файл записи в основном основан на этом коде:

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 байт.Системный вызов имеет 84ms выполнения.

Затем я вернулся к своей предыдущей настройке с WriteConsoleOutputW () .Он использует тот же вывод ptr консоли, но на этот раз для буфера 320 * 84 (он использует CHAR_INFO ptr в качестве буфера, то есть 4 байта каждый) -107 520 байт, он длится всего 1ms !

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 как CHAR_INFO, ноон выводит их в виде текста.Поэтому вопрос таков: могу ли я как-нибудь вывести escape-последовательность, используя WriteConsoleOutput или NtDeviceIoControlFile ()

Кроме того: мой буфер кадров будет состоять только из escape-последовательностей и пробеласимвол после него.Ширина и высота буфера, а также прямоугольник определены, все, что мне нужно сделать, это вывести правильные цвета переднего плана для каждого из пробелов (поэтому длина будет 20 * Высота * Ширина)

1 Ответ

0 голосов
/ 08 апреля 2019

CMD - это эмулятор VT100 (эта информация из справки приложения сервера Telnet).

Я не уверен, почему вы продолжаете говорить об ANSI и о функции, не имеющей функций.

ANSI не поддерживается, за исключением самых последних версий Windows 10.

Не используя 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.

...