Repository: microsoft/terminal (language: cpp)

Issue:
Incorrect rendering for Gorched terminal-based game. 
Another render canary for you, @miniksa: Gorched (scorched earth game, terminal version.) It even has a Windows installer, so I'm guessing it was tested on alacritty or something.

From: https://github.com/zladovan/gorched

It should look like:

![Attract Screen](https://github.com/zladovan/gorched/raw/master/showcase.gif)

But actually looks like (with default options):

![image](https://user-images.githubusercontent.com/1844001/83318226-b21a7700-a200-11ea-94da-57b033cfaf22.png)

When I run with "safe" options, `gorched --low-color --ascii-only` I see:

![image](https://user-images.githubusercontent.com/1844001/83318284-3967ea80-a201-11ea-94b1-b97f13ed2d47.png)

No matter what width I set, I couldn't get it to align. Additionally, it seems there's some persistent glitching after the game is quit (ctrl+c) with margins and wrapping. 


Discussion / hints:
I had  a look at the underlying go library that the game is built on, `termloop`. It seems none of the examples there render correctly either, but they are significantly simpler. Maybe that would be easier to debug. I set up the environment like so:

```
scoop install go
go get -u github.com/JoelOtter/termloop
git clone https://github.com/JoelOtter/termloop
```

Then I ran some of the examples in: /tree/master/_examples -- they all render messed up, or don't work at all. I wonder what it's doing that's so wacky. 
Termbox, the library Termloop builds on, notoriously (at least, they're notorious to me :smile:) tries to be clever about interacting with the Windows console instead of using our VT support. I wonder what _they're_ doing.

This is probably something "[conhost recording](https://github.com/microsoft/terminal/tree/dev/duhowett/hax/conhost_dump_replay)" would help with. . . :smile:

Thanks for looking at this, @oising!
This is essentially a duplicate of #4363. The game uses console API calls to write to the screen buffer, and it looks like a lot of the blank areas of the background are actually the zero codepoint. Ideally conpty should be translating those to something like a space or non-breaking space, but it's just passing them through as a null control, which then ends up getting ignored.
Oh, lordy. I didn't look _that_ closely. I just presumed it was VT all the way ... look what I've become! Close as a dup if you see fit, guys.
I should mention the colors also don't work (i.e. some elements will be invisible) unless you've used the `--low-color` option, because obviously the console APIs can only handle 16 colors.

That said, you can actually run the Linux build in WSL, and that works perfectly (as far as I can tell), because it's then using actual VT sequences.

Fix patch:
diff --git a/src/renderer/vt/paint.cpp b/src/renderer/vt/paint.cpp
index d8e3e66686b..4e5d3ec5389 100644
--- a/src/renderer/vt/paint.cpp
+++ b/src/renderer/vt/paint.cpp
@@ -472,7 +472,25 @@ using namespace Microsoft::Console::Types;
         _bufferLine.append(cluster.GetText());
         totalWidth += cluster.GetColumns();
     }
+
+    // If any of the values in the buffer are C0 or C1 controls, we need to
+    // convert them to printable codepoints, otherwise they'll end up being
+    // evaluated as control characters by the receiving terminal. We use the
+    // DOS 437 code page for the C0 controls and DEL, and just a `?` for the
+    // C1 controls, since that's what you would most likely have seen in the
+    // legacy v1 console with raster fonts.
     const auto cchLine = _bufferLine.size();
+    std::for_each_n(_bufferLine.begin(), cchLine, [](auto& ch) {
+        static constexpr std::wstring_view C0Glyphs = L" ☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼";
+        if (ch < C0Glyphs.size())
+        {
+            ch = til::at(C0Glyphs, ch);
+        }
+        else if (ch >= L'\u007F' && ch < L'\u00A0')
+        {
+            ch = (ch == L'\u007F' ? L'⌂' : L'?');
+        }
+    });
 
     const auto spaceIndex = _bufferLine.find_last_not_of(L' ');
     const auto foundNonspace = spaceIndex != decltype(_bufferLine)::npos;


Test patch: