← [ TECH / 技術部 ] に戻る
OBSERVATION · 其の12418 · 2026.10.23

ファミリーベーシックでマシン語に挑戦【後編】マリオ風 1-1 を 4KB に入れる

◉ REC COVER · 圖版 FRM·3055

こんにちは、パレイド技術部の夏目です。ファミリーベーシック V3(任天堂、1985年)の上で、AI にマシン語(CPU 6502 が直接実行する命令列)を書かせ、スーパーマリオ 1-1 を再現したマリオ風クローンを動かしました。動画「ファミリーベーシックでマシン語に挑戦」の後編の受け記事として、動画で語り切れなかった数字の表と、打ち込み方を足します。テトリス風の前編は別の記事で扱っています。

https://youtu.be/uDjcJF1PE2I

任天堂とは無関係の、個人の制作物です。確認はすべてエミュレータ上で、実機・実テープでは確かめていません。

本記事はローカル LLM による自動執筆パイプラインで生成されました。現段階ではクラウド AI(Claude 等)の補助や人間の編集が介在していますが、pareido.jp では最終的に AI が自律的にコンテンツを制作できる仕組みの構築を目指しています。

原作の動作から取った数字

前提の条件を先に並べます。絵は自作せず、ファミリーベーシックの ROM に入っているキャラの組み合わせだけで描いています。

項目 条件
対象 ファミリーベーシック V3
範囲 1-1 のみ
使える RAM $6000〜$6FFF の 4,086 バイト(BASIC の本文と共有)
絵 ROM 内蔵のキャラの組み合わせ(自作の絵なし)
確認 エミュレータ上(実機・実テープは未確認)

点数とパレットは、記憶ではなく原作をエミュレータで動かして実測しました。連続で踏んだときの点数に「500 なんてあった?」と疑問が出たのが発端で、ROM を動かすと確かに入っていました。

項目 実測した値
連続踏みの点数 100→200→400→500→800→1000→2000→4000→5000→8000
2匹を同時に踏む 連鎖が2つ進み、1回目が 500
甲羅で倒す 500→800→1000→2000
マリオの色 $27 / $16 / $18

雲・茂み・丘の配置は、原作を最後まで走らせてネームテーブル(背景のタイル番号の並び)を採取し、そのまま取り込みました。

実装で踏んだ罠は3つです。

  • 背景の色0は白にできない。色0は全パレット共通の背景色で、パレットを変えても変わりません(PPU=画面を描く専用チップの仕様)
  • 画面が真っ黒になる。NMI(画面を1枚描き終えるたびに CPU を呼ぶ割り込み)を自前に差し替えると、BASIC が $32/$33 に持つ画面設定を自分で書き戻す必要がありました
  • 画面の上端が乱れる。スクロールの計算を NMI の中で行うと描画の休み時間に収まらず、計算はメインの処理、NMI は書き込みだけに分けて解消しました

なお動画のクローンは自動操縦で、原作より速く走ります。同じ速さの比較ではありません。

3.6KB が 4KB に入らない壁とローダ

ファミリーベーシックには、マシン語をそのまま保存・読み込みする手段がありません。マシン語は DATA 文に16進で書き、POKE でメモリに置き、CALL で呼びます。その BASIC の本文も同じ 4KB を使うので、3.6KB のマシン語は一度に入りません。

そこでパートに分け、LOAD と RUN を繰り返して積み上げます。鍵は CLEAR &Hxxxx です。これは BASIC の本文の領域と、その上の自由に使える領域を分ける命令で、上の領域に書いた値は NEW でも LOAD でも、CLEAR の値を下げても残ることを実測で確かめました。積み上げが少ない最初のパートほど本文を大きく取れるので、CLEAR を後ろのパートほど下げます。

ローダ マシン語 パート数 読み込み時間 判定
最初の分け方 3,632B 31 1,157秒 △ 起動と走行は確認。打ち込むには多すぎる
CLEAR を後ろほど下げる 3,632B 8 881秒 ○ 起動と走行を確認
公開コード(改良後) 3,746B 10 未計測 ―

読み込み時間は、エミュレータへのキーボード入力での実測です。最初の分け方では、マシン語が 100 バイト増えるごとにパートが約5つ増えていました。

動画では「3,632 バイト・8パート」と説明しましたが、公開するコードは「3,746 バイト・10パート」です。動画の作成後に機能を足して改良したためで、10パート版の読み込み時間は測っていません。公開コードの CLEAR の階段は次のとおりです(1パートの量は15バイト単位。3,746 バイトを 3,750 バイトに切り上げ、余りは0で埋めています)。

パート CLEAR 置く量
01 &H6B50 1,200B
02 &H6808 840B
03 &H65CE 570B
04 &H6448 390B
05 &H633A 270B
06 &H6286 180B
07 &H620E 120B
08 &H61B4 90B
09 &H6178 60B
10 &H615A 30B

各パートの先頭は同じ形です。mario_01.bas の冒頭を引きます。

10 CLEAR &H6B50
20 A=&H6B50:FOR K=1 TO 80:READ S$:FOR J=1 TO 30 STEP 2
30 POKE A,VAL("&H"+MID$(S$,J,2)):A=A+1:NEXT:NEXT

10行目で置き先を守り、20〜30行目で DATA の16進文字列を1バイトずつ POKE します。打ち込み方は次のとおりです(公開先の README と同じ)。

  1. mario_01.bas を打ち込んで RUN。書き込みが終わるまで待つ
  2. NEW で本文を消し、次の番号を打ち込んで RUN
  3. 最後のパート(mario_10.bas)まで繰り返す。最後のパートの CALL でゲームが始まる
  4. 先頭の CLEAR の値は変えない

コードは https://pareido.jp/files/famibasic-machinecode/README.md から辿れます。公開しているのは 4KB に収まる版だけで、動画の最後に出る約 9.6KB のディスク版(ディスクベーシック V3.0P 用)は BASIC のローダにできないため含まれません。4KB の壁そのものは、以前の記事でも扱っています。

パレイドファミリーベーシックだけでファミコンのエミュレータは書けるか(1)|CPU は完成し、4 キロバイトで止まったこんにちは、パレイド技術部の夏目です。 ファミリーベーシックの実験を続けています。今回はファミリーベーシックでファミリーベーシックの実装が可…

キャラ近似ツール:数字と見た目を分けて

人の手で一番重かったのは、原作の絵に近いタイルの組み合わせを探す作業でした。そこで AI に近似ツールを作らせました。スプライトは小マリオの12ポーズを、反転4通りと並べ替えの全組み合わせで比べます。背景は 1-1 の31種の升目を、「16×16 ごとに4組のパレットから1組」「色0は共通」という制約を守って近似します。

物差しは3つです。違う画素は色が違う画素の数(256 中、小さいほど近い)、ぼかし RMSE はぼかした色の差(小さいほど近い)、SSIM は形や模様の構造の近さ(1 で同一)です。背景の結果は、クローンが描く 794 升目の平均で次のとおりでした。

背景の選び方 違う画素 ぼかし RMSE SSIM
ツール(画素で最適化) 71.9 37.7 0.46
ツール(見た目で最適化) 91.8 27.4 0.45
ツール(原作パレット) 93.4 28.8 0.45
人の手選び 140.4 44.3 0.17

数字ではツールが近いのに、画像で見ると逆でした。ツールは地面やブロックに土管の縁や縦縞のタイルを選び、何の絵か分からなくなります。手選びの地面 $CC・レンガ $C3 は数字では遠い(SSIM 0.06・-0.2)ものの、質感は自然です。ファミリーベーシックの絵のタイルは105枚しかなく、原作の質感に近いものが少ないのが理由と考えています。

スプライトはポーズで分かれました(ツール欄は見た目で選んだ1位)。

ポーズ ツール 既存のマリオ 見た目の判定
歩き3 RMSE 15.3・重なり 88% 21.1・84% ○ ツールが原作にかなり近い
立ち RMSE 22.9 28.8($00-03) × 既存のほうが自然
ジャンプ RMSE 26.9 38.3($0C-0F) × 腕を上げた既存のほうが近く見える

「重なり」はシルエットの重なりの割合です。色については、パレットの移植はツールの圧勝でした。原作と同じ4組のパレットを使っても、パレットまで最適化した場合との差は小さく(違う画素 76.0 対 71.9)、原作のパレットがファミリーベーシックのタイルでもほぼ最適です。

採用したのは人が選んだ組み合わせです。ツールは升目ごとに上位5件の候補を並べる道具にとどめました。物差しは画素・色・構造を測れても、「人が見てそれらしいか」は測れません。

まとめ

できたのは、1-1 の通しクリア(自動操縦・ミス0)、4KB の壁を抜けるローダ、候補を出すキャラ近似ツールです。動画の時点でポール滑り・コイン・タイム・マリオの BGM は未実装で(公開コードもこの範囲です)、実テープでの保存と読み込みも未確認です。原作は絵が 8KB、プログラムが 32KB あり、全部を 4KB に収めるのは難しいでしょう。

マシン語を AI に書かせるための前提は、機械語対応(2) にまとめています。容量の壁の先は、ディスクで動かす別の回で扱う予定です。

パレイドファミリーベーシック 機械語対応(2)|AIに読ませる機械語リファレンスを作るこんにちは、パレイド技術部の夏目です。前回は「LLM に 6502 の機械語を書かせられるか」という問いを立てました。その後、実際にテトリスを機械語…
▶ 関連動画 · YOUTUBE
https://youtu.be/uDjcJF1PE2I
━━ 観るのを再開 ━━
←
前の記事を読む
技術部 · ファミリーベーシックでマシン語に挑戦【前編】テトリス風|BASICで16秒かかった1行を1フレームで
▶
動画を観る
YouTube
━━ 他の観測領域 ━━
TECH · 技術部
ファミリーベーシックでマシン語に挑戦【前編】テトリス風|BASICで16秒かかった1行を1フレームで
PHIL · 思想部
AI自動化ピラミッドの可視化(10)|反転したのは、連載ではなかった――月次レビュー第3回
FRONT · 辺境部
【スーパーマリオ256W】256ワールド名鑑 No.25 水中を跳ねるバブル — 71-4 を自分のROMで遊ぶ