From 08e594268ed20c5c2355a249ac691c007e38aed9 Mon Sep 17 00:00:00 2001 From: Sadeep Madurange Date: Mon, 22 Dec 2025 23:38:06 +0800 Subject: Matrix post. --- _site/feed.xml | 2 +- _site/index.html | 26 +++---- _site/log/index.html | 26 +++---- _site/log/matrix-digital-rain/index.html | 105 +++++++++++++++++++++------- _site/log/matrix-digital-rain/matrix.mp4 | Bin 930430 -> 696574 bytes _site/log/matrix-digital-rain/poster.png | Bin 70901 -> 233077 bytes _site/log/matrix-digital-rain/source.tar.gz | Bin 2075 -> 3602 bytes _site/log/matrix-digital-rain/thumb_sm.png | Bin 22764 -> 52762 bytes _site/posts.xml | 2 +- _site/projects/index.html | 30 ++++---- _site/robots.txt | 2 +- _site/sitemap.xml | 34 ++++----- 12 files changed, 139 insertions(+), 88 deletions(-) (limited to '_site') diff --git a/_site/feed.xml b/_site/feed.xml index ed5a433..4d5229e 100644 --- a/_site/feed.xml +++ b/_site/feed.xml @@ -1 +1 @@ -Jekyll2025-12-21T08:09:20+08:00/feed.xmlASCIIMX | LogW. D. Sadeep MadurangeHow to manage Suckless software installations2025-11-30T00:00:00+08:002025-11-30T00:00:00+08:00/log/suckless-softwareW. D. Sadeep MadurangeFingerprint door lock2025-08-18T00:00:00+08:002025-08-18T00:00:00+08:00/log/fpm-door-lockW. D. Sadeep MadurangeOn the use of MOSFETs as electronic switches2025-06-22T00:00:00+08:002025-06-22T00:00:00+08:00/log/mosfet-switchesW. D. Sadeep MadurangeHow to configure ATmega328P microcontrollers to run at 3.3V and 5V2025-06-10T00:00:00+08:002025-06-10T00:00:00+08:00/log/arduino-unoW. D. Sadeep MadurangeMy first PCB2025-04-26T00:00:00+08:002025-04-26T00:00:00+08:00/log/my-first-pcbW. D. Sadeep MadurangeBumblebee: browser automation2025-04-02T00:00:00+08:002025-04-02T00:00:00+08:00/log/bumblebeeW. D. Sadeep MadurangeHow to set up ATSAM3X8E microcontrollers for bare-metal programming in C2024-09-16T00:00:00+08:002024-09-16T00:00:00+08:00/log/arduino-dueW. D. Sadeep MadurangeEtlas: e-paper dashboard2024-09-05T00:00:00+08:002024-09-05T00:00:00+08:00/log/etlasW. D. Sadeep MadurangeExperimental e-reader2023-10-24T00:00:00+08:002023-10-24T00:00:00+08:00/log/e-readerW. D. Sadeep MadurangeRecreating the Matrix rain with ANSI escape sequences2022-08-22T00:00:00+08:002022-08-22T00:00:00+08:00/log/matrix-digital-rainW. D. Sadeep Madurange \ No newline at end of file +Jekyll2025-12-22T23:37:38+08:00http://localhost:4000/feed.xmlASCIIMX | LogW. D. Sadeep MadurangeRecreating the Matrix rain with ANSI escape sequences2025-12-21T00:00:00+08:002025-12-21T00:00:00+08:00http://localhost:4000/log/matrix-digital-rainW. D. Sadeep MadurangeHow to manage Suckless software installations2025-11-30T00:00:00+08:002025-11-30T00:00:00+08:00http://localhost:4000/log/suckless-softwareW. D. Sadeep MadurangeFingerprint door lock2025-08-18T00:00:00+08:002025-08-18T00:00:00+08:00http://localhost:4000/log/fpm-door-lockW. D. Sadeep MadurangeOn the use of MOSFETs as electronic switches2025-06-22T00:00:00+08:002025-06-22T00:00:00+08:00http://localhost:4000/log/mosfet-switchesW. D. Sadeep MadurangeHow to configure ATmega328P microcontrollers to run at 3.3V and 5V2025-06-10T00:00:00+08:002025-06-10T00:00:00+08:00http://localhost:4000/log/arduino-unoW. D. Sadeep MadurangeMy first PCB2025-04-26T00:00:00+08:002025-04-26T00:00:00+08:00http://localhost:4000/log/my-first-pcbW. D. Sadeep MadurangeBumblebee: browser automation2025-04-02T00:00:00+08:002025-04-02T00:00:00+08:00http://localhost:4000/log/bumblebeeW. D. Sadeep MadurangeHow to set up ATSAM3X8E microcontrollers for bare-metal programming in C2024-09-16T00:00:00+08:002024-09-16T00:00:00+08:00http://localhost:4000/log/arduino-dueW. D. Sadeep MadurangeEtlas: e-paper dashboard2024-09-05T00:00:00+08:002024-09-05T00:00:00+08:00http://localhost:4000/log/etlasW. D. Sadeep MadurangeExperimental e-reader2023-10-24T00:00:00+08:002023-10-24T00:00:00+08:00http://localhost:4000/log/e-readerW. D. Sadeep Madurange \ No newline at end of file diff --git a/_site/index.html b/_site/index.html index 8b74fe9..82d971f 100644 --- a/_site/index.html +++ b/_site/index.html @@ -54,6 +54,19 @@ + + + Recreating the Matrix rain with ANSI escape sequences + + + + + + + + + + How to manage Suckless software installations @@ -171,19 +184,6 @@ - - - Recreating the Matrix rain with ANSI escape sequences - - - - - - - - - - diff --git a/_site/log/index.html b/_site/log/index.html index 57887a7..32f0ff2 100644 --- a/_site/log/index.html +++ b/_site/log/index.html @@ -44,6 +44,19 @@ + + + Recreating the Matrix rain with ANSI escape sequences + + + + + + + + + + How to manage Suckless software installations @@ -161,19 +174,6 @@ - - - Recreating the Matrix rain with ANSI escape sequences - - - - - - - - - - diff --git a/_site/log/matrix-digital-rain/index.html b/_site/log/matrix-digital-rain/index.html index cf04bde..6007da5 100644 --- a/_site/log/matrix-digital-rain/index.html +++ b/_site/log/matrix-digital-rain/index.html @@ -42,45 +42,96 @@

RECREATING THE MATRIX RAIN WITH ANSI ESCAPE SEQUENCES

-
22 AUGUST 2022
+
21 DECEMBER 2025

-

Over the weekend, I came across Domsson’s Fakesteak: a beautifully lean rendition of the -Matrix rain in raw C using ANSI escape sequences—zero dependencies, not even -ncurses.

- -

To keep things simple, Fakesteak didn’t support Japanese characters and that it -used 8-bit color mode. The latter meant that the ghosting effect has to rely on -different foreground colors rather than shades of the same color. As a tip of -the hat to Domsson’s impressive work, I decided to add Unicode and 24-bit -truecolor support to it, aiming to faithfully recreate the original Matrix from -the first movie during Neo and Cypher’s conversation:

+

The Matrix digital rain implemented in raw C using ANSI escape sequences with +zero dependencies—not even ncurses.

-

Adding Unicode support via wchar_t and wprintf() was easy enough. -Implementing the ghosting effect with truecolor support, however, turned out -harder than expected. To achieve the ghosting effect, I treated phosphor decay -as a multiplier, which allowed me to emulate the dim afterglow by gradually -transitioning each raindrop’s color towards the background color:

+

This is a fork of Domsson’s unique rendition of the Matrix rain: Fakesteak. Three years ago, I forked his project +and added truecolor and Unicode support. I also drastically modified the +algorithm to produce a rain that resembled the original aesthetic with high +visual fidelity.

+ +

Unicode support

+ +

Unicode support in the 2022 version lacked flexibility. The charset used in the +rain had to be a single contiguous block defined by UNICODE_MIN and +UNICODE_MAX settings:

+ +
#define UNICODE_MIN 0x0021
+#define UNICODE_MAX 0x007E
+
+static inline void insert_code(matrix *mat,
+    size_t row, size_t col) 
+{
+    mat->code[index(mat, row, col)] = rand()
+        % (UNICODE_MAX - UNICODE_MIN)
+        + UNICODE_MIN;
+}
+
+ +

There was no way, for instance, to use both ASCII and Katakana at the same +time. The user had to pick one. In the new version, the user can use any number +of Unicode blocks using glyphs array. In fact, the default rain now includes +both ASCII and half-width Katakana characters:

+ +
#define UNICODE(min, max)  (((uint64_t)max << 32) | min)
+
+static uint64_t glyphs[] = {
+    UNICODE(0x0021, 0x007E), /* ASCII */
+    UNICODE(0xFF65, 0xFF9F), /* Half-width Katakana */
+};
+
+static uint8_t glyphlen = (sizeof glyphs) / (sizeof glyphs[0]);
 
-
static void mat_shade(matrix *mat, size_t row, size_t col) 
+static inline void insert_code(matrix *mat,
+    size_t row, size_t col) 
+{
+    uint64_t block;
+    uint32_t unicode_min, unicode_max;
+
+    block = glyphs[(rand() % glyphlen)];
+    unicode_min = (uint32_t)block;
+    unicode_max = (uint32_t)(block >> 32);
+
+    mat->code[index(mat, row, col)] = rand()
+        % (unicode_max - unicode_min)
+        + unicode_min;
+}
+
+ +

Entries in the glyphs array are Unicode blocks bit-packed in an 8-byte +container: the four low bytes forms the first codepoint and the four high bytes +the last.

+ +

Phosphor decay

+ +

The dim afterglow of monochrome CRT displays is achieved by carefully scaling +the RGB channels individually and mixing them:

+ +
#define DECAY_MPLIER  2
+
+static inline void blend(matrix *mat,
+    size_t row, size_t col)
 {
     unsigned char *color;
-    color = mat->rgb[mat_idx(mat, row, col)].color;
-    color[R] = color[R] - (color[R] - COLOR_BG_RED) / 2;
-    color[G] = color[G] - (color[G] - COLOR_BG_GRN) / 2;
-    color[B] = color[B] - (color[B] - COLOR_BG_BLU) / 2;
+
+    color = mat->rgb[index(mat, row, col)].color;
+    color[R] = color[R] - (color[R] - RGB_BG_RED) / DECAY_MPLIER;
+    color[G] = color[G] - (color[G] - RGB_BG_GRN) / DECAY_MPLIER;
+    color[B] = color[B] - (color[B] - RGB_BG_BLU) / DECAY_MPLIER;
 }
 
-

Looking back at the implementation, there are still a few improvements to be -made. Instead of using a dedicated buffer, I should have bit-packed the -phosphor decay into the RGB data buffer to save memory. I’m not entirely -satisfied with the Unicode support as it’s restricted to contiguous code -points. The glitch effect, which I implemented with characters unexpectedly -changing, would have been closer to the original if flashed white as well.

+

The blending function emulates the phosphor decay by gradually transitioning +each raindrop’s color towards the background color. The multiplier is the +number of passes over the rain track needed before the afterglow disappears.

+ +

The algorithm

Nonetheless, the rain resembles the original with high visual fidelity. It’s highly customizable and gentle on the CPU. On my 14” ThinkPad T490, which has a diff --git a/_site/log/matrix-digital-rain/matrix.mp4 b/_site/log/matrix-digital-rain/matrix.mp4 index 84a9839..7edf5d6 100644 Binary files a/_site/log/matrix-digital-rain/matrix.mp4 and b/_site/log/matrix-digital-rain/matrix.mp4 differ diff --git a/_site/log/matrix-digital-rain/poster.png b/_site/log/matrix-digital-rain/poster.png index 0321ad3..1f68ca4 100644 Binary files a/_site/log/matrix-digital-rain/poster.png and b/_site/log/matrix-digital-rain/poster.png differ diff --git a/_site/log/matrix-digital-rain/source.tar.gz b/_site/log/matrix-digital-rain/source.tar.gz index fead280..5a69236 100644 Binary files a/_site/log/matrix-digital-rain/source.tar.gz and b/_site/log/matrix-digital-rain/source.tar.gz differ diff --git a/_site/log/matrix-digital-rain/thumb_sm.png b/_site/log/matrix-digital-rain/thumb_sm.png index d3f06c9..940965a 100644 Binary files a/_site/log/matrix-digital-rain/thumb_sm.png and b/_site/log/matrix-digital-rain/thumb_sm.png differ diff --git a/_site/posts.xml b/_site/posts.xml index d5fea09..1d3402d 100644 --- a/_site/posts.xml +++ b/_site/posts.xml @@ -1 +1 @@ -Jekyll2025-12-21T08:09:20+08:00/posts.xmlASCIIMXW. D. Sadeep Madurange \ No newline at end of file +Jekyll2025-12-22T23:37:38+08:00http://localhost:4000/posts.xmlASCIIMXW. D. Sadeep Madurange \ No newline at end of file diff --git a/_site/projects/index.html b/_site/projects/index.html index 2ef4c48..c75a620 100644 --- a/_site/projects/index.html +++ b/_site/projects/index.html @@ -50,17 +50,17 @@ - - Fingerprint door lock -

Fingerprint door lock
+ + Recreating the Matrix rain with ANSI escape sequences +
Recreating the Matrix rain with ANSI escape sequences
- - Bumblebee: browser automation -
Bumblebee: browser automation
+
+ Fingerprint door lock +
Fingerprint door lock
@@ -71,17 +71,17 @@ - - Etlas: e-paper dashboard -
Etlas: e-paper dashboard
+
+ Bumblebee: browser automation +
Bumblebee: browser automation
- - Experimental e-reader -
Experimental e-reader
+
+ Etlas: e-paper dashboard +
Etlas: e-paper dashboard
@@ -92,9 +92,9 @@ - - Recreating the Matrix rain with ANSI escape sequences -
Recreating the Matrix rain with ANSI escape sequences
+
+ Experimental e-reader +
Experimental e-reader
diff --git a/_site/robots.txt b/_site/robots.txt index e087884..d297064 100644 --- a/_site/robots.txt +++ b/_site/robots.txt @@ -1 +1 @@ -Sitemap: /sitemap.xml +Sitemap: http://localhost:4000/sitemap.xml diff --git a/_site/sitemap.xml b/_site/sitemap.xml index e2c5b7e..7a775fd 100644 --- a/_site/sitemap.xml +++ b/_site/sitemap.xml @@ -1,55 +1,55 @@ -/log/matrix-digital-rain/ -2022-08-22T00:00:00+08:00 - - -/log/e-reader/ +http://localhost:4000/log/e-reader/ 2023-10-24T00:00:00+08:00 -/log/etlas/ +http://localhost:4000/log/etlas/ 2024-09-05T00:00:00+08:00 -/log/arduino-due/ +http://localhost:4000/log/arduino-due/ 2024-09-16T00:00:00+08:00 -/log/bumblebee/ +http://localhost:4000/log/bumblebee/ 2025-04-02T00:00:00+08:00 -/log/my-first-pcb/ +http://localhost:4000/log/my-first-pcb/ 2025-04-26T00:00:00+08:00 -/log/arduino-uno/ +http://localhost:4000/log/arduino-uno/ 2025-06-10T00:00:00+08:00 -/log/mosfet-switches/ +http://localhost:4000/log/mosfet-switches/ 2025-06-22T00:00:00+08:00 -/log/fpm-door-lock/ +http://localhost:4000/log/fpm-door-lock/ 2025-08-18T00:00:00+08:00 -/log/suckless-software/ +http://localhost:4000/log/suckless-software/ 2025-11-30T00:00:00+08:00 -/about/ +http://localhost:4000/log/matrix-digital-rain/ +2025-12-21T00:00:00+08:00 + + +http://localhost:4000/about/ -/ +http://localhost:4000/ -/log/ +http://localhost:4000/log/ -/projects/ +http://localhost:4000/projects/ -- cgit v1.2.3