世界を動かす技術を、日本語で。

WriteUp: マトリックスレインを音に変えるx86の16バイト

概要

  • 16バイト のx86アセンブリで実現された Sierpinskiフラクタル の描画とオーディオ化
  • BIOSビデオモード初期化テキストバッファ操作 の詳細
  • XORによるセル・オートマトンスピーカー出力 の連携
  • メモリステップ幅 による 音・映像パターンの変化 解説
  • ハードウェア依存性実行環境ごとの違い への考察

16バイトx86アセンブリによるSierpinskiフラクタル生成

  • Outline Demoparty 2026年5月、Ommen, NL で発表
  • 16バイト のx86リアルモードDOSアセンブリによる極限的アルゴリズム密度の探求
  • ビデオメモリ を計算空間とし、 Sierpinskiフラクタル を無限描画
  • 描画データ をそのまま PCスピーカー のオーディオ信号として出力

コード詳細

  • int 10h: BIOSによるビデオモード0(40x25テキスト)初期化
  • mov bh, 0xb8 / mov ds, bx: データセグメントを 0xB800 (テキストバッファ)に設定
  • L: lodsb / sub si, byte 57 / xor [si], al / out 61h, al / jmp short L: メインループ
    • lodsb: SIで指すバイトをALにロード、SI++
    • sub si, 57: SIを56バイト逆方向へ移動(結果的に-56バイト/ループ)
    • xor [si], al: メモリ内容とALをXORし保存
    • out 61h, al: ALの値をスピーカーポートに出力
    • jmp short L: ループ継続

初期化とテキストバッファの均一性

  • BIOS int 10h でテキストバッファ全体を ASCII 0x20(スペース)/ 属性0x07 で初期化
  • 均一なデータ がセル・オートマトンの正確な進行を保証
  • ランダムなメモリ内容 ではパターンが乱れるリスク

加法的プレフィックスサムの数理

  • 理想状態 として全メモリ0でモデル化
  • add で進めると、AL=2で16バイトごとに加算し プレフィックスサム 形成
  • 4096ステップ でセグメント全体を1周(65536/16=4096)
  • ALの値 はパスごとに 二項係数 で増加
    • $$A^{(p)}[k] \equiv 2 \binom{k+p}{p-1} \pmod{256}$$

XORによるSierpinskiパターン

  • XOR へ切り替えると、加算のキャリーを無視し ビットプレーン のみ伝播
  • AL=2 (Bit1のみON)により Rule 60 型セル・オートマトンへ
  • Lucasの定理 により、XOR進行は加法表のBit1と一致
  • Sierpinski三角形 のパターンが明確に浮かび上がる

オーディオ化:fractalを音に

  • out 61h, al :ALのBit1が PCスピーカーコーン を直接制御
  • フラクタル進行 がそのまま パルス幅・周波数 の異なる矩形波に
  • CPU速度 がサンプリングレートを決定
  • パターン変化音の高さ・リズム として聴覚化

56バイトステップの効果

  • sub si, 57 で-56バイトずつ逆方向移動
  • 65536バイト/56=8192ステップ でメモリ全域を7周してカバー
  • 1周あたりのステップ数倍増音の基本周波数が1オクターブ低下
  • ASCIIキャラクタバイト のBit1がスピーカー制御、残り7bitが画面上にカオスな文字列生成

視覚パターンの構造:斜めシア

  • テキストモード は1キャラ2バイト、1行40キャラ(80バイト)
  • -56バイト移動≡+24バイト(mod 80)12カラム右/1行上 に進行
  • gcd(12, 40)=4 なので 10本の等間隔縦柱 として描画
  • フラクタル が画面上で 斜めにシア された形で現れる

実行環境とメモリ依存性

  • BIOSやエミュレータ ごとに初期メモリ状態に差異
  • XOR進行 が既存メモリ内容に依存し、 表示・音色 が環境で変化
  • 完全再現 には全メモリの明示的初期化が必要だが、16バイト制限では不可能
  • この不確定性もデモシーン的魅力

ご覧いただきありがとうございました。

Hackerたちの意見

「wake up! 16b」(Outline Demoparty、2026年5月、オムメン、オランダ)は、ビデオメモリを使ってシェルピンスキーのフラクタルを計算し、それを音声として再生する16バイトのMS-DOSプロダクションです。ビデオ: https://youtu.be/MvycyU-kLjg | Pouet: https://www.pouet.net/prod.php?which=106210 16バイトのコード:

int 10h ; ビデオモード0を初期化
mov bh, 0xb8 ; VRAMセグメントを設定
mov ds, bx
L: lodsb ; [SI]をALにロード、SIをインクリメント
sub si, 57 ; ポインタを後ろに移動
xor [si], al ; セルオートマトン
out 61h, al ; PCスピーカー出力
jmp short L ; 無限ループ
  1. キャンバス: int 10hは、40x25のテキストグリッドをASCII 0x20とカラー0x07で均一に初期化します。この安定した均一な空間は、セルオートマトンが静的に崩れないようにするために必要です。
  2. フラクタル(ルール60): このループがaddを使っていたら、二項接頭辞和を生成していました: A^(p)[k] = 2 * C(k+p, p-1) mod 256 でも、addxorに置き換えることで、算術キャリーが捨てられ、ビットプレーンが分離されます。これにより、数学が純粋なセルオートマトンに変わり、ウルフラムのルール60にマッピングされます: Cell^(p)[k] = Cell^(p-1)[k] XOR Cell^(p)[k-1] ビット1の伝播を5回のパスで視覚化すると(X = セット): P1: X X X X X X X X P2: . X . X . X . X P3: X . . X X . . X P4: . . . X . . . X P5: X X X . . . . X P6: . X . . . . . X P7: X . . . . . . X
  3. 音声: ポート61hはビット1を使ってPCスピーカーのコーンを物理的に動かします。シェルピンスキーの幾何学は、正方形波の音声指示として直接作用します: 交互のビット(P2のように)は高周波を生み出し、まばらな行(P4)はリズミカルな休符を作ります。
  4. -56バイトのステップ: ポインタのネット移動はループごとに-56バイトです。
  • ビジュアル: 80バイト幅のグリッド上で、このオフセットはフラクタルを対角に10本の均等に間隔を空けた垂直の柱に切り取ります。
  • 音声: 56は64KBセグメントを均等に割り切れないため、1サイクルを完了するのに8192ステップ(7回のフルラップ)が必要です。マクロサイクルを倍にすると基本周波数が半分になり、音声がちょうど1オクターブ下がります。
  1. ハードウェアの特異性: 理論的な数学はゼロのメモリを期待しますが、XOR操作はBIOSの0x20/0x07初期化と激しく衝突します。これにより、純粋な三角形が擬似ランダムなASCIIグリフのカスケードに変わります。生のRAM状態に完全に依存しているため、視覚的および聴覚的出力は特定のマシンやエミュレーターに非常に敏感で、単純な数学的特異性がユニークな視聴覚フィンガープリントに変わります。

よくやった!これを思いついたきっかけは何だったの?

いつも美しい作品だね!見ることができて嬉しい。

いいね!

シェルピンスキーのフラクタルは雨のエフェクトとどう関係してるの?

TLDR: 各タイムステップで、別のシェルピンスキー三角形のラインが a) スピーカーで再生され b) ステップサイズ56で画面に描かれる。動きを感じることはできるけど、実際には見えない。8192 "ピクセル幅"だけど、1行の文字はたったの80バイトだから。もっともっと大きな画面なら三角形が見えるかも。もしくは、"ピクセルをスキップ"せずに一度に全部描けば、見えるはず。実際、同じパーティーでそれをやったバージョンがあるけど、特定の音が失われちゃったんだ。 https://www.pouet.net/prod.php?which=106206 https://www.youtube.com/watch?v=OVk-iP93ZEs

それは魔法に違いない。こんな短いコードで実現できるとは思えない。

まだちょっとそうだね!純粋な音はそんな風に聞こえるべきじゃないから、メモリの設定や初期化(グラフィックカード関連)を掘り下げて、なぜ少し違って聞こえるのかを100%説明しなきゃ。

魔法か神秘だね。可能なだけじゃなくて、見つけられるってのがすごい。言葉が出ないよ。

すごいね。コメントが大きい。

これ、マトリックスレインを音に変換すると思ったけど、視覚と音の両方があるんだね。すごい!しかも、ちゃんとしたトラックみたいで、今頭の中で音楽がぐるぐる回ってる。これはプログラムなのか、それとも何かの秘密のキーで化け物を解放するのか?よくわからん!

同じ作者が数年前に別のデモ「Memories」について長い記事を書いてたよ。めっちゃ面白いから読んでみて!http://www.sizecoding.org/wiki/Memories

もっとリラックスした「雨」のデモを見たいなら、「Rainy 32b」っていう32バイトのx86デモをチェックしてみて!: https://www.pouet.net/prod.php?which=86923 https://www.youtube.com/watch?v=iCgIQuPHb5w

おお、これも気に入ってくれて嬉しい!面白い話なんだけど、COVOX版を持ってて、そっちの方が音が良かったんだけど、たまに動かなくて…だから「ちょっと悪い」バージョンを出したんだxD

6位だった。WriteUpは2位。ほかのエントリーも気になるね。

pouet.netには、こんな32バイトのドラゴンフラクタルみたいな小さなデモがいくつかあるよ: https://m.pouet.net/prod.php?which=63522 こんな少ないバイト数で作れるなんて、ほんとすごい!

ああ、これは俺の初期のデモシーン作品の一つだよ :) 実は、数日前にこのの改造版CGA 8086を古いハードウェアで動かす機会があったんだ!https://youtu.be/XLrjChvJf0k

これってC64デモ「A Mind Is Born」の逆をやってるみたいだね(https://linusakesson.net/scene/a-mind-is-born/)。あっちは音楽を先に作って、それを同時にグラフィックスとして解釈してる。もちろん、あのC64デモはこのx86のやつに比べたらすごく大きいけど :)

そういう意味ではタイトルが誤解を招くね。2014年のオリジナル「m8trix」はすでに画面に擬似ランダムな文字を表示してたし(8バイトで、その後7バイトで) https://www.pouet.net/prod.php?which=63126 どうやって「いい音にするか」ずっと考えてたんだ。でも「wakeup」の開発の時系列では音が先だったんだよね。「聞こえるものが見える」から、実際にはあまり関係ないけど、「シェルピンスキーの音をマトリックスの雨に変える16バイト」って言ってもいいかもね =)

一番好きなデモは「Freespin」で、コンピュータなしでフロッピードライブだけで動いてるんだ。クレイジーなやつだよ。 https://www.youtube.com/watch?v=zprSxCMlECA

お気に入りは「spongy」で、128バイトのメンガー・スポンジフラクタルを水中で旅するやつだよ: https://www.pouet.net/prod.php?which=53871 https://www.youtube.com/watch?v=36BPql6Nl_U 技術的な達成よりも、その不気味な美しさに感動してる。たとえコードが何倍も大きくても、やっぱり素晴らしいと思う。

なんだこれ。マジで。すごい! ちょっと悪態ついてごめんけど、今まで見た中で一番クレイジーなデモだよ。動画のトップコメントを残しておくね:「魔女はもっと小さな魔法で焼かれてきた」

そのデモは見たことなかったけど、君の説明からC64のフロッピードライブだろうなって思った。C64と同じCPUを使ってて、埋め込みファームウェアがファイルサーバーみたいに動いてるんだよね: https://en.wikipedia.org/wiki/Commodore_1541 https://en.wikipedia.org/wiki/Commodore_DOS