クチバジムのゴミ箱をデバッグする
ちょっと考えたら出来そうだったので手動バイナリパッチでなおしてみた。
動画
2nd ゴミ箱のテーブルを圧縮しつつ未使用エリアを 00 ではなく FF に変更。
and演算のバグを修正、隣接数にかかわらず 0-3 で乱数を振って FF を引いたらリトライするように変更。
2ndゴミ箱失敗時のコードは改変の余地が少なすぎるので、テーブルを詰めて開いた領域に 1st ゴミ箱の乱数生成用コードを追加、call の飛び先を変更。
クチバシティ外観でのリセットコードは余裕があったのでそのまま cp 0F から jp nc に変更。
0001a33b: fe 0f 30 f9 ea
0005fe10: 21 65 7e fa 51 cd 47 87 87 00 16 00 5f 19 00 e5
0005fe20: cd 8c 3e cb 37 e6 03 e1 16 00 5f 19 7e fe ff 28
0005fe30: cb 00 e6 0f ea c3 d6 3e 3b 18 27 fa c3 d6 47 fa
0005fe40: 51 cd b8 28 11 21 f2 d6 cb 8e cd a1 7e 00 00 ea
0005fe60: 3e 3d c3 25 3f 01 03 ff ff 00 02 04 ff 01 05 ff
0005fe70: ff 00 04 06 ff 01 03 05 07 02 04 08 ff 03 07 09
0005fe80: ff 04 06 08 0a 05 07 0b ff 06 0a 0c ff 07 09 0b
0005fe90: 0d 08 0a 0e ff 09 0d ff ff 0a 0c 0e ff 0b 0d ff
0005fea0: ff cd 8c 3e fe 0f 30 f9 c9 00 00 00 00 00 00 00
No available modular metadata for modular package
fedora33 のしばらく放置してた環境を update しようとしたら No available modular metadata for modular package というエラーがいっぱいでて上がらなくなった。
modular 周りの仕様が変わったのか、updates-modular 周りのパッケージ更新が失敗する状態だったのでいったん dnf update dnf で dnf のみをアップデートすると動くようになる。
(常時起動機は自動更新かけてるけど wsl とかだとついつい更新わすれてしまう・・・)
AGDQ2021 japanese restream解説参加れぽ
AGDQ2021 japanese restream で初代ポケモン図鑑完成RTAの日本語解説させてもらいました。
ゼロから解説参加するまでのRTAをご紹介。
1/4 解説公募していることを知る
実は通しでみたのは初めてなので解説は事前に集まったボランティアスタッフによるものだとおもってました・・・
ゲーム中に飛び入り解説(野生の解説者)しているのをみたことと、初代ポケモンでバグ使うカテゴリがあったので、やってみようかなと思いたちます。
1/5 予習
「さすがに見ればなにやってるかくらいわかるだろ」と思ってspeedrun.com に向かいワールドレコード動画を眺めます。
「なるほどわからん」
guideを眺めると最新チャートがあったのでとりあえず読んでみます。
「なるほどわからん」
用語がさっぱりわからず頭を抱えます。
「アイテムを north connectionと入れ替える」「9Fをつかう」「T-Fry」「LG」「Unjack」とかかかれてもわかんないです!!!
ということで、動画とチャートとメモリマップとglitchcity archiveを眺めながらちょっとずつ紐解いていくことに・・・
1/6 意を決して応募する
あるていど解説できそうな気になってきたので、応募して退路を断ちます。
(応募して数分でdiscordでメンション飛んできてびびりました)
ここからはひたすら動画を見ながらチャートを訳していく作業をします。
ついでに事前に必要なバグ知識をまとめておきます。
日本語版の様々なバグ技はよく知られているので多少冗長になるかな?とは思いつつ、全く知らない人向けに説明を混ぜつつ、バグマスターでも楽しめるような小ネタを混ぜておく、という方針で解説つくりました。
大枠ができるまでほぼ丸一日、といった感じです。
1/9 マイクテスト
事前にスタッフを呼んでマイクテスト、ということだったのですがお願いしようと思ったタイミングでトラブル起きてそうだったり深夜になってしまったりしたので前日まで伸ばしてしまいました。
テストでは単に音声設定の確認だけでなく、応募時に貰うマニュアルでの操作の不明点などの確認、その他相談事項などの確認を手厚くしていただきました。(discord初使用・・・)
最初は10分~15分くらい時間あるときにやっておくと良いと思います。
1/10 本番
ここまでくると楽しみのほうが勝っていたので特に緊張せず。得意分野だし。
最終盤以外はハイスピードに進むのでほぼチャート追うだけで、多少余裕があったら細かい解説をアドリブで挟む感じでした。
いくつか反省点を挙げると
- なんで「赤」「緑」と「Red」「Blue」になったかの説明をしようと思って忘れてた
- 日本語はマリオとルイージの赤と緑、アメリカ版は星条旗の赤と青、でそれぞれ出したと言われています
- 序盤の乱数調整ミス、ライバル初戦時点で失敗確定してたのに気が付いてなかった
- 元チャートにステータスごとの特殊16到達可否かいてあったのに写してなかった・・・
- 一部チャートを追うのに必死で途中画面見落としてたりしたので状況にあってない解説してたところがあった
- 主にカビゴン捕獲前のところ、ボックスを変えに行くと思ったら変えに行かなかった
- ななしのどうくつでの捕獲数が少なかったのでボックス変更不要だったらしい
もうちょっと頑張れたかな、という気はしますが初参加だし盛り上がったしゆるして。
ちなみに、セットアップ中に「エンディング呼び出し?」とか意味の分からないことを話していますが、これは解説者用の画面共有に突然 japanese restream のスタッフロールスライドが突然出てきたからでした。
あとから見たら配信には乗ってなかったので結果的に意味不明な発言に・・・
おまけ:チャットで来ていた質問で返しきれなかった部分
Q: 「4」 をつかってポケモンを出すのは任意コード実行に引っかからないのですか?
A: 長い名前の道具を使ってバッファオーバーフローを起こした場合はあくまでデータを書き換えているだけで、プログラムを実行していません。バッファオーバーフローを利用してイベントプログラムのポインタを書き換えたりすれば任意コード実行禁止に抵触しますが、ポケモンが出るのは特定のアドレス(日本語版でいうD03A)に数値を書きこんだことにより起きるもともとのプログラムの挙動です。
Q: 海外版で新しく使えるようになったバグはありますか?
A: 有名どころでは Old man glitch と呼ばれるバグがあります。今回のチャートでは採用されていませんが、トキワの捕獲チュートリアルを見た直後にグレンに飛ぶことで主人公の名前に応じてポケモンを出すことができるバグです。
Q: この(バグを使って151匹集めた)状態から正常に戻せる?
A: 正常、をどう定義するか次第ですが、基本的にイベントフラグ周りしか弄ってないんでなんとかなるんじゃないでしょうか・・・
マップ周りはいくら壊しても再読み込みで復旧できるので、みためほど壊れていません
Q: 初代でつくったミュウを金銀に送ったらコイキングになった
A: 初代では「見た目の種族」と「中身の種族」があります。おそらく姓名判断でコイキングからつくったんじゃないかと思いますが、それは見た目ミュウですが中身はコイキングで、金銀側にコンバートするときに中身の種族だけを見るので化けの皮が剥がれるのです。
Q:セレビィを初代で作る方法はありますか
A: 金銀側のタイムカプセルのテーブルに存在しないので絶対に無理です
Q. バグによってROMごとおかしくなることはありますか
A: 原理上ありえません。最悪でも完全データ削除すれば元に戻ります。
Android VLCで日本語が文字化けするのをなんとかする
AndroidのプレイヤーをVLCに切り替えてWindows上で入ったSHIFT-JISなメタデータが読めなくなってさすがに辛いものがあったのでなんとかした。
それっぽい記事が@ITにあるのでとりあえずそれに従ってEasyTAGを入れて SJIS → UTF-8 にしてみたところ、Fedora の Rhythmbox では読めるようになったがAndroidのVLCではやっぱり読めない。
どうも、AndroidのほうはUTF-16 (どっちのエンディアンなんだろう・・・)設定にするべきらしく、出力をUnicode(UTF-16)にしてやったら読めるようになった。
ということで、こんな感じで設定して Force Save Files すればVLCで読めるメタデータが書き直された。
dnf system-upgrade で fc31とfc33なパッケージが混ざった上glibcが消えたシステムの復旧
system-upgrade のたびに壊れることに定評のある 7年物の fedora 環境、leafeon.msmrrenda.net がまた壊れました・・・
(前回:dnf system-upgrade 中に固まったシステムの復旧)
どうも、fedora31から33にあげてるときに何らかの依存関係がうまくいかなかったらしく、glibcがおかしくなったりしたようです。
ログインしようとしたらsshd がsegvするんで、とりあえずコンソールをとって、何を思ったか dnf remove glibc-*.fc31 した馬鹿がこちらになります。
もちろん実ファイルを巻き込んで glibc.fc31 が消え、メタデータだけの抜け殻となったglibc.fc33が残っていますが、こうなっては単独では詰みです。
ということで、例によって install disk から起動しようとして頭を抱えます。virt-manager が壊れたvmにしか入ってないので使えねぇ・・・
virsh edit でエラーを吐きまくりながら書いた xml をたぶん来年も壊す自分のために残しておきましょう。
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/var/tmp/Fedora-Everything-netinst-x86_64-33-1.2.iso'/>
<target dev='hdc' bus='ide'/>
<readonly/>
<address type='drive' controller='0' bus='1' target='0' unit='0'/>
</disk>
無事起動したらまずは root filesystem をマウントしておきます。
で、dnf や rpm が途中でクラッシュしたので壊れてるであろう rpmdb を直してから glibc を再インストールします。
(試したときは dnf install からやって、なんか暴走し続けたので kill -9 したら完全に壊れた)
mkdir /mnt/chroot
mount /dev/vda3 /mnt/chroot
chroot /mnt/chroot rpm --rebuilddb
dnf reinstall --installroot=/mnt/chroot --releasever=33 glibc glibc-common
glibc が復活したのでこれで起動できるようになります。
祈りながら再起動したら上がってきたので、とりあえず dnf update --releasever=33
しなおすも、やっぱり fc31 と fc33 が同居したような状態になってしまったので、
dnf check –duplicate
で出てきた fc31 なパッケージを全部 rpm -e –nodeps –justdb
して、 dnf reinstall '*'
をするときっと治るとおもうのでいまやってます・・・
もしかして:毎年壊れるアップグレード復旧コストを考えると ansible か何かにしておいて毎回一から作り直すほうが早い
初代ポケモン ボックスSRAMと初期化済みフラグ
初代ポケモンではボックス領域に専用のSRAMバンク2と3が使われています
(SRAM1がメインのセーブデータ、SRAM0がでんどういり情報っぽい?)
SRAM2 はボックス1-4 を保持しており、SRAM3 はボックス5-8 を保持していて、内部構造は D9B2 以降をまるごとコピーしたもの。
これとは別に、「現在D9B2 にロードされているボックス番号」を保持する領域D51F があります。
たとえば、ボックス1を見ているときは 0x80、ボックス8を見ているときは 0x87 が入っています
D51F の最上位bitは「そのセーブデータを作った後 SRAM2,3を初期化したか」というフラグに使われており、これが立っていない場合はゲーム開始後にSRAM2,3を初期化していないものとして扱います。(データを消さずに「さいしょからはじめる」をするとセーブデータを維持したままになるため)
ゲームを開始してはじめてボックスを切り替えるとき、D51F は 00 なので、「初期化されていない、ボックス1が選ばれた状態」となります。
ここでボックスを変えようとしたとき、はじめてSRAM2,3の最低限の初期化が走り、各ボックスのポケモン数を0、ボックスの先頭の見た目を FF にされることで「なにもいない」状態になります。
ということで、ボックス切り替え処理というのはこんな処理です:
- 選択中ボックス番号の最上位bitが立っていなければSRAM内のボックスデータを初期化
- 現在の WRAM D9B2 以降にある選択中ボックスデータを、WRAM D51F に記載されている「選択中のボックス」をもとに算出した SRAM の領域に書き出す
- 選択されたボックスを SRAM から WRAM D9B2 以降に読み込む
- WRAM D51F に ボックス番号(0-7) + 0x80 を書き込む
なので、実はボックス1を選んでいるときに D51F をいじって 0x81 とかにしてボックスを切り替えると、ボックス2にボックス1の内容をまるごと上書きしだすことになります。
日本語版の場合
書き込み先バンクは (D51Fの値 & 0x7F) < 4 なら SRAM2、それ以外ならSRAM3です。
その中のオフセットは (051Fの値 & 0x03) で決まります。
0,1,2,3 のとき、それぞれ A000, A566, AACC, B032 になります。
0x88とか指定した場合でも、バンクは3、オフセットは0なのでボックス5の場所を指します。
以下は余談です
もともとボックスが一つだったころ、おそらく D9B2 以降のボックス領域がそのまま単純にボックスだったのでしょう。
途中でニックネームを保持するためにSRAMの多いカートリッジを使うことが決まり、後付けでボックス切り替えを実装したという話はポケモン・ストーリーという本で語られています。
このボックス切り替えコードから、ボックス専用SRAMが後付けされ、そことWRAM上にあるボックスの同期をとることで、もともとの1ボックス時代のコードを生かしつつ複数ボックス切り替えを最小限の追加コードで実装しようとした当時の空気が感じられました。
msmrrenda.net 全域の動作確認環境変更
これまで開設以来 msmrrenda.net 全域の動作確認環境はその時々において最新の google chrome でしたが、本人のメインブラウザ乗り換えに伴い vivaldi に変更します。
とはいえ、エンジンは同じですし、UAでのだし分け等はしていないので何も変更はないはずです。
(そもそも最近新コンテンツが増えていないので、vivaldi 向けに何か手を加えることもない予定です)
dnf system-upgrade 中に固まったシステムの復旧
5年モノくらいの Fedora27 環境を dnf system-upgrade していたところ、
ディスクを載せていた glusterfs が機嫌を損ねて固まってしまいリセットを余儀なくされました。
当然アップグレード中にそんなことをすればもろもろのライブラリバージョンの不整合で動かなくなるわけで・・・ Live DVD で起動してのシステム復旧を試みることに。
- Fedora29 Live DVDで起動
- /mnt/sysroot 以下に元々のルートファイルシステムをまるごとマウント
- fedora-release-27-1 を削除
- 27と29が共存しているので、削除しないと dnf が releasever=27 と設定してしまう
- dnf –installroot=/mnt/sysroot update
- 最低限これで rpm が動くようになったので、rpm DB 上に f27 と f29 のパッケージが同居してしまっているものを処理します。(この時点でまだ中のdnfは動かない)
- dnf check –duplicate で重複パッケージをリストアップ
- chroot して f29 の方を rpm -e –nodeps –justdb で DB から削除
- f29 を消せばとりあえず再度アップデートが走る状態になり、実在しているのがどちらのバージョンであろうと f29 版に上がってくれることが期待できます
- chroot を抜けて dnf –installroot=/mnt/sysroot update をやりなおす
- 再起動
再起動してみたところ、dbus 周りがおかしそうでうまく起動しないのでもう一度 Live DVD 環境に戻って rpm -qa | grep dbus で出てきたパッケージを reinstall したら動くように。
ついでに dnf check で出てくるdependency brokenなパッケージを適切に処理してやって対応終了。
意図せず他人のサービスを乗っ取ってしまっている
とある都合でアクセスログを眺めていたときのこと。/event/xxxx の謎のアクセスログがいっぱい。
最初はwordpress狙いのいつものかと思ったらどうやら様子が違うようで、追いかけてみるとどうやらとあるドメインが anju.msmrrenda.net のIPアドレスを向いている模様。
現anju(2代目)は2017年夏ごろにanju(初代)のリプレース先として借りたさくらのVPSなので、おそらく以前使っていたユーザがレコードを残したままにしており、それがIPアドレスの使いまわしでうっかりこちらを向いてしまったようです。
これがただの自社サイトの残骸とかだったらバーカバーカで済んだのですが、サービス提供用ドメインでわずかながらリンクが貼られてしまっているため無関係な一般ユーザも知らずにこちらに流れてしまっています。
そんなわけで急遽トラフィック吸い込み用のバーチャルホストを追加、警告ページを表示しつつ410 GONEを返すだけのページを配置しました。
410はmod_rewriteのフラグに「G」と書けば出ますが、これだと単に標準エラーページが出るだけなので410用のカスタムエラーページ設定をかいてやります。
サービスを廃止するときはちゃんとレコード消したりしましょう・・・
FreeBSD fuse glusterfsでstale NFS file handle になる問題の解消
FreeBSDマシンでfuse mountしたglusterfsの領域を別ホストから読み書きしたときに、
たびたび 「失効した NFS ファイルハンドルです / stale NFS file handle」となってremountする他なくなる状況をようやく打開しました。
(fuse cacheの実装によるFreeBSD特有の問題とまでは分かっていましたが、対策が見つかっていませんでした)
sysctl で vfs.fuse.lookup_cache_enable=0 してやると、
fuseのキャッシュが無効化されて(既に発症しているファイルも含めて)正常に読み書きできるようになります。