summaryrefslogtreecommitdiffstats
path: root/_site/projects/matrix-digital-rain/index.html
blob: 2893c9205ce73c42e77005184cb8254707fbc4b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>The Matrix digital rain</title>

    <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>The Matrix digital rain</title>
  <link rel="stylesheet" href="/assets/css/main.css">
  <link rel="stylesheet" href="/assets/css/skeleton.css">
</head>



  </head>
  <body>

    <div id="nav-container" class="container">
  <ul id="navlist" class="left">
    
    <li >
      <a href="/" class="link-decor-none">hme</a>
    </li>
    <li >
      <a href="/blog/" class="link-decor-none">blg</a>
    </li>
    <li class="active">
      <a href="/projects/" class="link-decor-none">poc</a>
    </li>
    <li >
      <a href="/about/" class="link-decor-none">abt</a>
    </li>
    <li><a href="/feed.xml" class="link-decor-none">rss</a></li>
  </ul>
</div>



    <main>
      <div class="container">
        <div class="container-2">
          <h2 class="center" id="title">THE MATRIX DIGITAL RAIN</h2>
          <h6 class="center">12 JANUARY 2024</h5>
          <br>
          <div class="twocol justify"><p>“All I see is blonde, brunette, red head.” The iconic digital rain from The
Matrix in C, with zero dependencies - not even ncurses.</p>

<video style="max-width:100%;" controls="" poster="thumb.png">
  <source src="matrix.mp4" type="video/mp4" />
</video>

<h2 id="overview">Overview</h2>

<p>This is my fork of Domsson’s beautiful <a href="https://github.com/domsson/fakesteak" class="external" target="_blank" rel="noopener noreferrer">Fakesteak</a>. While studying the code, I wondered
what it would take to faithfully recreate the original Matrix from the first
movie without sacrificing the program’s minimalism and elegance.</p>

<p>My version adds:</p>

<ul>
  <li>Unicode character support.</li>
  <li>Fully customizable 24-bit RGB (truecolor) colors.</li>
  <li>Glitches in the matrix.</li>
  <li>Ghosting effect of old monochrome CRT displays.</li>
  <li>Closely resembles the Matrix seen in the background during Neo and Cypher’s
conversation.</li>
</ul>

<p>With no dependencies, compilation is trivial:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cc -O3 main.c -o matrix
$ ./matrix
</code></pre></div></div>

<h2 id="how-does-it-work">How does it work?</h2>

<p>The program tracks the state of the terminal - characters, background and
foreground colors, shading levels, cursor position - using multiple internal
data buffers. On each frame, it updates these buffers and repaints the screen
using ANSI escape codes:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>static void term_print(const matrix *mat, size_t row, size_t col)
{
    size_t idx;
    idx = mat_idx(mat, row, col);
    wprintf(L"\x1b[%d;%dH\x1b[38;2;%d;%d;%dm%lc",
        row, col,
        mat-&gt;rgb[idx].color[R],
        mat-&gt;rgb[idx].color[G],
        mat-&gt;rgb[idx].color[B],
        mat-&gt;code[idx]);
}
</code></pre></div></div>

<p>The ghosting effect, the signature feature of this implementation, works by
scaling and mixing the RGB channels:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>static void mat_shade(matrix *mat, size_t row, size_t col) 
{
    unsigned char *color;
    color = mat-&gt;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;
}
</code></pre></div></div>

<p>The ghosting function emulates the screen decay by gradually transitioning each
raindrop’s color towards the background color. This approach provides two key
benefits: straightforward color configuration that integrates naturally with
Unix ricing (desktop customization) and high-fidelity recreation of the Matrix
aesthetic.</p>

<h2 id="customization">Customization</h2>

<p>While you can adjust almost every aspect, including its speed, glitch
frequency, and rain density, the most useful settings for customization are the
color scheme and character set.</p>

<p>There are three color settings: head, tail, and background. You can configure
them by setting the <code class="language-plaintext highlighter-rouge">COLOR_*_RED</code>, <code class="language-plaintext highlighter-rouge">COLOR_*_GRN</code>, and <code class="language-plaintext highlighter-rouge">COLOR_*_BLU</code> definitions
in main.c.</p>

<p>The <code class="language-plaintext highlighter-rouge">UNICODE_MIN</code> and <code class="language-plaintext highlighter-rouge">UNICODE_MAX</code> values control the Unicode block used. For
example, setting them to <code class="language-plaintext highlighter-rouge">0x30A1</code> and <code class="language-plaintext highlighter-rouge">0x30F6</code> rains Katakana (if a font that
supports Katakana is present on the system):</p>

<p><img style="width: 100%;" src="katakana.png" /></p>

<p>Files: <a href="source.tar.gz">source.tar.gz</a></p>
</div>
          <p class="post-author right">by W. D. Sadeep Madurange</p>
        </div>
      </div>
    </main>

    <div class="footer">
  <div class="container">
    <div class="twelve columns right container-2">
      <p id="footer-text">&copy; ASCIIMX - 2025</p>
    </div>
  </div>
</div>


  </body>
</html>