乱数の初期値について
このゲームはところどころFCプログラムとして行儀の悪いところがあり、メモリの初期化をしていない領域を使用していることがあります。
乱数もその一つであり、乱数の初期値は本体のメモリ初期値に依存しています。
このゲームはところどころFCプログラムとして行儀の悪いところがあり、メモリの初期化をしていない領域を使用していることがあります。
乱数もその一つであり、乱数の初期値は本体のメモリ初期値に依存しています。
ハードウェア依存なので実際に調べるのが手っ取り早いと思います。
所持している赤白ファミコン(HVC-CPU-GPM-02, MOTOROLA MCM2018AN35)の初期値は全領域 0xFF(255) でした。
ニューファミコンや互換機は所持していないので他の方に…。
Ram editを使うとメモリ初期値の確認と、後述のメモリ操作が任意にできます。(宣伝)
現在確認しているメモリIC
電源再投入時に既定の値(0xFFとか)に初期化されるものと、以前の値が残るものがあります。
後者の値が残るものの場合、時間経過によってメモリセルの電荷が減衰していき、特定の値に落ち着きます。
減衰中はどこのビットが変化するかわからないため、実質ランダムな状態になります。
温度等によって回路の電気抵抗も変化するため、減衰時間は都度変動します。
電源投入直後のメモリが固定値である本体は、状況再現が可能となります。
テニスをプレイ中にカセットを引っこ抜き、スーパーマリオブラザーズに入れ替えると任意のワールドをプレイできるというバグ技があります。
これを応用して、別カセット(メモリの内容が把握できていれば何でも構いません)によりメモリを初期化してもらうことでランダムな本体でも乱数初期値を固定化することができます。
電源を入れたままカセットを引っこ抜くのは本体やカセットにダメージを与える可能性があるのでご注意ください。(トーテム尾崎もですが)
リセットボタンを押している間はCPUへのクロック供給が止まるので、少し優しいかもしれません。
GAME GENIEやEver Driveなど独自のメニューを挟んでからゲームに移行する場合、それらがメモリを初期化してくれるかもしれません。
ただし、全領域を初期化したり、常に一定の値である保証はありません。
レトロフリークなど、内部がエミュレータのもの。
大抵メモリ初期値は固定なので何もしなくても固定化済み。(未所持のため不明)
線形帰還シフトレジスタベースのアルゴリズムです。
周期は65534 = 2^16-2 なのでM系列ではないです。
メインメモリの$32が出力値、$33が乱数生成用ワークになっています。
詳しい処理内容については逆アセンブルとC言語書き下しをご参照ください。
1回生成のたびにこの処理を11回繰り返して、下位バイトである$32を使用します。
乱数初期値が`$5555`か`$AAAA`だった場合、この2種類だけを交互に繰り返すようになります。
南西または東の風で、風速は1mか4mの4パターンのどれかになります。
乱数はほとんど無視できるようになりますが、あまり良い状態にはならないようです。
消費数にスラッシュがある場合は、 `(Stroke or Match) / (Tournament)`
$C343[$1C343]
: カップ位置 18ホール +18$B921[$17921], $B92F[$1792F]
: トーナメント時 (他プレイヤースコア計算?) +200$B9E8[$179E8]
: トーナメント時 (他プレイヤースコア計算?) +160$B9E8[$179E8]
: トーナメント時 (他プレイヤースコア計算?) +64$C3C1[$1C3C1]
: 基準風向 +1$C3C8[$1C3C8]
: 基準風量 +1$C442[$1C442]
: 風量変更 +1$C442[$1C442]
: 風量変更 +1$C4FD[$1C4FD]
: Amature以外ショット時 (カーソル初期位置調整) +1$843E[$1843E]
: グリーン以外でのパター時 (飛距離調整) +1$84C3[$184C3]
: ラフからのショット時 (飛距離調整) +1$861E[$1861E]
: 木衝突時(1/4の確率で通過、3/4の確率で引っかかる) +1$87E9[$187E9]
: ウォーターハザード時(画面倍率x1→x1の場合のみ?) +1$8953[$18953], $896C[$1896C]
: ピンフラッグ衝突時(反射角度調整) +2$AE6F[$16E6F]
: オングリーン時レッスン +1$AEDF[$16EDF]
: 5フレーム毎(まばたき) +1$AFB5[$16FB5]
: 5フレーム毎(1文字表示の口パク) +1
難易度選択後に18ホール分、18ホール目から逆順に生成しています。
起動後(乱数初期値固定)最初に使用される乱数であり、プレイの影響は受けないためカップ位置の固定ができています。
位置の決定には乱数の下位2bitを利用しており、4パターンの中から選ぶことになります。
シミュレータもご利用ください。
ホール開始時に基準風向と風量が決定されます。
風向は乱数生成して上位3bit、$00 = 北, $20 = 北東, ... と時計回りに決まります。
風量は再度乱数生成して下位4bitを利用し、11以上の場合は8を引きます。([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 3, 4, 5, 6, 7]
)
ショット毎に乱数生成して下位3bitを以下のリストで変換し、基準風量に加算します。(本当は計算してるけど式にするのがだるい)
[0, 0, -1, 0, 0, 1, 1, 2]
風量がマイナスになった場合(基準風量=0, 乱数風量=-1 : 1/128の確率)、風向を反転して、風量1mとします。プラスの場合は各難易度の最大風量を下回るまで5を引き続けます。
いいぞ。
カセット内の基板の部品がいろいろ乗っているPCB Frontが、実際は後ろを向いてファミコンに刺さっています。 カセット左側がプログラム、右側が画像データにアクセスできるようにピンアサインされています。
ファミコンの映像用メモリ(VRAM)はコストダウンのため2KBしか搭載されていませんが、実際には倍の4KBを認識できるようになっています。
そのため、不足しているアドレス用信号ピンを他の信号ピンで代用しています。
すると、画面の半分は同じ画像になり、これをミラーリングと呼んでいます。
この不足しているピン CIRAM A10
はカセットによって制御が様々で、基板のはんだパッドによって選択していたり(NROM)、マッパーによって制御されており場面に応じて切り替えて可能なものもあります。
尾崎にはMMC1というマッパーが乗っており、マッパーを制御することでミラーリング方向を切り替えられるようになっています。
ネームテーブルとは画面に表示するタイル(ツクールとかでいうマップチップ)の並びが格納されるメモリ領域のことです。(PPU $2000-$3FFF)
信号線のことをバスと呼び、これが未接続(オープン)になることをオープンバスと呼んでいます。
未接続の信号を読み込むと内容は不定ですが、少しの間はバスに残っている以前の値を読むことができたりします。
ファミコン初期はプログラム32KB, グラフィック8KBに収めないといけない厳しい制約でしたが、マッパーと呼ばれるチップをカセット内に積むことによって大容量のゲームを実現しました。
本体は変わらないので、一部領域を"取り換える"ことによって見せかけの領域は同じにしつつ、様々なプログラムやグラフィックを使用できるようにしています(バンク切り替え)。
全部解析していないため一部推測が含まれています
カセット右側を半挿しして CIRAM A10
の信号をオープンバス状態にします(これよりさらに抜くとプログラム用信号まで巻き込んでしまうためフリーズします)。
これにより、本来更新するはずのネームテーブルのあて先が狂います。
ワンポイントレッスン移行時は画面を丸々書き換えていますが、本来とは異なる、見えていない領域に更新内容を書いてしまいます。
そのため更新前のショット画面のタイルの並びのまま、ワンポイントレッスン用グラフィックに切り替わり、偶然にも森のグラフィックと尾崎先生の顔が同じ領域だったことによってトーテム尾崎となってしまいました。
ΩND