こんにちは。

このブログでも説明していますが、CTRPFだとGatewayがなくともコードサーチできます。
そこで皆さん

CTRPF自作プラグインを作りたいとは思いませんか??

前に紹介したSELECT式自作プラグイン。
もちろんあれでもいいです。しかしながら...

SELECT式プラグインなどもう古いです。 
もっと上に行きましょう。

はい、つまりそういうことですね。

ではやっていきましょうか。


まず大前提ですが、PCに下記のツールが入っていることが前提です。

DevKitARM

Python

これらはプラグインを作成するにあたっては必須です。絶対にインストールしておいてください。
当たり前ですがインストールしてないとビルド自体できません。


この記事ではインストールしていることを前提に話を進めます。


まず初めに以下のソースをダウンロードしましょう。

CTRPF Plugin Sources (DarkFlare氏のマリオカート7用CTRPFソース)

腕に自信がある方は以下の空のソースをDLしましょう。

CTRPF Plugin Sources (Nanquitas氏のBlankテンプレート)


ついでに以下のツールも入れとくとコード編集がぐっと楽になります。

Notepad++

※このツールは必ず入れなくても結構ですが、メモ帳なんかより明らかに編集しやすくなるので
プラグイン作成、コーディングにおいては入れておいて絶対に損はありません。



DLできたらPCの適当な場所に解凍しておきます。

解凍したらファイル構造はこんな感じになってると思います
2020-09-01 (1)
まぁ、自分の場合は多少弄ってたりするので構造が一部違う可能性がありますが、
基本はこんな感じになっていると思います。

そしたら Sources フォルダーに移動します。
2020-09-01 (2)
こんな感じになっていると思うので、まずは cheats.cpp を Notepad++ で開きます。
SELECT式でいうと、cheats.cにあたるファイルです。
cheats.cppを選択して右クリックし、Edit with Notepad++ をクリックすれば編集できます。

開くとこんな感じです
2020-09-01 (3)
これを編集していくわけですが、初めて作る方は訳が分からないと思いますので
簡単に作り方を説明していきます。

まず、一番下の方に行って適当に自分でコードを記述していきます。
記述方法としてはこんな感じ。
2020-09-01 (4)

まず

void  {チートの名称}(MenuEntry *entry)

とし、次に{}でスコープを記述。

void  {チートの名称}(MenuEntry *entry)
{

}


↑こんな感じ。
これで一つのチート項目になります。

そしてスコープの中に

void  {チートの名称}(MenuEntry *entry)
{
u32 offset;
Process::Write32(offset + 0xXXXXXXXX, 0xXXXXXXXX);
}

※実際に記述するときはXXXXXXXXにサーチしたコードのアドレスと値を指定する

という感じで記述し、組んでいきます。
SELECT式との最大の違いとして、

void  {チートの名称}(void)

から、

void  {チートの名称}(MenuEntry *entry)

となっていることに注意しましょう。

また、Process::にはWrite32以外にもいくつかの記述方法があります。

8bitアドレス操作 ( 0~255まで格納可能 )
Process::Write8
Process::Read8


16bitアドレス操作 ( 0~65535まで格納可能 )
Process::Write16
Process::Read16


32bitアドレス操作 ( 0~4294967295まで格納可能 )
Process::Write32
Process::Read32


これは一例であり、この他にも記述方法は存在します。

これもSELECT式との記述は大きく違います。

WRITEU32

から

Process::Write32

に変わっています。
8bitや16bit、READも同様です。


条件分岐にはSELECT式と同じく if 文を使用します。

条件分岐を利用する際の例:

特定のボタンを押している間だけコードを有効にしたいとき
ある特定の値が変化したらコードを有効にしたいとき
ポインターコードなどを使用するとき 等

ちなみに、特定のボタンを押している間だけコードを有効にしたいときの記述方法はこうです。

void   {チートの名称}(MenuEntry *entry)
{
if (Controller::IsKeyDown(Start)) {
u32 offset;
Process::Write32(offset + 0xXXXXXXXX0xXXXXXXXX);
}
}


Controller::IsKeyDownで押すボタンを指定します。
例ではスタートボタンを押すとコードが反映されます。

また押すボタンの指定は複数可能です。

Controller::IsKeyDown(A + B + X + Y + Start)

これだとABXYスタートでコードが反映されます。
つまり+で区切ってやれば好きなボタンで指定できます。

これもやはりSELECT式と異なっています。

if (is_pressed(BUTTON_A))

から

if (Controller::IsKeyDown(A))

となっています。


とりあえず最低限の記述方法はこんな感じです。高度な記述方法もあるのですが...
これは需要があれば記事にしたいと思います。
そもそももうそんな需要ないと思うけど実際のところどうなんだ...?


とりあえず、チートの記述方法はこの辺にして、編集できたらcppファイルを保存します。

次に、メニュー項目の編集に移ります。

cheats.cppの下にある、main.cppをNotepad++で開きます。
SELECT式でいうと、create_menu.cにあたるファイルです。
2020-09-01 (5)
開くとこんな感じですが、これまた複雑です。

まず手始めに自分で適当にメニュー項目を追加してみましょう。
まずこれを見てください。
2020-09-01 (6)

PluginMenu *menu = new PluginMenu("{CTRPFプラグインの名前}", n, n, n);

プラグインの名前を編集したい場合ここを弄ります。
{CTRPFプラグインの名前}にはプラグインの名前、nにはバージョン番号を入れます。
※名前には日本語も使えます。


SELECT式との違いとして

char  *builder_name = "{作成者名}";

から

PluginMenu *menu = new PluginMenu("{CTRPFプラグインの名前}", n, n, n);

となっています。
SELECT式では日本語が使えないというところも最大の違いでしょうか。


自分でメニュー項目を追加したい場合、MenuFolder 項目を弄ります。

MenuFolder *mymenu1 = nullptr, *mymenu2 = nullptr

メニュー項目を複数作りたければ、カンマ区切りでこのように指定すれば好きなだけ作れます。

次にコードの説明項目の追加です。
MenuFolderの下を見てください。
std

ずらーっと項目が並んでいますが、これがコードの説明になります。
自分でコードの説明を作る場合の記述方法はこうです。

std::string mycheat_note = "{説明文}";

説明文には日本語も使えるのでこういうところはCTRPFのいいところですね。
なお、説明文を改行したい場合は\nと記述してやるとそこで改行されます。
間違ってもソース内で改行はしないでください。コンパイラがエラーを吐きます。
基本、文字列を改行したい場合は改行したい箇所で\nと記述します。

例:std::string mycheat_note = "説明文:\nこれはチート説明文です";


SELECT式との違いとして

static const char * const mycheat_note = "{説明文}";

から

std::string mycheat_note = "{説明文}";

となっています。
こちらも、SELECT式では日本語が使えないというところが最大の違いでしょうか。


次にメニュー項目の編集です。こちらを見てください。
2020-09-01 (6)
こうなっていますが、これも記述方法があります。
メニュー項目を追加したい場合はこうです。

mymenu1 = new MenuFolder("{メニュー項目名}");
menu->Append(mymenu1);


メニュー項目内にコード項目を追加したい場合はこうです。

mymenu1 = new MenuFolder("{メニュー項目名}");
mymenu1->Append(new MenuEntry("{コード名}", Cheatcode, mycheat_note));
menu->Append(mymenu1);


という感じで記述します。
複数の項目を作る場合も同様です。

mymenu1 = new MenuFolder("{メニュー項目名}");
mymenu1->Append(new MenuEntry("{コード名}", Cheatcode1, mycheat_note1));
mymenu1->Append(new MenuEntry("{コード名}", Cheatcode2, mycheat_note2));
menu->Append(mymenu1);

mymenu2 = new MenuFolder("{メニュー項目名}");
mymenu2->Append(new MenuEntry("{コード名}", Cheatcode, mycheat_note));
menu->Append(mymenu2);


こんな感じで記述してやればOKです。

構造としては

mymenu1: MenuFolderでnullptr設定した関数のポインタ

Cheatcode: cheats.cppで設定したvoidからなるチート名称関数のポインタ
(void   {チートの名称}(MenuEntry *entry) の{チートの名称}に使った文字列)

mycheat_note: std::string mycheat_note = "{説明文}"; の mycheat_note の部分の文字列


こちらも日本語が使えます。CTRPFは便利ですね。


SELECT式との違いとして

new_spoiler("{メニュー項目名}");
new_entry_with_note("{コード名}", Cheatcode, mycheat_note)
exit_spoiler();


から

mymenu1 = new MenuFolder("{メニュー項目名}");
mymenu1->Append(new MenuEntry("{コード名}", Cheatcode, mycheat_note));
menu->Append(mymenu1);


となっています。
こちらもやはり、SELECT式では日本語が使えないというところが最大の違いでしょうか。
あとSELECT式は直でメニュー項目が作成できましたが
CTRPFは MenuFolder にまず記述しないといけないところに注意です。そのまま直でやったらビルドの際にコンパイラがエラー吐くんで。(当たり前だけど)

2020-09-01 (7)

こんな感じですね。

メニュー項目の弄りかたはこんなもんにして、できたらmain.cppを保存します。


よし!これでビルドできるぞ!
そう思ったけど、ちょっと待ってください。
まだ編集するファイルがあります。焦ってはいけません。



build.batがある最初のフォルダーに戻り、Includesフォルダーに移動します。
2020-09-01 (8)
中にあるcheats.hppをNotepad++で開きます。
SELECT式でいうと、cheats.hですね。
2020-09-01 (9)
まぁ、例としてこうなっている訳ですが。
既にSELECT式プラグインを作成したことがある方は大体お分かりでしょう。

void   {チートの名称}(MenuEntry *entry);

と記述するだけです。
cheats.cppで先ほど記述したコードの部分ですね。
これは拍子抜けするぐらい簡単ですね。


SELECT式との最大の違いとして、

void  {チートの名称}(void);

から、

void  {チートの名称}(MenuEntry *entry);

となっていることに注意しましょう。
簡単だと思って記述してるとビルド時にエラー...なんてことはよくあるので
ここの違いだけはしっかりと理解しておくべきです。



記述できたら保存します。
これであらかたの作業は終了です。では、いよいよプラグインをビルドします。

ビルドはbuild.batをダブルクリックするだけです。

では、build.batをダブルクリックしてみましょう。
2020-09-01 (10)
ソースの記述方法に間違いがなければ、Done! Enjoy Your Plugin! と出ます。
2020-09-01 (11)
そうするとbuild.batと同じ場所に MarioKart7.plg が出来ているはずです。

※この時、ソースに1箇所でも間違いが存在すると、コンパイラがエラーを吐きます。
その場合は該当箇所を探して修正します。


無事にビルドできましたか??
あとはお待ちかねの動作テスト。
3dsのpluginフォルダ内にぶち込んでテストするだけです。
(MK7のTIDは0004000000030600)

例によっていつものNTR CFW Selectorを起動してNTRを有効にし、MK7を起動。
起動して上画面の右下に Plugin ready! と出れば大丈夫です。

top_0000
top_0001
top_0002
はい。できていますね。ここまで本当にお疲れ様でした。


まとめ

CTRPFはSELECT式と比べると記述方法が変わってたりしてて面倒ですが
慣れれば作成方法はほぼ同じです。単にcがcppに、hがhppに置き換わっただけです。
(まぁ関数自体が変わってたりするし、そこで戸惑うかもしれませんが)
それにメニュー項目とチートの説明に日本語を使用できる点はかなりデカいんじゃないでしょうか。

それにコードサーチやFreeCheat化などCTRPFの機能も使用できます。
これを考えるとビルドに挑戦してみる価値は十分にあるかと思います。

SELECT式よりもメリットは大きいので、皆さんも是非ともCTRPFプラグインを自作してみましょう。

以上です。


わからないことがあればコメント欄で受け付けます。