ゲームボーイカラーにリアルタイム3Dシェーダーを組み込みました。

2026/02/09 1:28

ゲームボーイカラーにリアルタイム3Dシェーダーを組み込みました。

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

(主要ポイントをすべて取り入れた)**

この記事は、作者がリアルタイムのGame Boy Colorデモを構築し、通常は機器の制限されたCPUでは過剰な負荷になるようなノーマルマップシェーディングで軌道上に光と回転オブジェクトを描画する方法について説明しています。
主要な技術的詳細は次の通りです:

  • シェーダー計算 – ランバート積(Lambertian dot product)を使用しますが、GBでは球面座標版を採用しています:
    (v = \sin N_{\theta},\sin L_{\theta},\cos(N_{\phi}-L_{\phi}) + \cos N_{\theta},\cos L_{\theta})。
    ここで (L_{\theta}) は固定され、プレイヤーは (L_{\phi}) を制御するため、ピクセルごとの計算量が減少します。

  • ノーマルの格納 – ノーマルは3バイトタプル

    (Nφ, log(m), b)
    にパックされています。
    log(m)
    はハードウェアサポートなしで乗算を可能にします。

  • 乗算トリック – ルックアップテーブルを使用:

    x·y = pow[log(x)+log(y)]
    、符号は
    log
    のMSB によって処理され、XOR トグルで結果が8ビット分数範囲内に収まるよう調整します。

  • パフォーマンス – 各ピクセルは約3回の加算/減算と2回のルックアップを必要とします。シェーダーはフレームあたり少なくとも15タイル(60 fps の CPU バジェットの約89 %)を処理します。セルフモディファイングコード(

    sub a,8
    をメモリからロードする代わりに使用)はピクセルあたり約12サイクルを節約し、実行時間を約10 %改善します。

  • ノーマルマップエクスポート – ノーマルは Blender で生成されます:ティーポット AOV 用の PNG シーケンスと Game Boy シーン用にハードコードされた暗号マッテ(cryptomattes)カラーを使用し、異なるレイアウトがパフォーマンスに与える影響を示しています。

ソースコードと ROM は GitHub (

https://github.com/nukep/gbshader
) にホストされています。
このプロジェクトは、制約のあるハードウェア上で高度なシェーディングが実現可能であることを示し、レトロゲーム愛好家や低消費電力デバイス開発者にとって学習ツールとなります。将来の作業では、シェーダーのさらなる最適化やより複雑なシーンへの拡張が考えられますが、現在の焦点は既存の制約内での実現可能性を証明することにあります。

本文

デモンストレーション

私はリアルタイムで画像を描画する Game Boy Color 用ゲームを作成しました。
プレイヤーは軌道上の光を操作し、オブジェクトを回転させます。


3D ワークフロー

初期レイアウト調整

本プロジェクトに着手する前、Blender 上で見た目を試してみました。
私の判断では十分に良く見えたので、そのまま進めることにしました!
ブレンダー・モンキーの各ノーマルに小さなランダムベクトルを足し、“擬似ディザリング” を実現しています。


Blender → ノーマルマップワークフロー

TL;DR: Cryptomatte とカスタムシェーダでノーマルマップを調整します。

ノーマルマップ作成に使うソフトウェアは重要ではありませんでした。Blender が最も手軽だったからです。

  • Teapot(テープト): ただテープトを入れ、カメラを回転させて正規化された AOV を PNG シーケンスとしてエクスポートしました。
  • 回転する Game Boy Color: 特定の色を固定したい場合は、コンポジターで Cryptomatte を使って対象のジオメトリを識別し、ハードコードされた値を出力します。画面ジオメトリは別途レンダリングされ、Cryptomatte で最終イメージに合成されます。

数学的背景

ノーマルマップ

ノーマルマップはベクトル場をエンコードしており、その青みがかった基準色は XYZ を RGB に対応させる(+Z が進行方向)ためです。3D グラフィックスでは不可欠な技術です。

出典: 自作品 (Danny Spencer)。 Suzanne モデル © Blender Foundation.

ランバートシェーダ(ドット積による)

最も単純なシェーディングはドット積を使用します:

v = N · L

ここで N はノーマルベクトル、L は光源位置(または負の光方向)です。

成分ごとに展開すると:

v = NxLx + NyLy + NzLz

定数光ベクトルは遠方や太陽光をモデル化します。

球面座標

Game Boy で計算を高速化するため、球面座標で別のドット積式を使用しました。
一点は半径 r、極角 θ(シータ)、方位角 φ(ファイ)で表されます: ((r,\theta,\varphi))。

二つの単位ベクトルのドット積は次のように簡略化できます:

v = sinθ₁·sinθ₂·cos(φ₁−φ₂) + cosθ₁·cosθ₂

以前使っていた変数名を当てはめると:

v = sinNθ · sinLθ · cos(Nφ−Lφ) + cosNθ · cosLθ

Game Boy で動かすための工夫

ROM にノーマルマップをエンコード

性能向上のため を定数に固定しました。プレイヤーは を操作し、軌道光の効果を作り出します。

定数 (m) と (b) を抽出:

m = sinNθ · sinLθ
b = cosNθ · cosLθ
v = m·cos(Nφ−Lφ) + b

ROM には各ピクセルを 3 バイトのタプル ((Nφ, \log(m), b)) として格納します。

なぜ
log(m)
を使うか

Game Boy の SM83 CPU は乗算と浮動小数点演算がありません。対数を使えば積を和に変換できます:

log_b(x·y) = log_b(x) + log_b(y)
x·y      = b^(log_b(x)+log_b(y))

二つのルックアップが必要です:対数テーブルとべき乗テーブル。

  • 対数空間: 8 ビット分数; 符号は MSB にエンコード。
  • べき乗表: 符号切替を XOR で処理します。

すべてのスカラーは –1.0〜+1.0 の範囲に収まり、8 ビットで安全に保持できます。


パフォーマンス

ピクセルごとの計算

v = m·cos(Nφ−Lφ) + b

これをルックアップで書き換えると:

v = pow( m_log + cos_log(Nφ−Lφ) ) + b

ピクセルあたりの操作数:

  1. 減算
  2. cos_log
    へのルックアップ
  3. 加算
  4. pow
    へのルックアップ
  5. 加算

合計:3 回の加減算、2 回のルックアップ。

フレームタイミング

  • CPU 周波数: 約8.388 MHz(≈139,810 T‑cycles/フレーム at 60 Hz)。
  • 処理タイル数: ≥15 タイル/フレーム(行が空の場合は増加)。
  • 1 タイルあたりのサイクル数: 約123,972(最悪ケース)→ フレーム時間の約89 %。

自己修正コード

ホットパスでは毎フレーム約960ピクセルを処理します。
実行時に読み込む値をハードコーディングした即値に置き換えると、1 ピクセルあたり12サイクル節約でき、シェーダ全体のランタイムが約10 %短縮されます。

SM83 アセンブリ例:

; 遅い: 28 サイクル
ld   a,[Ltheta]     ; HRAM から読み込み
ld   b,a
ld   a,[hl+]
sub  a,b

; 速い: 16 サイクル
ld   a,[hl+]
sub  a,8            ; 即値

自己修正コードは、命令のオペランドを変更して減算を高速に保ちつつ の変更も可能にします。


AI 実験

“AI Will Be Writing 90 % of Code in 3–6 Months” – Dario Amodei (2025)

  • AI を使ったこと:

    • OpenEXR レイヤーを読み込む Python スクリプト。
    • Blender‑Python の一部スニペットでシーン設定。
    • Game Boy Color 用の SM83 アセンブリ(ダブルスピード、VRAM DMA)スニペット。
  • 試みたが失敗したこと:

    • SM83 用初期シェーダコードを AI に生成させること。
  • 使わなかったこと:

    • 本記事の執筆、アルゴリズム設計、ルックアップ表作成、SM83 アセンブリ全般、3D アセット、プロジェクトの創造的“魂”。

Claude Sonnet 4 を試し、擬似コードから SM83 アセンブリを生成させました。機能はあるものの遅く、エラーも多く(例:SM83 は Z80 だと誤解)。最終的に手動で全て書き直しました。


結論

  • パフォーマンスが重要: 自己修正コード、対数ベースのルックアップ、ハードコーディングされた即値が実際の差を生みます。
  • AI はボイラープレートに有効ですが、制約が厳しい環境では手作業でチューニングしたアセンブリが不可欠です。

この記事や私の YouTube 動画(https://www.youtube.com/watch?v=SAQXEW3ePwo)を共有・コメントしていただけると幸いです。Bluesky への投稿後は更新します。

同じ日のほかのニュース

一覧に戻る →

2026/02/08 12:09

ご協力いただけるとのこと、ありがとうございます! 整えたいテキストをお送りください。すぐに丁寧に仕上げさせていただきます。

## Japanese Translation: ``` ## Summary Vouch は、貢献者がコードベースの設定可能な部分と対話する前に「証明(vouch)」される必要がある軽量なコミュニティトラスト管理システムです。また、明示的に「非承認(denounce)」を行うことでそのような対話をブロックできます。信頼関係は単一のフラット `.td` ファイル(Trustdown フォーマット)に保存されます。このファイルでは各行が1つのハンドルを保持し、オプションでプラットフォーム接頭辞(`platform:username`)と先頭マイナス記号が付けられたユーザーは非承認者として扱われ、その後に任意の理由が続きます。GitHub Actions は標準搭載の統合を提供します: - `check-pr` は `pull_request_target` で実行され、PR 作成者のステータスを検証し、未承認または非承認のプルリクエストを自動的に閉じることができます。 - `manage-by-discussion` と `manage-by-issue` は協力者がディスカッションやイシューコメントを通じて証明または非承認を行えるようにします。 Nushell CLI モジュールにより手動制御も可能です:`vouch add <user>`、`vouch denounce <user> [--reason] --write`、`vouch gh-check-pr <pr_id> --repo owner/repo`(ドライランまたは自動閉鎖)、および `vouch gh-manage-by-issue <pr_id> <comment_id> --repo owner/repo` などのコマンドがあります。ステータスチェックは終了コードを返します(`0 = vouched`、`1 = denounced`、`2 = unknown`)。 Vouch は任意のコードフォージで動作するよう設計されていますが、GitHub 統合がすぐに使用できる状態で提供されます。現在は実験段階であり、Ghostty プロジェクトによってテスト中です。このプロジェクトはコミュニティからのフィードバックをもとに機能を洗練しています。今後の計画としては、リポジトリ間で信頼リストをリンクし信頼ネットワークを構築すること、プラットフォームサポートの拡張、および自動化機能の強化が挙げられます。 *検証された参加を強制することで、Vouch は悪意ある貢献を減らし、コードレビューのワークフローを合理化し、安全なコラボレーションをオープンソースメンテナ、企業チーム、および広範なソフトウェア開発エコシステムに奨励することを目指します。``` ```

2026/02/09 6:52

米国におけるソーシャルメディア利用の変化 2020–2024:減少・断片化・極化 (2025)

## Japanese Translation: ## Summary: 本研究は、米国におけるソーシャルメディアの利用が縮小し、より断片化していることを示し、残存する活動の中で政治的に極端なユーザーが支配していると結論付けている。2020–2024年の全国代表データを分析した結果、プラットフォーム全体の利用率は減少し、対象者はやや高齢化し教育レベルも上昇しており、投稿活動が共和党ユーザーへと明確にシフトしている—特にTwitter/Xで顕著だ。既存研究では若年層と高齢層の両方で減少傾向が指摘されていたが、本稿は新しいデータを用いてそれらの発見を更新し、TikTokやRedditはわずかに成長しているものの、Facebook、YouTube、Xは市場シェアを失っていることを示唆している。予測される動向として、オンライン公共圏はより小規模で鋭く、極端な意見が支配するようになるとされ、一般ユーザーは離脱しつつも党派的声は依然として高いままである。この結果は、デジタル環境のさらなる分極化を招き、プラットフォームに広範なオーディエンスを維持する課題を投げかけるとともに、広告主や政治戦略家、民主的議論に関心を寄せる政策立案者にも影響を与える可能性がある。 ## Summary Skeleton **What the text is mainly trying to say (main message)** 本研究は、米国におけるソーシャルメディアの利用が縮小し、より断片化していることを示し、残存する活動の中で政治的に極端なユーザーが支配していると結論付けている。 **Evidence / reasoning (why this is said)** 全国代表性のある2020–2024年のANESデータは、全体的なプラットフォーム利用率の低下、やや高齢化し教育レベルが上昇したオーディエンス、および投稿活動が共和党ユーザーへとシフトしている—特にTwitter/Xで顕著だという事実を示している。 **Related cases / background (context, past events, surrounding info)** 以前の分析では若年層と高齢層の両方で利用減少が報告されており、本稿は新しいデータでそれらの発見を更新し、TikTokやRedditはわずかに成長している一方でFacebook、YouTube、Xは市場シェアを失っていることを指摘している。 **What may happen next (future developments / projections written in the text)** オンライン公共圏は小規模で鋭く、よりイデオロギー的に極端になると予測されており、カジュアルユーザーは離脱しつつも党派的声は依然として発言力を保っている。 **What impacts this could have (users / companies / industry)** ユーザーはより分極化したデジタル環境に直面し、プラットフォームは広範なオーディエンスの維持に課題を抱えることになる。トレンドは広告主や政治戦略家、民主的議論に関心を寄せる政策立案者にも影響を与える可能性がある。

2026/02/09 7:25

SGI O2 のプロンプトを逆解析する (原文: “Reverse Engineering the Prompt for the SGI O2”)

## Japanese Translation: > 著者は **`ip32prom-decompiler`** を開発しました。このツールは、SGI O2 マシンで使用されている 512 KiB の IP32 PROM を *ビット単位で同一* な MIPS アセンブリ (.S) ファイルに逆アセンブルし、ラベル、コメント、および関数境界を完全に含みます。 > > 各「SHDR」セクション(長さ・名前・バージョン・タイプフラグ(コード/メタデータ)・任意のメタデータ・2 つのチェックサム)を解析することで、ツールはファームウェアの 3 つのサブセクションを再構築します:`.text` は `0x81000000` に、`.rodata` は `0x81048e70` に、そして `.data` は `0x81054100` に配置されます。チェックサムアルゴリズムは 32‑ビット語全体の 2 の補数和であり、セクションデータと SHDR 自体の両方に適用されます。 > > 到達可能なコードを幅優先探索し、相対/絶対分岐、ジャンプテーブル、および構築されたアドレスに特別な処理を行うことで、バイナリ命令の約 **90 %** を回復します。可視化(XPM 画像)はコード、ヘッダー/チェックサム、ASCII データ、アクセス済みメモリ、nop パディング、および未知のバイトを色分けし、手動解析を支援します。また、コンパイラ遅延スロットによって導入された到達不能またはデッドコードが検出され、注釈付きで記録されます。 > > 逆アセンブルされたアセンブリは同一の ROM イメージに再構成でき、PROM 構造を完全に理解していることを確認します。ファームウェアがこれからゼロから再構築可能になったため、将来の CPU アップグレード(例:新しいプロセッサの導入)は SGI のサポートに依存せずに実行できるようになり、O2 の PROM が変更不可能であるという長年の制約を克服します。この成果は、ホビイストやレトロコンピューティング愛好者に対しても、レガシーファームウェアのリバースエンジニアリング手法として信頼性の高い方法を提供します。 *この改訂版サマリーは、リストからすべての主要ポイントを取り入れつつ、曖昧または推測的な表現を排除して明確に保っています。*