gimidump v0.00 公開


「Steam版ギミック!スペシャルエディション」のメモリ空間からROMダンプ。
Download : gimidump v0.00

 いつもなら「超レアROMダンプできたウヒョーイ!」とか喜ぶところなんですが、サンソフトの復刻チームが凄く頑張ってるところに水を差すのも何なので「わかる人だけ使ってね」という感じ。

 そもそも、ウン十万円もする中古カセットとかヤフオクとかメルカリで売ってる海賊版ギミック!を購入してもメーカーには1円もプラスにならんのです。
 ROMイメージを入手したいという理由だけでも、Steam版を購入すれば開発者の利益になりますので、今後のサンソフト復刻シリーズのために購入をお願いします。
Steam : Gimmick! Special Edition

激安UVランプでEPROM消去!

楽天市場:【在庫処分】充電式紫外線ランプ JP18-UV Lamp UV除菌ライト 185-254nm 殺菌 ポータブル バクテリア 細菌 カビ ウイルス 家庭 寝室 授乳室 ペット 旅行 ¥980

(アフィ踏みたくない人は 直リンク )

 まあ、これを記事に書いている時点でお察しだと思いますが、楽天のリサイクルインクショップ「インクのオアシス」で売られているアウトレットの紫外線ランプ(なんと1本980円!)の波長が185-254nmで、見事にUV EPROMの消去特性と合致。

<照射の様子>長押し5秒でフルオート10分照射

<結果>しっかり0xFFフィルされていて消去完了

 ちなみに3,980円以上注文で送料無料になるので、他にもアレコレ買うと良いかもねえ(ウチはこのランプ2本+らずぱい用HDMIモニタ2500円をポチりました)。

~追記~

 UVの特性について知らない人もいるかも知れないので念のため追記。
 この紫外線ライトは185-254nmの波長をもつ紫外線を放出しますが、思いっきり人体に有害&オゾンが出ますので、人の居る場所で使わない方が無難です。
 上の写真は撮影のために一瞬だけ正面に向けてますが、照射中はアクリルケースや段ボールの中に入れたり、トイレに入れて照射が終わるまで放置しておくのが良いでしょう。

スペランカーの「無敵モード」を実機で

 ふと気がつけば公開から約3年経過となる4ST黎明期の1本、スペランカーの無敵モードアンロックの動画を久々に見ていて、ふと……。

「この時代のファミコンカセットって特殊ROMを積んでないし、カセットを改造すれば実機でもプレイできるんじゃね?」

 というわけで、スペランカーの生贄を1本入手。

 パカっとな。

 スペランカーはPRG-ROM(256KB)+CHR-ROM(64KB)で、CHRには何故か窓シール無しのUV EPROMが採用されています(※ロット差はあるかも)。
 そして前者のPRG-ROM(写真向かって右)はINTEL P27256(DIP28pin)で、今回のターゲットはコイツです。

 半田は超ゆるゆるなので、吸い取り機などでサクッと取れます。
 続いてP27256のROMイメージをPCにダンプすることになりますが、コレもaliexpressで売られている格安ROMプログラマxgecu T48で試してみました。

Aliexpress : Xgecu-spi/nor/nand flash/emmc bga/tsop/sop/plcc 13パーツ用の新しいt48 (TL866-3G) プログラマーのサポート,34000のマイク

 私は13パーツ付き9,000円弱のヤツを買いましたが、DIPしか読まないならTSOP変換ソケットが付いてない6,500円くらいのでも十分かも。
 Aliexpressで自力で買い物をできるレベルの人に説明は不要と思いますが、xgecu公式サイトでクライアントを落としてインストール、ROMプログラマ本体をUSB接続したらファームウェアが勝手に上がり、以後は普通にROMの読み書きが可能です。


 ROMプログラマにCHR-ROMをセットしたら、デバイスセレクトで27256をサーチ、メーカーINTEL、デバイスP27256@DIP28を選んでRead。


 まったく引っかかることなく、スムーズに吸い出し成功。


 バイナリエディタでダンプしたPRG-ROMから、目的の箇所を00→20へ変更。
 ※NESヘッダ0x10バイトが無い分オフセットのズレがあるので、動画とは違い$06E9を書き換える。


 書き換えたPRG-ROMデータを生ROMに焼き焼き。
 xgecu ROMプログラマ対応+リード5Vで動作してP27256と互換性あり…という条件で、今回は TMS27C256-15 を利用(ヤフオクで送料込1個320円でした)。


 焼いたROMを基板に半田付けしつつ、窓が飽きっぱなしのCHR-ROMも気になるので念のため両方とも塞いでおく。

 ……というわけで。

 セレクトボタンで自由に空飛ぶ動作も問題ナシ。
 虚弱体質だったスペランカー先生が画面中を縦横無尽に飛び回り、空中で幽霊に体当たりして撃破する様を、いつでもファミコン実機で拝めるようになりました。

~追記~

 上記の作業を「個人で楽しむ目的」はギリギリで法律上のグレーゾーンですが、オークションサイトやフリマサイトなどで販売すると、思いっきり著作権法違反+不正競争防止法違反で一発で刑事事件になります。
(※サテラビューで配信されてたクーリーほにゃらら体験版にクラックパッチを当てたROMを焼いて売ってるあの人とか)

 改造版スペランカーで小遣い稼ぎをする変態は居ないとは思いますが、軽い気持ちで金銭が関わるとマジで人生詰むので、あくまで個人で楽しむだけにしましょう。

「超ファミつく」で遊んでみた

 レトロゲームの再生産やゲーム互換機の販売で有名なコロンバスサークル様(以後敬称略)がTwitterで実施した懸賞でSFC互換機「超ファミつく」が当選したので、ちょいと遊んでみました。
 ただし、ウチは3Dプリンタだの加工機だの高度なアイテムなんざ持ってないので、志は低めに目標は次の三つ。

1.ニンテンドースイッチと同じくらい画面がデカい(=7インチ)。
2.AC電源が要らない(=完全バッテリ駆動)。
3.ケースに収納できるポータブル型。

 そんなこんなでスタートです。

【コロンバスサークル】コロンバスサークル CC-SFCFT-GR 超 ファミつく SFC互換機DIYキット スーパーファミコン

価格:4,070円
(2023/3/12 15:12時点)
感想(0件)

・そもそも「超ファミつく」って何?
 コロンバスサークルが販売しているSFC互換機「16BIT COMPACT」の基板+ACアダプタ+パッド2個だけを単品販売しているバルク基板です。
 つまり外装パーツが無いので、どんなハコに組み込んで使うかを楽しむ商品です。

・ハードウェア仕様
 詳しくはパッケージに書いてある仕様を参考にしていただければと思いますが「出力はRCAコンポジット+S端子、電源はセンターマイナスDC10V/600mA」です。

・7インチアナログ液晶パネルの入手
 なので「アナログ映像入力が可能で、バッテリ駆動できる7インチ液晶パネル」が必要なわけですが、最近売られている多くのパネルはHDMI接続で変換回路が必要なうえ、全て揃えるとそこそこのお値段になります。
 懸賞で当選したとはいえ実売5,000円以下の互換機のためにそこまでやってられないので、いざ人柱で下記パネルを購入しました。

Amazon : OBEST 7インチモニター (執筆時3,599円)

 ただし超ファミつく接続時には画面左下にノイズが出たので、完全に適合するとは言いがたい」です。

(画面左下がビリビリしている様子)

 あくまで「安価にリモコン対応パネルを買いたい場合」に適切なだけで、もしかすると完璧に表示できる製品が別にあるかもしれません。
 ちなみに、同じくAmazonで大量に売られている「4.3インチ液晶パネル」は擬似NTSC信号と相性が悪く、適切な同期が取れなくてずっと画面がグルグル回っていたので、回避した方が良さそうです

・液晶パネル用のセンタープラスDC12Vを生成する
 前述のOBEST7インチモニターを動かすために、12V/400mAの電力源を引っ張ってくる必要があります。
 と言っても、その程度の低電力の12Vを生成するだけなら、USBモバイルバッテリにDC12V昇圧ケーブルを繋ぐだけでOK。
 今回のモニタのDC端子仕様は「外径5.5mm、内径2.1mm、センタープラス」なので、ごく普通の汎用格安品で良いでしょう。

Amazon : LANMU USB 5V-9V/5V-12V DC電源供給ケーブル(執筆時899円)

 USBモバイルバッテリと7インチモニタをこのケーブルで繋いで、靑画面が出力されれば成功です。
 あと、この記事を読んでチャレンジする人は大丈夫とは思いますが、おそらく超ファミつく本体にこのセンタープラス12Vを流し込むと即死すると思います。
 
接続時には要注意!

・超ファミつく用のセンターマイナスDC10Vを生成する
 そしてここからが少し厄介なのですが、USBモバイルバッテリからセンターマイナスDC10V/600mAを生成できる安価な既製品はほとんど無いです。
 もしかするとファミコンのように「実は本体内5V駆動で、基板に配線直結すれば10V要らない」という可能性もあるのですが、今回は回路設計までは追いかけないので、素直にダイヤル式DC-DC昇降圧コンバータを使いました。

Amazon :電圧レギュレータ DC-DC昇降圧コンバータ 2個セット (執筆時960円)
 ここに「外径5.5mm、内径2.1mmの端子をセンターマイナスになるように繋ぐ」のですが、ウチはうっかり手持ちのACアダプタをぶった切って繋いだものの、実は前述のOBEST7インチ液晶パネルに同じ仕様のケーブルが付いてます。
※そもそも車載用で12Vバッテリから電源を取るためですね。

 レギュレータのダイヤルを回して約10Vが生成できていることを確認。
 黒棒(マイナス)をDC端子の中央に突っ込んで、センターマイナスもしっかり確認。
 さっきも書いたけど、コレを間違えたら一発アウトだよ。あと、ここで生成したセンターマイナスを液晶モニタに突っ込んでも多分一発アウトだよ。
 とにかく注意!!

・動作テストを行う
 超ファミつく本体と液晶パネルを繋いで、事前に動作テストをします。
 モバイルバッテリは適当な10000mAh(USB5V 2.1A+1.0Aの2口出力)を利用。
 超ファミつく本体が6.5W要求しているのでUSB2.1Aから、液晶パネルは5W以下で動くのでUSB1.0Aから、それぞれDC10VとDC12Vを生成して供給しました。

 これで「AC電源なしでどこでも遊べる7インチ液晶パネル付きSFC」が実現可能であることが確定。
※1万円ちょいでこんなのが作れるとは、とんでもねえ時代だなぁ(‘-`;

・ケースはどうする?
 というわけで、ここから先は皆のアイデア次第です。
 アタッシェケースに組み込むとか、余ってる自作PC用ケースに入れるとか、ここで自分好みに仕上げられるのが超ファミつくの遊びどころ。
 というわけで……

 ドギャーン。

 正気を疑われそうですが、まあサイズ的に「上の黒い部分にほとんど納められるんじゃね? あと、メッシュの部分にボルト+ナットで止められそうだよね。放熱性も良さそうだし」という安直な理由でセレクト。

 結局こんなレイアウトになりますた。
 上フタはヒートシンクに干渉したのでサヨウナラ。
 透明なボディ部分は加工が超難しいので一切触っておりません。
 液晶パネルは透明な「ポスター用 剥がせる両面テープ(100均)」で軽く貼り付け。

・仕上げ
 この状態では「音が鳴らない」「遊んでいない時もUSBモバイルバッテリの残量がゴリゴリ減る」という致命的な問題があるので、それを解決します。

Amazon : KAUMO USB電源コード2分岐 (執筆時490円)

Amazon : ノーブランド USB延長コードオンオフスイッチ付 (執筆時335円)

 これでスイッチひとつで超ファミつく本体と液晶パネルを同時給電可能に。
※消費電力を考えるとUSB3A出力のモバイルバッテリを使う方が良いかと。

 ダイソーの300円USBミニスピーカーと、それをRCAの赤白オーディオ端子に接続するためのRCAオス-ステレオミニメス変換端子を用いて接続。
(もっとスマートに仕上げるならスピーカーモジュールだけ取り出して、ボリュームコントローラを外から触れるようにした方が良いですね)

・完成形

~最後に~

 当初の目的を振り返ります。

1.ニンテンドースイッチと同じくらい画面がデカい(=7インチ)。
 良い感じ。

2.AC電源が要らない(=完全バッテリ駆動)。
 これもバッチリ。

3.ケースに収納できるポータブル型。
 プレイ中はカセットが外に露出するものの、本体・画面・バッテリ・スピーカーすべて虫かごに収納できて満足です。

 虫かごの加工はニッパーとカッターナイフのみ、極性チェックに使ったテスター以外は大抵のご家庭にあるはず。
(テスターは1000円以下で買えるので1台くらい持っておくのが吉)
 そんなわけで「超ファミつくを利用した7インチ携帯型SFC互換機」は無事完成。
 皆様も何か面白そうなケースを探してチャレンジしてみましょう。

妖怪道中記 隠しパスワード解析「最初の一週間」の裏側

発売から35年、妖怪道中記・隠しパスワード完全解明までの一部始終
~531垓分の1を探し求めた男たち~

 本動画の5:10で「その一週間後、はむさんの手によりパスワード解析ツールの第一弾が完成する」と語られた「一週間」で行った作業を列挙してみました。

 なお、詳細解析情報や解析ツールのソースコードについてはZIPアーカイブにまとめていますので、そちらをご覧ください。
Download : yokai-pack-20211219.zip

工程1:ROMを眺める


 妖怪道中記のROMイメージを見ると、パスワード入力が正解した時に表示されるメッセージと謎の数字の羅列(後にチェックデジットと判明)が順番に格納していることがわかります。
 ところがパスワード本体が平文で全くヒットせず「まさか1987年にハッシュ関数を…?」と若干不安な気持ちに。
 実際にはその想像をはるか超える地獄が待っていようとは……。

工程2:メモリエリアを眺めてアドレス選定


 自作ツールemuhasteをPCEエミュレータootake専用にカスタムし、カーソルを動かしてサーチ、文字を打ったり消したりしてサーチ、入力文字数をサーチ……など、ひたすら地道な作業。

 この時点で「入力した文字の合計数がアドレス$31F6に格納されていること」「アドレス$31DC以降に入力したパスワード列情報があり、文字コードがゲーム独自である」などといった重要な要素が判明します。

工程3:[PCE 6280逆アセンブラ]を用いた解析


 アドレス$31F6に極めて重要なパラメータが格納されていたので、オールドゲームROM研究所のBAB氏作「PCE 6280逆アセンブラ」を用いて、$31F6に触れているルーチンを列挙したところ、下記コードを発見。

D6F7 : AD F6 31 LDA $31F6

 上記アドレス$D6F7からパスワード入力ルーチンが始まっており、Iボタンを押した瞬間にパスワード文字数をチェックしたり、カーソル位置を元に文字コードを生成するといった主要の処理を行っていました。
 なお、この段階ではサブルーチンコールJSR(20 xx xx)などをNOP(EA)で破壊し、実際にゲームを実行して挙動を確認するといった、かなり豪快な方法で各処理内容を調査しています。

工程4:デバッガによるリアルタイム動作解析


 マルチエミュレータMESSがPCエンジンエミュレーションに加え、超強力なデバッガが実装されていたので、下記コマンドからデバッグモードで起動。

>mess.exe pce youkaid -debug

 さらに同デバッガのブレークポイント機能( bpset $D6F7 )でアドレス$D6F7以降の処理を追跡したところ、アドレス$D853以降に露骨なゼロクリア処理を発見。

D853 : 82 CLX ; Xをゼロクリア
D854 : 8E F4 31 STX $31F4 ; 31F4=0
D857 : 8E F5 31 STX $31F5 ; 31F5=0
D85A : 8E F7 31 STX $31F7 ; 31F7=0
D85D : 8E F8 31 STX $31F8 ; 31F8=0
D860 : 8E F9 31 STX $31F9 ; 31F9=0
D863 : 8E FB 31 STX $31FB ; 31FB=0
D866 : A9 01 LDA #$01 ; A=01
D868 : 8D FA 31 STA $31FA ; 31FA=01

 これをデバッガの[Step Info]でひとつずつ追跡したところ、パスワード文字数を格納する$31F6を除く$31F4~$31FBに何らかの演算結果を入れていることが判明。

 また、適当な正解パスワードのラスト1文字を入力した瞬間に処理の終端を確認すると「ROMのメッセージ間に挟まれていた謎の値と、$31F4~$31FBの値が完全一致していた」ことから、PCエンジン版妖怪道中記のスタッフインフォメーションボードのパスワード処理ルーチンは、下記のプロセスであることが確定しました。

1.ユーザがパスワードを入力すると$31DC以降に順番に文字コード値を挿入。
2.それと同時に$31F6に入力文字数をセット。
3.サブルーチン$D853をコールし、$31F4~$31FBの値=チェックデジットを生成。
4.最終チェック処理$D730をコールし、全ての隠しパスワードの設定値と前述のサブルーチンで生成した値を比較。
5.一致するパスワードがあれば正解処理(無敵フラグや画面表示)を行う。

 あとは、チェックルーチン$D853が何をやっているのかを解読し、それを自作プログラムで再現できれば、PCエンジン実機やエミュレータが無くても隠しパスワード解析にチャレンジしたり、実際にパスワードハッキングができる…というわけです。

工程5:パスワード解析ツールを自作

 ここまで解析が進めば、後はプログラミングの時間です。
 ただし一発で完成品が出来るわけもなく、テストモジュールをコツコツ作ります。

 PCエンジンのCPU(HuC6280)用のコードをVisual C++に移植する作業です。
 HuCそのものは6502カスタム版なのでNESの開発ドキュメントあたりも参考になりますが、Googleで”Turbo Graphics 16 opcode”あたりのキーワードで検索して、CPU仕様書を探して勉強するのが無難かなぁと。
(ウチもHuCのCPU仕様書を読んだのはこの作業が初めてだったので、頑張れば何とかなるなる)
 というか、実際の置き換えもかなり力技でした。

HuC(6502) Visual C++
PHA
LDY #$08
ASL A

PHA

stackA[stackApos++]=A;
Y=8;
A = A << 1;
if(A>0xFF){ C=1; A=A&0xFF; }else{C=0;}
stackA[stackApos++]=A;

 スタック操作(PHA)は配列stackA[]と変数stackAposを用いてLIFOの流れを模倣。
 ASL Aを実行すると8ビットのAレジスタを左1ビットシフトし、溢れたビットがキャリーフラグ(C)にセットされるので、これをムリヤリ条件分岐で再現~…というメチャクチャすぎる力技を採用。
 その副産物で「環境依存せず、あらゆる言語に移植できた」ので、ケガの功名というか、まあ良かった(のかなぁ???)

・・

 以下、私が作成した初期の解析ツール群です。

yokai01(没)
 パスワードを入力するとアドレス$31DC~と同じレイアウトの配列を生成するテストプログラム。

yokai02
 yokai01のルーチンの後、妖怪道中記と全く同じ演算を行い$31F4~$31FBの値を生成し、画面に表示するパスワードシミュレータ。
 当初「$31F4と$31F5が一致すればほぼ本物じゃね?」などと安易に考えていたので、ツール名が[$31F4 $31F5 simulator]になっています。

yokai03
 yokai02のルーチンに対し、総当たりで全パターンのパスワードを試行するツール。

yokai04(没)
 yokai02のルーチンに対し、単語を順番に辞書アタックを仕掛けるツール。
 ※よくよく考えると同じ単語が連続するパスワードを解析できないので没。

yokai05
 yokai02のルーチンに対し、完全ランダムの組み合わせで辞書アタックを仕掛けるツール(無駄は多いけど無難)。


 そして、これらの解析結果は私よりもずっと高スキルのエンジニア達に共有され、発売から35年目ついに攻略~……という流れでした。

 当然、こんなプロセスを動画にまとめてもクソ退屈な映像になってしまうわけで。
 難解なシーンをすべてカットして、まるで英雄譚のように綺麗にまとめたシイナさん、超グッジョブでした(‘ω`)

セガサターン「街(体験版)」隠しメッセージ捜索

 妖怪道中記の隠しパスワード選手権関連でサーチしてたらこんなツイートを発見。


そして


まあ買うよね。

 詳細は上記ツイートのツリーを見ていただければと思いますが、とりあえずテキストコンバータ(フォントテーブル未完成)をアップしました。
Download : matconv221030.zip

 文字化けや抜けもかなり多数ありますが、はてさて本当に本作に隠しメッセージがあるのやら……

ついに「PCエンジン妖怪道中記パスワード完全解明」の動画が公開されました

関連記事
【速報】PCエンジン妖怪道中記 真パスワードが発見されました

YouTube : 発売から35年、妖怪道中記・隠しパスワード完全解明までの一部始終~
531垓分の1を探し求めた男たち~

~動画のコメント欄にあった疑問など~

Q.「なむこむな!756-2311」以外の解があるのでは?
A.候補数1.6億の中にナムコの電話番号が偶然含まれる確率0.0000165244%なので、
 これが真のパスワードである確率は99.999983%…まあ否定は無理でしょう。
 おそらく「なむこむな!」は黒電話のダイヤルの指の動きだと思われます。
 (参考)Wikipedia : 黒電話

Q.8桁パスワード「818-6104」も別解があるのでは?
A.これは宇田川氏が本物だと断言しているので、確率うんぬんでなく本物です。

Q.もし知ってたら、この祭りに参加したかった!!
A.え? まだ隠しダンジョンの攻略が終わってませんけど???

ファンタジーゾーン2の解析を支援してみる


 最近、ほぼ4STさんトコのネタばかりではありますが「ファンタジーゾーン2の最終ボスラッシュで$9720890手に入る」という話をちょっと深掘り。

--FANTASY ZONE 2 MONITOR
while (true) do
	local zz = memory.readbyte(0x0132);
	local yy = memory.readbyte(0x0133);
	local xx = memory.readbyte(0x0134);
	gui.text( 0,32,""..(xx-xx%16)/16);
	gui.text( 7,32,""..xx%16);
	gui.text(14,32,""..(yy-yy%16)/16);
	gui.text(21,32,""..yy%16);
	gui.text(28,32,""..(zz-zz%16)/16);
	gui.text(35,32,""..zz%16);
	gui.text(42,32,"0");
	FCEU.frameadvance();
end;

 とりあえず↑をコピペしてテキストエディタに貼り付けて「FZ2MON.LUA」とでも名前を付けて保存。
 ファミコンエミュレータFCEUX2.23でファンタジーゾーン2をロードして、File→Lua→New Lua Script Windowをオープン。
 Browse…で保存したFZ2MON.LUAをロードして[Run]ボタンを押すと…  
 こんな感じでボスラッシュ中に取得した金額をチェックすることができます。
 ちなみにメモリ上のデータレイアウトはこんな感じ↓

マネーの表示レイアウト $xxyyzz0
-addr-
0x0132 zz
0x0133 yy
0x0134 xx
$9720840加算= 84 20 97 の16進数をそのまま10進数として処理している。

 つまり「画面表示は10進数っぽく並べただけの16進数」ですね。
(上述のLuaスクリプトが16の除算や余数の計算をしているのはそのせい)

 どうしてボスが爆破した瞬間に 84 20 97 を加算しているのか詳細までは解析できていませんが、9720840ドルが加算される瞬間にブレークした結果は下記のとおりです。

コール元
 06:AC55:20 F4 BC  JSR $BCF4
 06:AC58:20 2C B6  JSR $B62C << ここをEAEAEA(nop)でお金増えなくなる
 06:AC5B:4C ED AB  JMP $ABED

コール先
 06:B62C:AD CC 00 LDA $00CC = #$00
 06:B62F:F0 01 BEQ $B632 << 加算ルーチンにジャンプ
 06:B631:60 RTS
 -----------------------------------------

加算ルーチン
 06:B632:AD 32 01  LDA $0132 = #$00
 06:B635:8D 88 01  STA $0188 = #$84 << 注目箇所
 06:B638:AD 33 01  LDA $0133 = #$00
 06:B63B:8D 89 01  STA $0189 = #$20 << 注目箇所
 06:B63E:AD 34 01  LDA $0134 = #$00
 06:B641:8D 8A 01  STA $018A = #$97 << 注目箇所
 06:B644:84 60     STY $0060 = #$90
 06:B646:86 61     STX $0061 = #$00
 06:B648:A0 00     LDY #$00
 06:B64A:B1 60     LDA ($60),Y @ $0090 = #$9A
 06:B64C:8D 8B 01  STA $018B = #$84
 06:B64F:C8        INY
 06:B650:B1 60     LDA ($60),Y @ $0090 = #$9A
 06:B652:8D 8C 01  STA $018C = #$BA
 06:B655:C8        INY
 06:B656:B1 60     LDA ($60),Y @ $0090 = #$9A
 06:B658:8D 8D 01  STA $018D = #$96
 06:B65B:20 71 B6  JSR $B671
 06:B65E:AD 88 01  LDA $0188 = #$84
>06:B661:8D 32 01  STA $0132 = #$00
 06:B664:AD 89 01  LDA $0189 = #$20
 06:B667:8D 33 01  STA $0133 = #$00
 06:B66A:AD 8A 01  LDA $018A = #$97
 06:B66D:8D 34 01  STA $0134 = #$00
 06:B670:60        RTS -----------------------------------------

 アドレス0188、0189、018Aの三連に[972084]の値が生成されているので、ここを追跡していくと真実が見えるかもですね。

スカイデストロイヤーで学ぶ「奇跡を強制召還する手法」

 さて、2022年5月28日に公開された4STさんの新作「発売から37年目の真実…闇夜に現れるという不気味な幽霊船は実在するのか|スカイデストロイヤー」を見て、幽霊船ゾンビの出現&破壊に挑んだ強者もいるかと思います。

 ウチもこんな感じで動画の翌日には幽霊船ゾンビを出現させて倒すツイートをしていたわけですが、実はコレ、莫大な時間と3D酔いと戦いの果てに勝利を掴み取ったシイナさんと違って、私のヤツはプログラムハックで強制召還したインチキ画像です。

・ ※動画の超ネタバレが含まれるので先に前述の4ST動画を見てね!


<前準備>

 ゲームソフト:ファミコン版スカイデストロイヤー
 ROMダンパー:https://www.amazon.co.jp/dp/B087GGBVMV/
 エミュレータFCE-UX:https://fceux.com/web/home.html
 emuhaste:https://i486.mods.jp/ichild/download/emulator-cheet-program-emuhaste
 ※ゲームソフト以外は好みでいいです。

<幽霊船ゾンビの出現条件をおさらい>

1.夜になってから、母艦ノースザネリ(以下、母艦)出現の瞬間に倒す。
 =出現前から魚雷を発射しなければ間に合わない。

2.母艦は8つのグラフィックで構成されている。
 内部的に状態変化カウンタが存在しているのは確実。

<母艦の各フレーム値を特定>

1.FCE-UXでゲームを進行する。

2.母艦が出現する直前あたりでステートセーブ。

3.現れた直前にポーズしてemuhasteでサーチ開始。

4.母艦が形態変化する都度にポーズして「変動」などで絞り込み。
=これでアドレス$006Bの値が母艦の形状と連動していることが確定。

 動作を調べたところ「母艦が出現した瞬間に$006Bに08がセットされ、時間経過ごとに07,06,05..とカウントダウンとともに表示座標が左にずれてゆく。値が08のタイミングで母艦を倒せば、幽霊船ゾンビが出現する」というプロセスでした。

 当然、アドレス$006Bに08を常時セットし続けることで、どのタイミングで倒しても確実に幽霊船ゾンビが出現することになります。

 ちなみに幽霊船ゾンビのX座標は$00ACに格納されており、母艦を08のタイミングで倒した瞬間に$00AC=FFがセットされて画面に出現。これが1フレームごとに-1ずつ減算され、00になると同時に画面から消滅します。
 なので、アドレス$00ACに00以外の値を書き込み続けることで常に幽霊船ゾンビを画面に固定することもできます……が、それはあまり面白くないですよねぇ。

<母艦のカウントダウン処理をハックする>

 母艦($006B)が08からカウントダウンする…ということは、そのルーチンがプログラムに存在するはず。
 そんなわけで、当該処理をFCE-UXのデバッガで実際に見てみましょう。

1.母艦が出現した瞬間にポーズ。

2.FCE-UXでDebug→Debuggerを起動し、Breakpointの[Add]でAddress 006B-006BをWriteにセット。

3.ポーズを解除して少し待つと、下記の箇所で自動停止する。
>00:ED88:C6 6B DEC $006B = #$06

4.デバッガの[Run]をクリックするとゲームが再開&再び自動停止し、デバッガの表示が下記のように変化する。
>00:ED88:C6 6B DEC $006B = #$05

 DECはデクリメント(1減らす命令)で、母艦が形態変化するタイミングで毎回$006Bが1ずつカウントダウン書き込みが行われ、デバッガのブレークポイント機能が「$006BへのWriteを検出し、プログラムを停止」させています。
 なので、アドレス$ED88にある2バイトコード”C6 6B”が「母艦を形態変化させるルーチン」というコトですね。

<ROMを書き換えてみる>

 ファミコン版スカイデストロイヤーが発売したのは1985年でROM容量もたったの24キロバイトしかないので、バイナリエディタで C6 6B とサーチするだけであっさり見つかります。
 ファミコンのCPU(6502)では「何もしない命令nop = EA」なので C6 6B を EA EA と書き換えることで母艦が「出現しても08のまま動かない固定建造物」になります。

<さらに幽霊船ゾンビを追跡!!>

 前述のとおり幽霊船ゾンビのX座標はアドレス$00ACに格納されているのですから、固定化された母艦を倒したタイミングで幽霊船ゾンビを出現させ、ブレークポイント00AC-00ACにWriteで仕掛けると――

>00:FA00:C6 AC DEC $00AC = #$4B

 まあ当然出てくるわけです。
 これを EA EAに書き換えると幽霊船ゾンビも固定建造物と化します。

 ちなみにDEC $00AC はもう一つ存在しており、こちらは「母艦を倒す前に00AC-00ACにWriteブレークポイントを仕掛ける」ことでヒットします。

>00:D6EE:C6 AC DEC $00AC = #$00

 実はプログラム的には面白い仕組みになっていて、コードが実行された瞬間、符号無し整数00をマイナス1し、00→FF(幽霊船ゾンビの初期カウンタ)がセットされます。

 当然、ここを EA EAに書き換えてしまうと幽霊船ゾンビに内部カウンタFFがセットされることは一生なくなるので「幽霊船ゾンビが絶対に出現しない改造バージョン」という悲しいシロモノになってしまいます。

 さらに、このヒット位置から少し上に遡ると以下のコードが見つかります。

00:D6E6:A5 30 LDA $0030 = #$02
00:D6E8:29 03 AND #$03
00:D6EA:C9 02 CMP #$02
00:D6EC:D0 0C BNE $D6FA
00:D6EE:C6 AC DEC $00AC

 これを人に分かる言語に解釈すると次の通り。

00:D6E6:A5 30  アドレス$0030をレジスタAにロード
00:D6E8:29 03 レジスタAと2進数11との論理積を取る。
00:D6EA:C9 02 その値が02
00:D6EC:D0 0C でなければ下の処理を飛び越えて次へ。
00:D6EE:C6 AC 幽霊船ゾンビ出現!

 このうち、$0030に格納されているパラメータ=時間帯であり、02=夜です。
 ここまで言えば勘の良い人なら気づきそうですが、最後にこんな画像で本記事を締めるとしましょう。

// 夜かどうかを判定するルーチンをnopで破壊
C9 02 D0 0C → EA EA EA EA (夜判定無効化)

\明るい幽霊船ゾンビ!/