SMB Laboratoryのトップページへ

実機を使った256Wの出し方とその動作原理

はじめに

実機を使った256Wの出し方は、テニスを使う方法とファミリーベーシックを使う方法の2種類あります。これらの方法とその動作原理について説明していきたいと思います。このページでは、ファミコンのメインメモリ(RAM)の16進数表記のアドレスXXXXを$XXXXと表記します。例えば、メインメモリのアドレス 75F(16進数)は、$075Fと表記します。

テニスを使う方法

(1) スーパーマリオブラザーズのカセットを差して電源を入れます。

(2) 電源を切らずにスーパーマリオブラザーズのカセットを抜きます。

(3) テニスのカセットを差して、リセットボタンを押します。

(4) テニスをプレイして、((出したいワールド) - 1)回移動します。移動は、十字ボタンを押しっぱなしにするのではなく、1秒間に2回くらいのペースでトントンと短くたたく感じで行い、この押し方で目的の回数だけ押します。移動回数のカウントについては、以下のような特徴があります。

・タイトル画面の音楽が鳴っている間は、カウントされない。

・サーブ中に自分がサーブする時は、空振りせずにサーブを打つまでは移動してもカウントされない。シングルスとダブルスで敵がサーブする時やダブルスで味方がサーブする時はカウントされる。

・審判が「IN!」「FAULT!」などとコールしている間は、カウントされない場合もある。

・ダブルスでは、2プレイヤーの移動回数も同様にカウントされる。

これらのことを踏まえると、タイトル画面の音楽が鳴りやむのを待って、ダブルスゲームを開始し、1プレイヤーがサーブのトスを上げ続けている間に、2コントローラで((出したいワールド) - 1)回移動するのが、簡単で確実な方法だと思われます。

(5) 電源を切らずにテニスのカセットを抜きます。

(6) スーパーマリオブラザーズのカセットを差して、リセットボタンを押します。

(7) Aボタンを押しながらスタートボタンを押して、コンティニューの裏技を使います。コンティニューの裏技については後述します。

ファミリーベーシックを使う方法

(1) ファミリーベーシックを起動してBASICにします。BASICにする手順はバージョンによって異なるので、取扱説明書を参照してください。

(2) 以下のコードを入力します。

10 FOR I=&H7D3 TO &H7DC:POKE I,0:NEXT
20 POKE &H7FF,&HA5
30 INPUT "WORLD=";A
40 POKE &H7FD,A+255AND255

(3) F8キーを押して、入力したコードを実行します。

(4) WORLD=?と表示されるので、プレイしたいワールドを10進数で入力してリターンキーを押します。

(5) ERRORが表示されていないことを確認します。ERRORが表示された場合は、入力した内容に間違いがあるので、それを修正して(3)からやり直します。

(5) 電源を切らずにファミリーベーシックのカセットを抜きます。

(6) スーパーマリオブラザーズのカセットを差して、リセットボタンを押します。

(7) Aボタンを押しながらスタートボタンを押して、コンティニューの裏技を使います。コンティニューの裏技については後述します。

ファミコンのハードウェア面でのポイント

電源を入れたままカセットを差し替えて、リセットボタンを押したときのファミコンの内部動作は、重要なポイントとなります。まず、メインメモリの各アドレスの値は、電源は入れたままなので、そのままになります。また、リセットボタンを押すことによって、プログラムは新しく差したカセットのリセット時のアドレスから実行されます。

スーパーマリオブラザーズのソフトウェア面でのポイント

コンティニューの裏技

スーパーマリオブラザーズのタイトル画面で、Aボタンを押しながらスタートボタンを押すと、前回ゲームオーバーになったときの到達ワールドからゲームを開始することができます。2人プレイでコンティニューの裏技を使った場合、マリオだけでなくルイージにも適用されます。

「前回ゲームオーバーになったときの到達ワールド」という表現をしたのは、例えば、ワールド6まで到達してゲームオーバーになり、その後、コンティニューの裏技を使わずに再プレイして、ワールド3でゲームオーバーになった場合、ワールド3がコンティニューの裏技を使ったときの開始ワールドとなるからです。

また、2人プレイである場合、最後にゲームオーバーになった方の到達ワールドがコンティニューの裏技を使ったときの開始ワールドとなります。例えば、マリオがワールド5まで到達して、先にゲームオーバーになり、ルイージがワールド3まで到達して、後でゲームオーバーになった場合、ルイージのワールド3がコンティニューの裏技使用時の開始ワールドとなります。

スーパーマリオブラザーズのメインメモリ初期化

$07D7〜$07DCの6バイトには、ハイスコアが保持されます。それぞれのバイトは100万の位〜10の位に対応しています。

$07FFには、メインメモリなどの初期化が行われたかどうかを示す値が保持されます。スーパーマリオブラザーズの起動後、メインメモリなどの初期化が行われると、$07FFにはA5(16進数)が代入されて、メインメモリなどの初期化が行われたことを示します。

メインメモリの初期化処理では、$07D7〜$07DCと$07FFの値をチェックすることで、電源が投入された時かリセットボタンが押された時かを判別し、リセットボタンが押された時であれば、ハイスコアやコンティニューの裏技の開始ワールドなどの情報を消去してしまわないようにメインメモリの初期化を行います。具体的な条件と対応する処理は以下の表のようになっています。

条件 ファミコンの状態 具体的なメインメモリの初期化処理
$07D7〜$07DCの各値が10未満で、
かつ、$07FFがA5(16進数)である
リセットボタンが押された時 $0000〜$07D6($0160-$01FFを除く)のメインメモリを0で初期化
上記の条件を満たさない 電源が投入された時 $0000〜$07FE($0160-$01FFを除く)のメインメモリを0で初期化

実機を使う方法で共通した内部動作

コンティニューの裏技のプログラム処理には、開始ワールドが1〜8で正常であるかのチェックがありません。

また、コンティニューの裏技を使ったときの開始ワールドはメインメモリの$07FDに保持されています。コンティニューの裏技が使用されると、スーパーマリオブラザーズのプログラムは、$07FDの値を開始ワールドとして読み込み、その値をもとにコースを登場させます。

ですので、テニスやファミリーベーシックを使って$07FDの値を書き換えて、コンティニューの裏技を使えば、スーパーマリオブラザーズのプログラムに9以降のワールドにもコースデータが存在するものとして強制的に処理させることができ、ワールド9以降のコースを登場させることができるというわけです(256ワールドが最大である要因は、ファミコンは6502というCPUを搭載しており、このCPUは8ビットCPUであることにあります)。

しかし、問題があります。先述したように、スーパーマリオブラザーズの起動時のメインメモリの初期化には、電源が投入された時のものとリセットボタンが押された時のものの2種類あり、前者は$07FDの値を0で初期化してしまいますが、後者は$07FDの値をそのままにしておきます。スーパーマリオブラザーズのカセットに差し替えて起動したときに、テニスやファミリーベーシックを使って$07FDの値を書き換えても、電源が投入された時のメインメモリの初期化が行われると、$07FDの値が初期化されてしまいます。これでは、うまくいきません。この問題を回避するためには、$07FDの値を初期化しないリセットボタンが押された時のメインメモリの初期化が行われるようにしなければなりません。これが行われるように、リセットボタンが押された時のメインメモリの初期化が行われる条件を満たすようにメインメモリを書き換えておく必要があります。

これらをまとめると、実機を使う方法で共通した内部動作の流れは次のようになります。

(1) $07FDの値を初期化しないリセットボタンが押された時のメインメモリの初期化が行われるようにメインメモリを書き換えます。具体的に必要なのは、次の2つの条件です。

・$07FFがA5(16進数)である。

・$07D7〜$07DCのそれぞれの値が10未満である。

(2) $07FDの値をプレイしたいワールドの値で書き換えます。

(3) 書き換えた$07FDの値を保持したまま、スーパーマリオブラザーズを起動します。

(4) コンティニューの裏技を使うことによって、$07FDの値を正常なワールドの値であるかのチェック無しに開始ワールドとして読み込ませて、強制的にコースの処理を行わせます。

テニスを使う方法の内部動作

(1) スーパーマリオブラザーズのカセットを差して電源を入れます。

電源が投入された時のメインメモリの初期化が行われ、$07FFにメインメモリなどの初期化が行われたかどうかを示す値が代入されます。このとき重要なのは次の3点です。

a. $07D7〜$07DCの6バイトが0で初期化される。

b. $07FFにA5(16進数)が代入される。

c. $07FDが0で初期化される。

aとbによって、再度スーパーマリオブラザーズのカセットを差してリセットボタンを押したときに、リセットボタンが押された時のメインメモリの初期化が行われます。

cは、見落としがちですが、重要な点です。テニスのプログラムでは$07FDが初期化されないので、この0での初期化がなければ、歩数でプレイしたいワールドを狙うことができなくなってしまいます。

(2) 電源を切らずにスーパーマリオブラザーズのカセットを抜きます。

(3) テニスのカセットを差して、リセットボタンを押します。

メインメモリの内容を維持したまま、テニスのリセット時のアドレスからプログラムが実行されます。

(4) テニスをプレイして、プレイしたいワールド分だけ移動します。

トントンと短くたたくように十字ボタンを押して移動すると、$07FDが1ずつ増加していきます。また、$07D7〜$07DCや$07FFは、そのままの値が維持されます(これらのアドレスの値は、テニスの起動時には初期化されず、少しプレイしてメインメモリの様子を観察した限りでは変化が無かったので、テニスでは使用されていないと思われます)。

(5) 電源を切らずにテニスのカセットを抜きます。

(6) スーパーマリオブラザーズのカセットを差して、リセットボタンを押します。

メインメモリの内容を維持したまま、スーパーマリオブラザーズのリセット時のアドレスからプログラムが実行されます。リセットボタンが押された時のメインメモリの初期化が行われ、$07FDの値が保持されたままスーパーマリオブラザーズが起動します。

(7) Aボタンを押しながらスタートボタンを押して、コンティニューの裏技を使います。

コンティニューの裏技のプログラム処理によって$07FDの値が1〜8で正常なワールドであるかのチェックが行われることなく開始ワールドとして読み込まれ、それをもとにしてコースが処理されていきます。

ファミリーベーシックを使う方法の内部動作

(1) ファミリーベーシックでBASICにします。

(2) 以下のコードを入力します。

10 FOR I=&H7D3 TO &H7DC:POKE I,0:NEXT
20 POKE &H7FF,&HA5
30 INPUT "WORLD=";A
40 POKE &H7FD,A+255AND255

それぞれの行は、次のような処理を行っています。

10行目 $07D3〜$07DCまでのそれぞれのアドレスに0を代入する。

20行目 $07FFにA5(16進数)を代入する。

30行目 画面に「WORLD=」と表示し、変数Aにキーボードから入力した数値を代入する。

40行目 変数Aを0起算で256未満の数値に変換し、変数Aの値を$07FDに代入する。

10行目の処理で、$07D7〜$7DCの6バイトが0となり、20行目の処理で、$07FFがA5(16進数)となります。これによって、電源を切らずにスーパーマリオブラザーズのカセットに差し替えたときに、リセットボタンが押された時のメインメモリの初期化が行われるようになります。$07D3〜$07D6にも0を代入していますが、これについては意図がよく分かりません($07D3〜$07D6は、電源投入時・リセットボタン押下時のどちらのメインメモリ初期化でも0で初期化されます)。

30行目と40行目の処理で、$07FDにコンティニューの裏技を使ったときの開始ワールドを代入しています。なお、40行目の変数Aに対する演算は、入力された1から数えるワールドの値を0から数える256未満(1バイト)の数値に変換するためのものです。

(3) F8キーを押して、入力したコードを実行します。

(4) WORLD=?と表示されるので、プレイしたいワールドを10進数で入力してリターンキーを押します。

(5) ERRORが表示されていないことを確認します。ERRORが表示された場合は、入力した内容に間違いがあるので、それを修正して(3)からやり直します。

(5) 電源を切らずにファミリーベーシックのカセットを抜きます。

(6) スーパーマリオブラザーズのカセットを差して、リセットボタンを押します。

メインメモリの内容を維持したまま、スーパーマリオブラザーズのリセット時のアドレスからプログラムが実行されます。リセットボタンが押された時のメインメモリの初期化が行われ、$07FDの値が保持されたままでスーパーマリオブラザーズが起動します。

(7) Aボタンを押しながらスタートボタンを押して、コンティニューの裏技を使います。

コンティニューの裏技のプログラム処理によって$07FDの値が1〜8で正常なワールドであるかのチェックが行われることなく開始ワールドとして読み込まれ、それをもとにしてコースが処理されていきます。

inserted by FC2 system