なるほどえたきちのブログじゃねーの

チラ裏雑記帳

ポケモン過去作の解析とか乱数調整とかそこら辺。不定期更新。

エメラルドID調整の調査記録

サムネは魔除けです。
この記事はPokémon RNG Advent Calendar 2020 6日目の記事です。

エメラルドID調整の手順そのものについては数ヶ月前に上げているので、調査の詳細に興味のある方向けの記事となります。
まあ調査記録といっても当時の記憶の書き起こしだしそこまで厳密には纏めてないけどね。
めんどくさいので画像も特にないです。
すごく読みづらいと思いますが何卒ご容赦下さい。
それと調査にあたってROMHackやマジコンを利用している為、苦手な方はブラウザバック推奨です。

また、筆者は乱数調整にあまり詳しい人間ではないので細かい所で「ん?」と思う所があるかと思いますがどうか生温かい目で見てあげてください。
文句言われてもスルーするので言うだけ無駄です。

概要



ポケットモンスターエメラルド自体は16年程前に発売されたそれなりに古いゲームで、殆どの要素において乱数調整方法が確立されていたが、トレーナーIDの決定に関しては1年くらい前まで調整不可能とされていた。
この記事では、不可能とされていた理由やその後調整できるようになった経緯等について適当に解説する。(正しく解説できる自信はない)

解説



まずはエメラルドのトレーナーID決定処理について。

// 名前入力開始
static void NameInStart(u8 type, u8* buff, u16 work0, u16 work1, u32 work2, pFunc rec_proc)
{

	Namein = (NAME_IN*)AllocMemory(sizeof(NAME_IN));
	if (Namein == NULL){
		MainProcChange(rec_proc);
		return;
	}

	Namein->name_type = type;
	Namein->arg_work0 = work0;
	Namein->arg_work1 = work1;
	Namein->arg_work2 = work2;
	Namein->set_name_buf = buff;
	Namein->rec_proc  = rec_proc;

	// 主人公名の決定時間を乱数のタネとする
	if(type == NAMEIN_HERO)
	{
		RandomTimerStart();
	}


	MainProcChange(InitNameInTask);
}
 
// 名前入力終了
static u8 NameInEnd(void)
{
	if (FadeData.fade_sw == 0){
		// 時間計測終了
		if (Namein->name_type == NAMEIN_HERO)
		{
			RandomTimerEnd();
		}

		MainProcChange(Namein->rec_proc);
		DelTask(CheckTaskNo(NameInMainTask));
		BMPWIN_SysExit();
		MEM_RELEASE(Namein);
	}
	return 0;
}

名前入力画面への遷移時にタイマーを開始し、名前決定後に経過時間をそのままトレーナーIDとして使用するという非常に単純な処理である。
ちなみにこの処理はFRLGでも使用されている。

「入力に掛かった時間がTIDになるならその入力時間を調整すれば任意のトレーナーIDが引けるのでは?」と思うかもしれないがこの「入力時間の調整」がとても難しい。
エメラルドの実行環境であるゲームボーイアドバンスはマルチスレッドに対応していない為、裏で何かしらのタスクを処理したい場合は割り込み処理を利用して実装することが多い。
割り込み処理の実行中はメインタスクの処理が停止するが、その前にセットされたハードウェアタイマーはそのまま動き続ける。
これが「入力時間の調整」を難しくしている原因となる。

この時裏で割り込み処理によって動いている処理とは何か?
BGMの再生処理である。

ゲームボーイアドバンスには先代のゲームボーイが持っていたチャンネルに加えて8bitのPCMが追加されており、サンプリングされた音源をそのまま再生できるようになっている。
これによってソフトウェアによって生成された合成音声を再生し、擬似的に同時発音数を増やすことに成功している。
ちなみにポケットモンスターエメラルドにおいて使用されているサウンドドライバは任天堂純正のMusicPlayer2000である。(Sappyとも呼ばれる。こちらの方が親しみのある名前だろうか?)
この「ソフトウェアによる音声合成」が中々に曲者で、BGMの再生位置によって合成するデータ量が大きく変動する為、処理に要するCPUサイクル数にムラが生じやすい。
ハードウェアタイマーのスタート/ストップの起点となるVBLANK割り込みから当該処理までのステップ数は一定だが、途中で割り込んでくる音声合成処理によって経過時間が変動してしまうのである。
しかし、逆に言えばBGMの再生位置と経過時間の管理によってトレーナーIDの調整が可能である、ということになる。

理論的な説明は以上の通り。後は全て力技で解決します。

ここまで分かったら「BGMの再生位置(OP開始からの経過時間)」と「名前入力画面内での経過時間」を渡してIDを概算できるようにしたい。
今回はハードウェアタイマーのスタート/ストップ処理のそれぞれに対応した「BGMの再生位置」と「処理実行までのクロック数」を紐付けたテーブルを作成する。

まずはタイマーストップ処理用のテーブル作成手順を紹介する。
BGMの再生処理を潰したROMを用意し、1フレームずつ名前入力の経過時間をズラしながら出現するトレーナーIDを確認する。
すると、1フレームにつき18752値が増えていた。
16777216(GBAのCPUクロック数) / 59.7275(リフレッシュレート) = 280896.002....
280896 % 65536 = 18752
なので、計算上でもこの結果はまあまあ正しそう。
後は未改造ROMで取得できたトレーナーIDと比較して音声合成処理によって生じたサイクル数のズレを記録していく。
この時、名前入力画面へ遷移する際のBGMの再生位置は固定するようにする。

次はタイマースタート処理用のテーブル作成手順。
名前入力画面遷移後にBGM再生処理が停止するようHackを施したROMを用意し、名前入力画面へ遷移する際のBGM再生位置を1フレームずつズラしながら出現するトレーナーIDを確認する。
この時、名前入力画面へ遷移した後の経過時間は固定するようにする。
その後、BGMの再生処理を潰したROMで同じ操作を行い、トレーナーIDの差分を取る。
この差分がタイマースタート処理実行までに発生した音声合成処理によるズレとなる。

後は記録した差分を2つ合わせた値と実際の値のズレを基準値とし、[基準値 + タイマースタートのズレ + タイマーストップのズレ = ID]が成り立つようにする。
かなりの荒技になってしまうが、一応これでエメラルドのIDの予測ができるようになった。

最後に



以上がポケットモンスターエメラルドのID調整を行うにあたっての調査内容です。
少し頭のいい方なら「もう少しスマートなやり方あるだろ!アレをソレしてこうして...」とツッコミたくなってしまうと思いますが、突っ込まれた所で基本スルーするつもりなので心の内にしまっておいて頂けると幸いです。

明日はpo氏が何か書くそうです。
当記事執筆時点では「何も考えていません。」とのことですが何が上がってくるんでしょう?
楽しみにしていますね。

【BW/BW2】全28バージョンパラメータ纏め

5世代海外版ROMのパラメータについて、適当に調べてもNazo値くらいしか見つからなかった為、海外版ROMを所持している方々と協力して全28バージョンの具体的なパラメータ調査を行った。なんと私は日本版BWすら持っていません

まずは無印BW。
Nazoはほぼ既出だが、スペインブラックのみ誤った情報が出回っているので注意。

Nazo値計算法:
Nazo1:(Nazo1)
Nazo2:(Nazo1 + 0xFC)
Nazo3:(Nazo1 + 0xFC)
Nazo4:(Nazo1 + 0x148)
Nazo5:(Nazo1 + 0x148)

バージョン名
Nazo1
VCount
Timer0
日本ブラック
0x02215F10
0x60
0xC79~0xC7A
日本ホワイト
0x02215F30
0x5F
0xC67~0xC69
韓国ブラック
0x022167B0
0x60
0xC84~0xC85
韓国ホワイト
0x022167B0
0x60
0xC7B~0xC7C
北米ブラック
0x022160B0
0x60
0xC7B~0xC7C
北米ホワイト
0x022160D0
0x60
0xC7E~0xC80
ドイツブラック
0x02215FF0
0x5F
0xC77~0xC78
ドイツホワイト
0x02216010
0x60
0xC7A~0xC7B
フランスブラック
0x02216030
0x5F
0xC73~0xC74
フランスホワイト
0x02216050
0x5F
0xC6E~0xC6F
スペインブラック
0x02216070
0x60
0xC86~0xC87
スペインホワイト
0x02216070
0x5F
0xC70~0xC71
イタリアブラック
0x02215FB0
0x5F
0xC6A~0xC6B
イタリアホワイト
0x02215FD0
0x60
0xC7B~0xC7C

次はBW2。
こちらもNazoは既出。
VCountズレという新たな概念の存在するバージョンがある為注意。

Nazo値計算法:
Nazo1:(Nazo1)
Nazo2:(Nazo2)
Nazo3:(Nazo3)
Nazo4:(Nazo3 + 0x54)
Nazo5:(Nazo3 + 0x54)

バージョン名
Nazo1
Nazo2
Nazo3
VCount
Timer0
日本ブラック2
0x0209A8DC
0x02039AC9
0x021FF9B0
0x82
0x1102~0x1108
日本ホワイト2
0x0209A8FC
0x02039AF5
0x021FF9D0
0x82
0x10F5~0x10FB
韓国ブラック2
0x0209B60C
0x0203A4D5
0x02200750
0x82
0x10EF~0x10F4
韓国ホワイト2
0x0209B62C
0x0203A501
0x02200770
0x81
0x10E4~0x10E9
北米ブラック2
0x0209AEE8
0x02039DE9
0x02200010
0x82
0x1102~0x1108
北米ホワイト2
0x0209AF28
0x02039E15
0x02200050
0x82
0x10F2~0x10F6
ドイツブラック2
0x0209AE28
0x02039D69
0x021FFF50
0x81~0x82※1
0x10E5~0x10EC※1
ドイツホワイト2
0x0209AE48
0x02039D95
0x021FFF70
0x82
0x10E5~0x10ED
フランスブラック2
0x0209AF08
0x02039DF9
0x02200030
0x82
0x10F4~0x10F8
フランスホワイト2
0x0209AF28
0x02039E25
0x02200050
0x82
0x10EC~0x10F0
スペインブラック2
0x0209AEA8
0x02039DB9
0x021FFFD0
0x82
0x1101~0x1106
スペインホワイト2
0x0209AEC8
0x02039DE5
0x021FFFF0
0x82
0x10EF~0x10F4
イタリアブラック2
0x0209ADE8
0x02039D69
0x021FFF10
0x82~0x83※2
0x1107~0x110D※2
イタリアホワイト2
0x0209AE28
0x02039D95
0x021FFF50
0x82
0x10FF~0x1104
※1 ドイツブラック2
Timer0の値が0x10E5~0x10E8の場合はVCount-0x81、0x10E9~0x10ECの場合はVCount-0x82となる。
※2 イタリアブラック2
Timer0の値が0x1107~0x1109の場合はVCount-0x82、0x1109~0x110Dの場合はVCount-0x83となる。
Timer0-0x1109に限りVCount-0x82とVCount-0x83の両パターンが存在する。

【ポケモンXY】ID調整

事の発端はこちら。
 ↓
sina-poke.hatenablog.com


XYのID調整に成功したので適当に調整手順等を纏めます。
(元々纏める気なかったけど)




疑似乱数周りの仕組み



IDの決定自体はORASと同様にTinyMTが用いられており、初期seedも同様に起動時刻によって決まっている。
但し、OP内でキャラクターオブジェクトのまばたきによる不定消費が発生している為、ORASと同様の手順ではseedの特定が難しい。
ここで使用されているまばたき処理は以下の通り。
(滅茶苦茶単純である)

u32 _counter;

void init()
{
	_counter= 0x021E - ((rand() * 0xB4) >> 0x20) << 0x01);
}

void next()
{
	_counter--;
	if (_counter == 0)
	{
		init();
	}
}

また、名前入力画面に遷移した際の1消費以外にその他消費は行われていない模様。
OP内ではキャラクターの数が変動する箇所があり、これによって時間あたりのおおよその消費速度が変化する。
キャラクター数の変動の仕方は以下の通り。


1人 (博士)
 ↓
2人 (博士,メェークル?)
 ↓
1人 (博士)
 ↓
3人 (博士,男主人公,女主人公)
 ↓
文字入力画面 (まばたき判定停止)
 ↓
3人 (博士,男主人公,女主人公)
 ↓
4人 (博士,男主人公,女主人公,選んだ方の主人公)


また、OPの最後に現れる主人公は名前確定時にまばたきカウンタのリセットを行っているよう。
名前確定→まばたきカウンタリセットまでの空白時間は主人公の性別によって異なっている。


ID調整方法の考察



TinyMTの初期seedはORASと同様に決定されている為、TinyMTを元に生成された値を観測することができれば32bitの総当たりによって初期seedの特定が可能となる。
但し、ID決定までの消費数が不定である都合上ORASと同じ手法は使えない。(使えたとしてもミリ秒ゲー以上の難易度になるが)
ID決定以外の乱数消費には「キャラクターのまばたき処理」があり、これは「まばたきのインターバル」という形で乱数値を使用する。
その為、今回はキャラクターのまばたきの長さを利用して32bitの総当たりを行い、現在seedを求める。
キャラクターが1人である状態なら、「現在seed」と「1人のキャラクターが持つまばたきカウンタの値」の2つを得ることで乱数値の制御が可能となる。
シーンの切り替わりによって新たに登場するキャラクターのまばたき処理についても、前述した2つの値が分かっていれば「シーン切り替わりの契機となる操作タイミング」を管理するだけで制御可能。
その為、今回の乱数調整では「キャラクターが1人である状態からまばたきのインターバルを複数記録して現在seedを特定した後、3DSの操作タイミングを管理することによって後に現れるキャラクターのまばたき処理を全て制御する」といった形でOP中の乱数消費を再現する。

キャラクターのまばたきのインターバルは最長542F(約9秒)、最短でも184F(約3秒)である為、時間あたりの消費速度はかなり遅めである。
また、まばたき以外の不定消費が存在していない為、消費速度を踏まえると操作精度が余程低くない限りは消費数がズレる可能性は低い。

調整にあたっての理論的な説明っぽいのは以上の通り。
これらの作業を簡潔に行う為のツールを作成したので使い方を適当に紹介する。
DL:https://bzl.hatenablog.com/entry/2090/11/11/000000#6genTidSearch


基準seedの特定



o3DSではラグの影響で消費の進む速度に若干の遅れが生じるようです。
このツールはラグの考慮を一切行っていない為、極力n3DSを使用して乱数調整を行うことを推奨します。

OP開始後、この画面まで進めておく。

6genTidSearchを起動し、[XY]→[基準seed検索]タブを開く。
初回は『全範囲探索』を選択し、その後OP内のプラターヌのまばたきに合わせて『瞬き』ボタンを押してまばたきの空白時間を記録する。
(数分間見つめ合ってるとちょっとロマンチックな雰囲気になってくる)
まばたきの空白時間を10個程記録したら検索を開始する。
2回目以降の検索を行う際は『基準seedから探索』を選択し、前回特定した初期seedを入力する。

seedが見つかった後、セルをダブルクリック又は『seedを選択』を押しておく。


目的のIDの検索



ID検索タブを開き、許容する消費数と目標IDを入力して検索を開始する。
ここで目標のIDが見つからなかった場合はリセットし、再度seedを特定する。
(複数候補の検索したかったら3DSRNGTool使ってね)


まばたきズレの補正



目標IDが出現するseedであった場合は消費数管理タブを開く。
『瞬き調整』内の開始ボタンを押すとプラターヌの瞬きに合わせて音が鳴るようになる。
但し、目視でまばたきを観測している都合上、実際のまばたきタイミングとはズレが生じている。
ここではその誤差の補正を行っていく。
基本的にはプラターヌのまばたきより遅く音が鳴っている為、『早める』を押してズレを縮めていく形となる。
プラターヌのまばたきと鳴る音のタイミングが一致したらこの手順は終了。


まばたき消費制御



ツール内で主人公の性別を選択する。
その後、以下のシーンでAボタンを押すのと同時に『ステップ(F9)』を押して消費の制御を行っていく。
また、名前確定時を待機フレームの始点としている為、CCTimerを使用している場合はF9キーを使用することを推奨する。


>> 主人公の性別選択

>> 名前入力画面

>> 名前決定

>> 名前確定



操作終了後はこの画面で待機を行う。

消費範囲を指定後、『計算』を押してリスト出力を行う。
ハイライト部分は「現段階でAボタンを押すと引くことのできるID」となっている。

出力されたフレーム数に合わせて待機を行い、出現したIDを確認する。
目標のIDが無事に引けていれば成功。


あとがき



XYの方は特に纏める予定はなかったのですが、任せられてしまったのでこちらも書くことにしました。
以前纏めたORASと比較すると手順は若干ややこしいものの、狙ったIDを引きやすいのでNN目的でID調整を行う方はこちらの方が都合良いかもしれませんね。
これを応用するとフィールド上でTinyMTのseedが特定できるようですが使い道がよく分からない...

【ポケモンORAS】ID調整

ORASのID調整に成功したので適当に調整手順等を纏めます。





疑似乱数周りの仕組み(ID決定に関係するもののみ)

  • 乱数生成器はMT、TinyMTの2種類
  • ID決定にはTinyMTが使用される
  • それぞれの乱数生成器の初期seedは別の値になるが、「(セーブデータ依存の値)+(起動時間ミリ秒)」という点は共通
  • セーブデータが存在しない場合、「セーブデータ依存の値」は固定される
  • ID決定までのTinyMTの消費数は[13 + (名前決定後『いいえ』を選択した回数)]となる


ID調整方法の考察



ID決定に使用されるTinyMTは非線形となる処理を用いて乱数値を生成する為、逆算は困難。
但し、初期seedは高々32bitである為、以下の点を踏まえれば「起動時間を管理しながら出現するIDを複数個観測する」ことにより総当たりで特定可能なことが分かる。

  • 初期seedは「(セーブデータ依存の値)+(起動時間ミリ秒)」
  • セーブデータが存在しない場合、「セーブデータ依存の値」は固定される
  • 名前決定後、『いいえ』を選択しなければID決定までの消費数は固定される

初期seed決定に使用される起動時間は厳密には1ミリ秒単位だが、流石に人間業では管理不可能なので1秒(1000ミリ秒)程度に幅を広げる。
この場合、IDを4個ほど観測すれば充分に初期seed(以降基準seedと呼ぶ)を絞り込むことができる。

基準seedに経過時間ミリ秒を足した値がそのまま初期seedとなる為、ソフト起動時に1ミリ秒を合わせれば任意のIDを引くことができるようになる。
また、ミリ秒を合わせずとも出現したIDがどのseedから生成されたか高い精度で絞り込める為、SID/TSV/TRVの把握が非常に簡単に行える。

調整にあたっての理論的な説明っぽいのは以上の通り。
これらの作業を簡潔に行う為のツールを作成したので使い方を適当に紹介する。
DL:https://bzl.hatenablog.com/entry/2090/11/11/000000#6genTidSearch

基準seedの特定



ゲームを新しく開始し、出現したIDを確認する作業を4回行う。
この際にカウントダウンに対応したタイマーとカウントアップに対応したタイマーの2つを用意する。
この内前者は基準seed特定時の時間管理、後者は作業全体の時間管理に使用する。
1回目の確認を行う際、ソフト選択と同時に2つのタイマーを開始する。
筆者が調整した際は自作のタイマーを使用した。
DL:https://bzl.hatenablog.com/entry/2090/11/11/000000#CCTimer


基準seed検索タブの設定内容は以下の通り。

  • 「TID1-4」 → 出現したIDを入力する。
  • 「経過時間」 → [(ソフトの起動時刻)-(1回目のソフト起動時の起動時刻)]を秒数で入力する。
  • 「許容誤差」 → ソフト起動時刻の誤差の幅をミリ秒で入力する。

一通りの入力を済ませたら検索を開始する。
PCスペックにも依るが少し時間が掛かる。(検索処理が雑すぎるだけ)
複数の候補が表示された場合はミリ秒ズレの幅を見て現実的であるものを選ぶ。


目的のIDの検索



ID検索タブを開き、特定した基準seedを入力する。
目標ID条件を入力したら検索を開始する。
現在の経過時間から目標のフレームを決め、待機を行う。
この際に実際に待機する時間は[(出力された待機時間)-(1回目のソフト起動から経過した時間)]となる。

指定された消費数分TN決定後に『いいえ』を選択して乱数の消費を行う。
消費が終わったら『はい』を選択し、自由に動けるようになった時点でIDを確認する。
目標のIDでない場合、ズレ確認タブを開く。
目標フレームのseed、消費数と実際に出現したIDを入力し、計算を開始する。
ここで表示されるズレはミリ秒単位。
SID/TSV/TRVも出力されるので、これらの値を把握することが目的であるならここで作業終了してもよい。
任意のIDを狙う場合は再度目標フレームを決め、この手順を繰り返す。


あとがき



ポケモンXYのID調整に成功した」という噂を風の便りに聞いたので便乗してみました。
XYは持っていなかったので、取り敢えず手元にあったORASでチャレンジしてみましたがミリ秒合わせはかなり難しかったです…
難易度的に考えるとSID/TSV/TRVの把握の為に使った方がまあまあ実用的かと思います。
XYの方の手順/ツール等は噂の種の方が纏めてくれそうなのでそちらを待ちましょう。
詳細は知りませんがこちらはミリ秒ゲーではないようです。

XY買ったので調べてみたらできました。

bzl.hatenablog.com

作ったツールなど

何か気が向いたので、適当に作ったツールを纏めてみます。
ツール置き場(Google Driveに飛びます)

ハックロム開発用

ValzHex (バイナリエディタ)

開発言語 : C#

  • C#で多分初めて作ったツール。
  • バイナリエディタに関して周囲ではStirlingが一般的に多く使用されていたが、強制終了等のバグが多く微妙に不便だったので作った。
  • UI/基本機能はStirlingに搭載されていたものを参考に、ハックロム開発においてそれなりに使いそうな新機能を手当り次第適当に突っ込んだ。
  • デザインが陰湿なオタクっぽいので気に入っている。

追加した記憶が残っている機能は以下の通り。

f:id:BZL:20200623191921p:plain

GBA General Compressor (画像導入ツール)

開発言語 : VB.Net

  • プログラミングに触れてから多分初めて作ったツール。
  • 制作期間は1-2日くらい。
  • 既存の圧縮画像導入ツールが揃いも揃ってなんか致命的なバグを抱えていたので作った。(詳細はこちら)
  • LZ77圧縮アルゴリズムで参考になりそうなものが見つからなかったのでフルスクラッチで頑張った記憶がある。
  • 結果として、何かよく分からないが最高の圧縮率と解凍バグ回避を両立させることができた。

f:id:BZL:20200623194459p:plain

PokeDataGenerator (個体情報作成ツール)

開発言語 : VB.Net

  • ハックロムの各種データ拡張に対応した手持ちデータ作成ツールを要求されたので作った。
Trainer Edit (トレーナー情報編集ツール)

開発言語 : C#

  • 各種データ拡張に対応したトレーナー情報編集ツールが欲しくなったので作った。
  • シンセの代替品にできるように機能拡張する予定。
Space check

開発言語 : C#

  • 空き領域を検索してリスト表示するだけのツール。
BINtoIPS

開発言語 : VB.Net

普通にゲームを楽しむ為のツール

SW Seed Calculator (レイド乱数Seed検索ツール)

開発言語 : C#, C++

  • 8世代乱数調整が盛り上がっていたのでノリで作ったツール。
    レイド乱数用の初期Seedを検索できたりできなかったりする。
  • 学歴の都合上数Ⅱまでしか履修していないので検索処理の実装に滅茶苦茶苦労した。
  • 巣穴リストやGPU検索等の機能を1番初めに実装したツールだったりした気がする。(今となっては殆どのツールにある機能だけど)
  • 検索速度に拘りを持っていた時期があったので4連続個体値等でも現実的な時間でSeedを求められるようになっている。
  • もう少し検索処理を速くする案がいくつかあるのだが、再度数学とバトルしたり慣れないアーキテクチャアセンブリコード書かされたりしそうなのでまだ手を付けていない。
  • リスト表示機能は実装していないが、夜綱氏の8denSearchと機能連携させる形で対応している。→8denSearchの紹介記事

f:id:BZL:20200623201314p:plain f:id:BZL:20200623201418p:plain

TIDFinder (エメラルドID調整ツール)

開発言語 : C#

  • 乱数調整してるオタク共の集落に首を突っ込んだら「エメラルドのID調整は不可能」と色々な所で言われていたので作ったツール。
  • 実際の所、調整できないことはないが滅茶苦茶難易度高い。
  • 使い方とかの解説記事はこちら。

f:id:BZL:20200312221346p:plain

CCTimer (タイマー)

開発言語 : C#

  • トロデザインなフォームで何か作りたかったので突貫工事で制作した。
  • EonTImerの丸パクリ。

f:id:BZL:20200312221907p:plain

NX Macro Controller (Switch用画像認識マクロ管理ツール)

開発言語 : C#

  • OpenCVを使った何かを作ってみたかったので作った。
  • 作ったマクロを外部ファイル保存して他人にバラ撒くことができる。
  • 操作の記録機能や入力用フォーム等を用いて、GUI上の操作だけである程度自由にマクロを作ることができる。
  • ポケモンに関して言えばこれより良いツールいっぱいありそう。

f:id:BZL:20200120155920p:plain

用途不明

334Timer (タイマー)

開発言語 : C#

  • 3時34分に「334」とツイートするアレを高い精度でやりたかったので作った。
  • 目標の日付とミリ秒単位のズレを入力することでいい感じに時報ツイートを行える。
  • 慣れれば±8msくらいで大体安定する。

日本版エメラルドID調整

ほぼ不可能と言われていたエメラルドのID調整に成功しました。
先に言っておきますがルビサファのように簡単ではないのである程度乱数調整に慣れている方向けだと思います。
私自身は乱数調整したこと殆どないけど


まずIDの決定方法について。
決定タイミングは名前入力画面→OPの画面遷移時。
OP→名前入力画面の画面遷移時に開始したTimer-1の値を使用してIDを決定している。
この値はLCG32の乱数値とは異なり1F間隔ではなくCPUのクロック単位で値が変動する為、人力での調整は不可能と言われていた。
しかし、キー入力判定自体は1F間隔なのでいつも通り(?)フレームを合わせれば現実的な難易度でIDの再現ができる。
各フレームで出現するIDを予測することも可能だが、数式等で簡潔に表せるものではない為、詳細は割愛する。
数式等に起こす自信のある人が居られましたらちゃんとした情報提供するので連絡ください

因みに、SIDは通常のLCG32を用いて決定されている。
ID決定時にIDと同じ値をSeed値として格納している為、名前決定からOP終了までのフレーム数を調整すればIDからSIDを予測できる。

必要なもの



TIDFinder
・好みのタイマー(当記事ではCCTimerを使用しています)
・ボタンモードLR、サウンドステレオ設定の日本版エメラルド(海外版でも多少ズレはあるが可能)
・GBAROMが起動できるハード
神を信じる心

目標のIDを決める



適当に決めましょう。
今回はID00000を狙います。
同時にSIDのリストも表示されますので調整したい場合は適当に候補選んでおいてください。
f:id:BZL:20200312221346p:plain
赤字で表示されるものはSelectズレを使用することで目標ID付近が狙えるフレームです。
Selectズレによって目標ID付近が狙えるフレームの場合、ツールに表示されている回数分、名前入力画面でSelectボタンを押下してキーボード切り替えを行います。
そうでないフレームの場合はSelectボタンの押下回数が表示されている回数と一致しないようにします。
このフレームの場合はSelect押下回数0でズレが発生する為、平仮名のみのTNを使用する場合でもキーボード切り替えを行うようにします。

実践


!注意

ここでのキー入力は長押しではなくすぐ離すような形にしてください。
画面遷移時にキー入力が発生していると出現するIDが少しズレます。(ズレる値はフレームと入力されたキーによって変動する)
フレーム合わせ後はIDの微調整に利用可能なのでお試しあれ。


実際にやってる所を撮影したので参考程度にどうぞ。

今回狙うフレームはFrame1が1636F、Frame2が1208Fなのでこのようにタイマーセットしておきます。
f:id:BZL:20200312221907p:plain

まずはロード画面で『さいしょから はじめる』選択と同時にタイマーをスタートします。
f:id:BZL:20200312221657p:plain

この画面でFrame1の指定フレーム分待機を行います。
f:id:BZL:20200312222219p:plain

この画面でFrame2の指定フレーム分待機を行います。
Selectズレの調整も忘れずに。
f:id:BZL:20200312222420p:plain

SID調整を行う場合、この画面でFrame3の指定フレーム分待機を行います。
f:id:BZL:20200312222451p:plain

入力フレームに誤りがなければ、目標IDにある程度近いIDが出ると思います。
この手順を目標IDが出るまで繰り返します。
f:id:BZL:20200312223144p:plain

試行回数をある程度重ねれば神へ祈りが届けば目標のIDが出ます。
f:id:BZL:20200312223255p:plain

あとがき



調査を重ねた結果、ある程度現実的なレベルでエメラルドのID調整が出来るようになりました。
尚、実際にやってみると分かりますがSID調整まで行うのは割とマゾの所業です。
私人間じゃないよって方は是非チャレンジしてみてください!
任意IDでの固定シンボル色乱数等がやりたい場合、正直言ってルビサファの方で行うのが精神衛生上宜しい気がします。
FRLGも同じような手順でID調整が可能になったはずですがツール側の検索がまだ対応していません。
いつかやると思います。

【Nintendo Switch 自動化】画像認識マクロツール NX Macro Controllerの使い方

大幅更新に伴い、記事の内容の修正中です。
旧verのサポートについては今後行う予定はありません。

結構前に画像認識と入力キー設定をGUIのみで行えるツールを作ったのですが、使い方に関して全く説明していなかったので大雑把に纏めておきます。


1)このツールでできること

  • PCに接続したキーボード/コントローラーを使用したNintendo Switchの操作/記録/実行
  • PCに接続したキャプチャーボードを使用したNintendo Switchの画面キャプチャ
  • 独自構文を用いたマクロの作成/保存/読み込み
  • 入力補助フォームを用いたマクロの作成
  • 作成したマクロの公開
  • LINE Notifyとの連携
  • Poke-Controller用に作られたプログラムの実行 ※一部動作しないものもあり
  • CH552マイコンをコントローラーとして認識させる為のファームウェア書き込み
  • Bluetoothドングルをコントローラーとして認識させる為のドライバインストール

3)必要環境

4)操作方法

ブログでは纏め切れないため、wikiを立ち上げて纏める予定です。

大まかな使い方についてはDiscordサーバーのチュートリアルを確認してください。
開発バージョンの先行公開やバグ報告受付もこちらで行っているので、自動化という遊び方に興味を持っている方は是非入って頂けると幸いです。
discord.gg