summaryrefslogtreecommitdiffstats
path: root/_log
diff options
context:
space:
mode:
Diffstat (limited to '_log')
-rw-r--r--_log/matrix-digital-rain.md65
1 files changed, 49 insertions, 16 deletions
diff --git a/_log/matrix-digital-rain.md b/_log/matrix-digital-rain.md
index 8c97ed3..e495445 100644
--- a/_log/matrix-digital-rain.md
+++ b/_log/matrix-digital-rain.md
@@ -7,14 +7,15 @@ thumbnail: thumb_sm.png
---
My 2022 implementation of the Matrix rain had too many loose ends. Unicode
-support was inflexible: the charset had to be a single contiguous block with no
-way to mix ASCII with something like Katakana; Phosphor decay level was stored
-in a dedicated array--still don't understand why I did that when I had already
-used bit-packing for the RGB channels; The algorithm was difficult to decipher.
-The 2022 version worked, but that’s not the same thing as being correct.
+support was inflexible: the character set had to be a single contiguous block
+with no way to mix ASCII with something like Katakana; Phosphor decay level was
+stored in a dedicated array--still don't understand why I did that when I had
+already used bit-packing for the RGB channels; The algorithm was difficult to
+decipher. The 2022 version worked, but that’s not the same thing as correct.
I began by placing the decay factor in the LSB of the 4-byte RGB value. Let's
-call that RGB-PD. PD plays a somewhat analogous role to an alpha channel; I
+call that RGB-PD. PD plays a somewhat analogous role to an alpha channel in
+that both influence transparency. However, they work very differently. So, I
avoided labelling it A so as not to cause confusion:
```
@@ -33,12 +34,12 @@ typedef union color_tag {
The decision to use union over more portable bit twiddling was made three years
ago, as I recall, for readability. Seeing as all my systems are little-endian,
-this is unlikely to cause me trouble. Besides, if union is never to be used,
+this is unlikely to cause any trouble. Besides, if union is never to be used,
why is it in the language anyway?
The blend() function, which emulates the dim afterglow of Phosphor by eroding
-the RGB channels towards the background, remains as elegant as it did three
-years ago:
+the RGB channels towards the background, with minor refactoring, remains as
+elegant as it did three years ago:
```
#define DECAY_MPLIER 2
@@ -55,13 +56,13 @@ static inline void blend(matrix *mat,
}
```
-While the memory inefficiency of Phosphor decay tracking was a technical
-oversight I hadn't noticed, the limitation around mixing nonadjacent Unicode
-blocks was a nagging concern even three years ago. So, a fix was long overdue.
+While the memory inefficiency of Phosphor decay was a technical oversight I
+hadn't noticed, the limitation around mixing nonadjacent Unicode blocks was a
+nagging concern even three years ago. So, a fix was long overdue.
-In the new version, I introduced a glyphs array that enables a user to add as
+In the new version, I introduced an array that enables a user to add as
many Unicode blocks as they want. The insert_code() function picks a block
-from the array at random, and then picks a character from that block at random:
+from it at random, and then picks a character from that block at random:
```
#define UNICODE(min, max) (((uint64_t)max << 32) | min)
@@ -96,8 +97,40 @@ are trivial and idiomatic, and the UNICODE() macro simplifies the management of
charsets. The insert_code() function is now ready to take its rightful place
next to blend().
-The result is a digital rain that captures the original Matrix aesthetic with
-high visual fidelity:
+The init_term() function is the arbiter of this zero-dependency software. It
+prepares the graphical environment so that I can interact with it via ANSI
+escape codes instead of unnecessary layers of abstraction:
+
+```
+static inline int init_term(const struct winsize *ws)
+{
+ struct termios ta;
+
+ if (tcgetattr(STDIN_FILENO, &ta) == 0) {
+ ta.c_lflag &= ~ECHO;
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &ta) == 0) {
+ wprintf(L"\x1b[48;2;%d;%d;%dm",
+ RGB_BG_RED, RGB_BG_GRN, RGB_BG_BLU);
+ wprintf(L"%s", ANSI_FONT_BOLD);
+ wprintf(L"%s", ANSI_CRSR_HIDE);
+ wprintf(L"%s", ANSI_CRSR_RESET);
+ wprintf(L"%s", ANSI_SCRN_CLEAR);
+ setvbuf(stdout, 0, _IOFBF, 0);
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, ws);
+ return 1;
+ }
+ }
+ return 0;
+}
+```
+
+All credit for the terminal control function belongs to Domsson, whose <a
+href="https://github.com/domsson/fakesteak" class="external" target="_blank"
+rel="noopener noreferrer">Fakesteak</a> inspired my own three years ago.
+
+insert_code() seeds the Matrix, blend() creates the old monochrome CRT display
+nostalgia, and ANSI control sequences paint the screen. The result is a digital
+rain that captures the original Matrix aesthetic with high visual fidelity:
```
$ cc -O3 main.c -o matrix