ntsc-crt
信号レベルの NTSC: コンポジット波形そのものを、三つのソースからエンコードし、四種類のフィルタで引き剥がし、五段の CRT モデルで表示する。どの段にも、失敗できる検査がある。
6502 の仕事はチップをスイッチのレベルで模擬する。こちらが模擬するのは、コンソールとブラウン管の間の信号そのもの: コンポジット波形を色副搬送波 1 周期あたり 12 サンプルで、レートを浮動小数ではなく厳密な有理数 12 x 315/88 MHz として保持する。二つのプロジェクトは NES で出会う。エンジンの梯子の機械がドットを出し、こちらがドットを波形に、波形を蛍光体に変える。

どの段も実物に照らして検査され、どの検査も失敗できる
三つのソースが一つの波形型に収束する。NES のドット列は PPU と同じやり方でエンコードされ、レベルは二重に確認して転記した実測電圧表から来る。任意の RGB フレームバッファは SMPTE ST 170M の条項そのものに照らした放送エンコーダを通り、公表されたカラーバーのレベルまで一致を求められる。キャプチャ波形だけは位相を自分で獲得しなければならないソースで、同期とバーストにロックし、模擬キャプチャカードを通した往復で証明される(注入した 50 ppm のレート誤差を 5 ppm 以内で発見する)。
デコードとは、混ざった色と明るさをもう一度引き剥がすことで、ここにはそのやり方が四つあり、それぞれ別々に検証される。ノッチフィルタは安価な 1980 年代のテレビがやっていたこと。2 ラインコムは NES の信号ではきっぱり拒否される: 隣接する行は 120 度ずれていて打ち消せないから、選ぼうとすると黙って劣化した絵ではなく、理由付きのエラーになる。3 ラインコムが NES に合うやり方で、三つの行の色位相が正確に打ち消し合う。フレームを平均する時間コムは、仕様が間違えていたやつだ。下に書く。
CRT はモデルであり、そう名乗る: ビーム、走査線、蛍光体の残光、マスク、幾何。パラメータはすべて手で選んだ値で、そう明記され、モデルには照らす実物が残っていないから解析的テストで保持される。そして木全体が MUTATE=1 でもう一度スイートを走らせ、フィルタ係数とレベル表をわざと壊す: 33 個のテストが赤にならなければならない。失敗できない検査は検査ではないからだ。
仕様自身の数字のうち三つが、実測に耐えなかった
このプロジェクトの元になった仕様は、自らの事前計算値をすべて「テストが確認すべき主張」と宣言していた。そのうち三つが落ち、それぞれの訂正はいま、それを強いたテストの隣で現行の仕様に載っている。
- 有名な 60.0988 Hz は実在するが、別の量に属する。NES のフルフレームは正確に 60.09848 Hz と実測される。60.09881 Hz は短フレームが交互に入る 2 フレーム平均で、プレイヤーが実際に見るレートだ。三つの NES レートはいまや各自のテストで留められ、二度と混同できない。
- 仕様どおりの時間コムは存在できない。仕様は、描画有効時のフレームが 180 度離れるから 2 フレーム平均でクロマが消える、と言った。仕様自身の幾何の節が述べる残差は 120 度と 240 度で、実測も一致する: 2 フレーム平均は減衰させるだけだ。フルフレーム 3 枚なら厳密に打ち消し、出荷されたのはそのコムである。
- 古典的な帯域幅は歴史的注記であって、規格ではない。Y は 4.2 MHz、I は 1.3、Q は 0.4、と誰もが引用する。手元にありハッシュで留めた一次規格は、Y を無制限のままにし、色差チャネルを等帯域とする。I/Q の分割値は規格自身の NTSC-1953 継続注記だ。
照合用の資料はハッシュで留められ、不一致にはすべて名前がある
NES パイプラインは blargg の nes_ntsc 0.2.2 と比較される。死んだ正規 URL の Wayback Machine 収集から回収し、ハッシュで留めたもので、テスト装置専用(LGPL)であり出荷物には決して入らない。二つのパイプラインが食い違う所では、差は許容誤差に吸収されず、テスト付きで特定の段に帰属される: レベルの丸めは彼のもの、強調近似も彼のもの、デコーダ行列とガンマは双方正当。統合表が各項を大きさ付きで挙げる。
放送エンコーダは SMPTE ST 170M-2004 そのもの(SMPTE のリポジトリから取得しハッシュで固定)に照らされ、公表カラーバー列を規格自身の条項から再導出するところまで確認される。NES のレベル表は、同じ Wiki 版を独立に二回転記し、全 43 個の数値が一致して初めて受理された。
カラーバーより先に、実機がパイプラインに届いた
2026-09-02、前面ローダーの NES と『スーパーマリオブラザーズ / ダックハント』のカートリッジが、うちのオシロスコープと出会った。生のコンポジット記録が 5 本、各 1200 万サンプル、125 MSa/s。ビデオピンから直接で、キャプチャカードもデコーダチップも経路にない。以下はすべて、その記録からリポジトリ自身のリカバリで実測したものだ。

最初のデコードは、示唆的な形で間違った。リカバリは放送の幾何を仮定していたが、NES は放送ではない: 1 行は副搬送波 227 と 3 分の 1 周期(グリッドで 2728 サンプル。放送は 2730)で、バースト位相は行ごとに半周期ではなく 3 分の 1 周期進む。間違ったモデルでデコードすると、各行が前の行より少しずつ色相回転して着地し、フレーム全体を色がなだらかに転がり落ちる。同じ 2 サンプルの偏りがスコープのクロックを 733 ppm 遅いと誤測定した。NES プロファイルでは同一の記録が -7 to -19 ppm と実測される。修正の recover_nes は合成 NES キャプチャで証明され、テストに仕込まれた妨害は放送の仮定そのもの: 実機が暴いた間違いを、二度と戻れないようスイートに残してある。

幾何が正しくなったところで、一時停止した World 1-1 の空が、一族自身の合成に対して採点された最初の実領域になった。同じ色 $22 を転記済みレベル表から生成し、同一経路でデコードして比べる。輝度は 0.003 以内、色相は 0.6 度以内で一致する。彩度は一致しない: 実機のクロマは 28 パーセント熱い(0.448 に対して 0.573)。この差は本物の所見で、許容誤差を広げて隠したら元も子もない。終端していないプローブ経路がクロマ振幅をよく見せているのか、実 DAC の AC 振幅が表の DC 実測値を本当に超えているのか。75 オーム終端での再キャプチャ一回が決める。



ここの数字は、テストを走らせ直した実測から来ている
上の物語はリポジトリのマイルストーン報告から来ているが、下の数字はその写しではない: 2026-09-04 に、記録されたコミットでプロジェクト自身のスキャナと全テストスイートと MUTATE=1 をもう一度走らせ、このページはその走行が書いたものだけを読む。
ベンチはパイプラインを生で走らせる
ライブベンチはこのパイプラインをページ内で走らせ、NES のドットを入れてデコード済みの画素を出し、ドリフトのカウンタを見せる。ブラウザでの実測はノッチフィルタで毎秒 41.5 フレーム以上、3 ラインコムで 44.4(perf-report run 2026-09-02, wasm+simd128 (the shipped bundle), node v24, Ryzen 5 5600X, low end of the spread over three fresh processes)。ソース自身の 60.09881 Hz に迫る速さで、ベンチは約束ではなく実際に出たレートを表示する。
まだ無いもの
- 実記録の検査のうちカラーバー側は開いたまま。実機キャプチャは端から端までデコードできるようになったが、検査は 75 パーセントの標準カラーバー 7 本を求め、ゲームカートリッジはそれを描かない: テスト ROM を待っている。手順は 1 ページ。
- 上の彩度の疑問には設計済みの実験が待っていて、それは走った: 同じ実機を 75 オームのフィードスルー終端に通す。プローブ経路のお世辞と DAC 自身の振る舞いを、それが切り分ける。コンポジット深掘りは、終端した信号をスコープからレベルごとに読む。
- 速くしたレバー(クロマ・ローパス前のデシメーションと、ベクトル化器のために組み替えた畳み込み)は、作られる前に M2 レポートで名指しされていたものだ。変更の間も、リファレンスとの固定済みの比較はすべて通ったままだった: 速さは、上の数字が再検証されたのと同じコミットから来ている。
リポジトリは公開で MIT: github.com/tinymachines/ntsc-crt。6502 の木と違って内部にライセンス境界はない: ダイ・データを一切埋め込まず、唯一の LGPL 部品はネイティブのテストオラクルで、出荷物には含まれない。