
2026/03/05 11:38
**Z80 Sans – フォントで実装したディスアセンブラ (2024)**
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Summary
Z80 Sans は、Hexadecimal Z80 命令バイトを GSUB と GPOS テーブルを介して視覚的なグリフに変換するカスタム OpenType フォントです。プロジェクトは
instructions.json ファイルを解析し、最大 458,752 個のユニークグリフ(各々が特定のバイト列を表す)を生成し、それらを小文字エンディアン順序、符号付きオフセット、および 65,536 グリフ制限に従うルックアップチェーンに配置します。
FontForge(Ruby インターフェース経由)で
commit 4f4907d9… から構築され、フォントは WOFF2 としてエクスポートされます。OpenType 機能をサポートする任意のプラットフォームで使用できます。事前ビルドされた z80-sans.ttf は速やかなテスト用に ./test/ ディレクトリで利用可能です;ビルド後、生成された .ttf は ~/.local/share/fonts/ にコピーされます。
インストールには Debian GNU/Linux 12、Ruby 3(
fontcustom がこのバージョンと互換性がないことに注意)、OpenSSL、ImageMagick、potrace、および fonttools が必要です。ビルドプロセスは WOFF2 をコンパイルし、RVM 2.4 のローカル OpenSSL インストール下で Ruby gem fontcustom をインストールします。
設計上の課題は、再帰下降パーサーを通じてすべてのオペランド可能性を Hex バイト列に展開し、それらをグリフへマッピングすることで対処されます。コンテキスチュアルチェーンルールは、
SET b,(IX+o) と SRA (IX+o) のような順序外のオペランドを、最後まで Hex バイトに一致させ、それぞれの変種用に専用ルックアップを生成して処理します。
既知のレンダリング不具合には、
LD (IX+o),r での間隔が不正確な点と SET b,(IX+o) におけるコンマが欠落している点があります。これらは「CTF quality」の小さな問題であり、全体的な機能には影響しません。
将来の改善としては、FontForge のスクリプタブル機能生成(
GenerateFeatureFile()、MergeFeature())を活用するか、Harfbuzz WASM を探索してさらに複雑な命令セットを処理できるようにすることが考えられます。フォントのベースグリフは Droid Sans Mono(Apache ライセンス)と Noto Sans Mono(Open Font License)から取得され、命令セットデータは maziac/z80‑instruction‑set から取得されています。
Z80 Sans は、低レベルの Z80 エミュレーション開発者や教育者が分解されたコードを明確に視覚的に表現したい場合に特に有用であり、カスタムフォントがニッチなアプリケーション向けに広範なバイナリ語彙をエンコードできることを示しています。
本文
Z80 Sans – ディスアセンブラフォント
何をするのか
Z80 Sans は16進数バイト列を読みやすい Z80 アセンブリに変換します。
OpenType の GSUB と GPOS テーブルを使って、各ニブル(0–f)を
命令語・レジスタ・アドレス・オフセットを表すグリフへマッピングします。
「好きなディスアセンブラは? それはフォントです。」
クイックインストール (Debian 12)
# 依存関係 apt install imagemagick potrace pip install fonttools git submodule update --init --recursive
FontForge
cd ./modules/fontforge/ git checkout 4f4907d9541857b135bd0b361099e778325b4e28 git apply ../../resources/fontforge.diff mkdir -p build && cd build cmake -GNinja .. ninja ninja install
woff2
cd ./modules/woff2/ make clean all
fontcustom (Ruby 2.7 必須)
rvm use 2.7 rvm pkg install openssl rvm install 2.4 --with-openssl-dir=$HOME/.rvm/usr gem update --system 3.3.22 export PATH=$PWD/modules/woff2/build:$PATH cd ./modules/fontcustom/ git apply ../../resources/fontcustom.diff gem build fontcustom.gemspec gem install ./fontcustom-2.0.0.gem
フォント生成
cp ./resources/droid-sans-mono.ttf /tmp/base.ttf ./gen.py ./resources/instructions.json # .ttf は ~/.local/share/fonts/ にコピーされます
デザイン上の課題
| 課題 | 理由 |
|---|---|
| 多くの文字 | 手動 GSUB ルールは非現実的。 |
| 巨大な組み合わせ空間 | 一部命令は最大で 65 536 × 7 = 458 752 のバリエーションがある。 |
| オーダー外のオペランド | エンコーディングとディスアセンブル時にレジスタ/オフセットの順序が異なる。 |
| リトルエンディアンアドレス | LSB グリフを先に表示する必要がある。 |
| 符号付きオフセット | 0x80–0xff のバイトは負の2補数として描画されるべき。 |
解決策は 再帰下降パーサ で全ての可能なオペランド値を展開し、
得られた命令ごとに1つまたは複数の16進ニブルグリフへマッピングします。
実装ノート
- 基本グリフ形状は Droid Sans Mono から取得。OpenType テーブルは
Noto Sans Mono の
を編集して作成。.ttx - 文脈チェーンルールで多くのルックアップを処理。
- 各ニブル(0–f)に独自グリフを割り当て、スペーシング文字で バイトやアドレス全体のマルチグリフ置換を実現。
- オーダー外ケースは専用リガチャと先読みルールでカバー。
現在確認されている問題
| 命令 | 表示結果 |
|---|---|
| |
| |
(これらは軽微な不具合で、残りの ISA は完全にディスアセンブルされます。)
今後の作業
- 手動
編集を避けるために FontForge スクリプト (.ttx
,GenerateFeatureFile()
) を活用。MergeFeature() - より大規模な命令セット向けに、Harfbuzz WASM などのフォントシェイパーを検討。
クレジットとライセンス
| リソース | ライセンス |
|---|---|
| Droid Sans Mono | Apache License |
| Noto Sans Mono | Open Font License |
| GNU LGPL v3 |
| その他すべてのファイル | MIT License |
ベースフォント: Droid Sans Mono, Noto Sans Mono。
命令セットソース: maziac/z80-instruction-set。
生データをそのまま読みやすい Z80 アセンブリへ変換する、たった一つのフォントでお楽しみください!