3DS研究所

homebrew・CFW全般

Luma3DS 日本語版

はじめに

つい最近始めたプロジェクトなんですが、現在Luma3DSの日本語版の開発をしています。見た目はこんな感じ。

Luma3DS 日本語版メニュー
少し前にCynricXu氏によって中国語版Luma3DSが公開されており、そのプロジェクトに基づいています。

インストール方法

既にCFWをインストールしている前提で話を進めます。

  1. Luma3DS_JP_v11.0.zipをダウンロード。
  2. 解凍後、中にあるboot.firmlumaフォルダを3DSで使用するSDカードのルートに配置する。

補足

修正・提案などあればお気軽に。 github.com

CTRPFのソースが流出?

 皆さんお久しぶりです。3DS界隈で一騒動あったようなのでお知らせします。

CTRPFソース流出か

 こちらは海外フォーラムにて起こった出来事ですが、どうやらCTRPFのライブラリ(0.5.1)が流出したと一騒動になっているようです。公開を行ったのはZetta-D氏。Zetta-D氏いわく、これはリークされたコードであり、Nanquitas氏に対する仕返しとして行っているとのこと。具体的なことは書かれていないため、彼らの間に何があったのかはわかりません。

実際は逆コンパイルの可能性

 しかし、実際には流出ではなく単なる逆コンパイルである可能性が高いようです。これについては、PabloMK7氏が以下のようにコメントしています。

I looked at the code, this is not a leak at all, but a decompilation (which has many many mistakes by the way).

 「コードを見たが、結局これはリークではなく、逆コンパイルだ(かなり多くの間違いがあるけれども)。」とのこと。実際にソースコード内にも逆コンパイルを行った形跡が残されています。当の本人は本物であると主張していますが...(笑)

まとめ

 結論を言うと、実際にはリークでない可能性が高いです。ただ、確定したわけではないため、ここにソースコードへのリンクを貼るのは控えておきます(著作権侵害に該当する可能性があるため)。
 これが本物であろうが偽物であろうが、迷惑行為であることには変わりありません。このような迷惑行為がなくなるといいですね。

当ブログ休止のお知らせ

毎度当ブログをご覧いただきありがとうございます。誠に勝手ながら、この度管理人の都合により、当ブログの更新を休止させていただくことになりました。既に公開されている記事に関しては公開を継続させていただきますが、更新に関しては今のところ行う予定はありません。質問に関しても原則返信いたしません。ご理解のほどよろしくお願いいたします。

フラッシュ表示の仕組み

フラッシュ表示は、CFWを導入している方なら馴染みがあるのではないでしょうか?BannerBomb3を実行したときに一瞬紫色になる下画面、3gx形式のプラグインを起動したときに一瞬水色になる上画面、これらはすべてフラッシュ表示によるものです。目に見えるところだけではありません。画面の初期化の際にも、内部処理では黒色のフラッシュ表示が行われています。これらのフラッシュ表示はどのような仕組みで行われているのでしょうか?

LCDレジスタ

フラッシュ表示はLCDレジスタという場所で処理されます。構成は以下の通りです。

項目

アドレス サイズ 項目
0x10202204 0x4 上画面フラッシュ
0x10202A04 0x4 下画面フラッシュ

オプション

ビット 説明
0~7 赤強度
8~15 緑強度
16~23 青強度
24 フラグ(0=無効、1=有効)

実装

以下のコードでフラッシュ表示を実装できます。

//上画面フラッシュ(白色)
*(u32 *)0x90202204 = 0x1FFFFFF;

//下画面フラッシュ(白色)
*(u32 *)0x90202A04 = 0x1FFFFFF;

物理アドレスのベースは0x80000000なので、前述した値に0x80000000を加算した値を書き込むアドレスとして指定します。
また、代入値は0x1(カラーコード)となるようにします。カラーコードはBGRの順で指定してください。これで指定色をフラッシュ表示できます。
※CTRPFの関数やGatewayコードでは仮想アドレスを参照するため、直接書き込みはできないので注意してください。

最後に

いかがでしたか?LCDレジスタでは他にもバックライトの輝度設定などが行えるので、よければ試してみてください。

参考文献:https://www.3dbrew.org/wiki/LCD_Registers

GDBデバッグ講座(Part2)

今回はリモートでレジスタの値を書き換え、3DSの挙動を変更してみましょう。
※Part1を終えた前提で話を進めます。まだPart1を見ていない方は、先にPart1を確認してください。
https://cfw-question.hatenablog.com/entry/2020/06/05/211346

準備

前回使用したGDBTestのmain.cを以下のように書き換えてください。

#include <3ds.h>

int main(int argc, char* argv[])
{
    gfxInitDefault();

    srvPublishToSubscriber(0x204, 0);

    // Main loop
    while (aptMainLoop())
    {
        gspWaitForVBlank();
        gfxSwapBuffers();
        hidScanInput();

        u32 kDown = hidKeysDown();
        if (kDown & KEY_START)
            break;
    }

    gfxExit();
    return 0;
}

今回注目する関数はsrvPublishToSubscriberです。これは3DSの制御にかかわるサービス通知を送信する関数です。引数にある0x204が通知IDで、これは「HOMEボタンの押下」にあたります。つまりこのプログラムは、「画面の初期化後にHOMEボタンを押したことになる」プログラムです。言葉で説明されてもいまいちよくわからないと思うので、実際にビルドしたciaをインストールして実行してみてください。起動後になぜかHOMEボタンを押したことになっていると思います。今回はGDBで通知IDを0x202(電源ボタンの押下)に書き換え、電源ボタンを押した判定にしてみましょう。

デバッグ

ブレークポイント

まずはPart1と同様にGDB3DSに接続してください。今回はブレークポイントを、main関数ではなくsrvPublishToSubscriberに直接行指定してみましょう。上記のコードでは7行目にあるので、b 7と指定します。指定できたらcontinueでブレークポイントまでを実行します。

アセンブル

アセンブルを行うことで、処理をより細かく見ることが可能です。disasというコマンドを実行してみてください。ズラーッと出てきたその中身が逆アセンブルの結果です。矢印で示されている場所が現在の処理位置です。
おそらく矢印は、srvPublishToSubscriberではなくmov r1, #0を示していると思います。これは引数を先にレジスタに代入しておかないと、srvPublishToSubscriberに分岐した際に引数を参照できないためです。今回は直接レジスタの値を書き換えて通知IDを変更してみましょう。

niコマンド

通知IDが既にレジスタに代入されているという状況を作るため、まずはsrvPublishToSubscriberに分岐するアドレスまでの処理を実行してみましょう。ブレークポイントをかけてもいいのですが、今回はniコマンドを使用します。これは機械語の命令単位で処理を実行できるコマンドです。では、このniコマンドを2回実行し、再度disasコマンドを実行してみてください。今度はsrvPublishToSubscriberと書かれた行を矢印が示していることと思います。

レジスタ書き換え

通知IDはr0に格納されています。set $r0=0x202と実行し、r0の値を書き換えます。

実行

これで準備は整いました。cを実行して挙動を確認してみてください。電源ボタンを押したときの挙動になっていることと思います。

最後に

今回はGDBでのレジスタ書き換えについて解説しました。今回使用した関数はほかの通知IDも使用できます。一覧は以下のURLを確認してください。
https://www.3dbrew.org/wiki/Services#Notifications

GDBデバッグ講座(Part1)

今回はサンプルソースを用いた、gdbによるhomebrewの実機デバッグ方法を紹介します。事前にdevkitProGitをインストールしておいてください。

準備

  1. git clone https://github.com/HIDE810/GDBTest.gitコマンドプロンプトに入力し、GDBTestをクローンします。
  2. build.batを実行し、ciaファイルをビルドします。
  3. ビルドしたciaファイルを、FBIなどでインストールします。

試しに一度インストールしたGDB Testerを起動してみてください。上画面に0が表示されていますか?今回はこの数値をリモートで書き換えることを目標に話を進めます。

接続手順

3DS側の操作

  1. ホーム画面を開いている状態でRosalina menuを開く。
  2. Debugger options... ⇒ Enable debuggerを選択。
  3. Starting debugger... OKと出るので、Bを押して戻る。(うまくいかない場合はネットワークの接続を確認)
  4. 同じDebugger options menu内の、Force-debug next application at launchを選択。Operation succeeded.とでたら成功。
  5. 先ほどインストールしたGDB Testerを起動。(ロゴ画面で停止すれば正常)

PC側の操作

  1. elfファイルをgdb.batドラッグアンドドロップする。
  2. target remote ip:4003と入力し、3DSに接続する。(ipの部分はRosalina menuの右上に表示されているipアドレスに置き換える)

この段階でin _start ()と表示されていれば、正常に接続できています。

GDBによる操作

ここからが本題です。そもそも、なぜGDB Testerを起動したときに、上画面に0が表示されたかお分かりでしょうか?まずはソースコードから確認していきましょう。
main.cをテキストエディタなどで開いてみてください。注目するのは6行目と13行目です。

//6行目
volatile int x = 0;

//13行目
printf("%d\n", x);

まず、6行目で変数xを宣言・初期化します。このとき、コンパイラの最適化が原因でgdbがエラーを吐くのを防ぐため、volatileを指定しておきます。
次に、13行目で6行目で宣言した内容を表示します。6行目では0で初期化されているため、このプログラムでは0と表示されます。

ブレークポイントの設定

ブレークポイントとは、プログラムを意図的に一時停止する箇所のことです。今回はmain関数をブレークポイントに指定します。これは、main関数に入るまでプログラムを実行するということです。main関数をブレークポイントに指定するには以下のコマンドを実行します。

b main

実行できたら、cと入力してみてください(continueの意味)。これによりプログラムが再開され、main関数に入るまで実行されます。3DS側はロゴ表示が消えて黒い画面になるはずです。

変数の書き換え

gdbではリアルタイムで変数の書き換えが可能です。今回は変数xを書き換えて、0以外の数字を表示してみましょう。例えば、xの値を10000にするには以下のコマンドを実行します。

p x=10000

書き換えが終われば、再度cと入力してみてください。3DSの上画面に書き換えた値が表示されていることと思います。確認できたら、スタートを押して終了します。PC側では、quitと入力してgdbを終了してください。

最後に

今回説明したのは初歩的な部分です。もっとgdbコマンドを知りたいという方は以下を参考にしてみてください。
http://www.fos.kuis.kyoto-u.ac.jp/le2soft/siryo-html/node49.html

各種bruteforceサイトがダウン中(お知らせ)

お気づきの方も多いと思いますが、現在各種bruteforceサイトがダウンしており、CFW導入時の一部サービスが利用できない状態になっています。今回の件について、対処法をざっくりまとめます。

対処法

代替サイトはいくつかありますが、失敗したとの報告が多い印象です。movable.sedの取得などは、公式のDiscord serverであるNintendo Homebrew内のマイニングサービスを利用するようにしましょう。
ちなみにPCさえあればmovable.sedを自分でマイニングすることが可能ですが、bruteforce(総当たり)手法を用いるため、かなりの高スペックでない限りマイニングは厳しいです(時間がかかるため)。ですので、特別な理由がない限りマイニングサービスを利用することをおすすめします。

代替のCFWの導入方法に関しては、そうむさんが日本語記事を公開してくださっていたので、こちらを参考にするようにしましょう。 https://soumu-diary.com/2020/06/post-215/

追記(2020/6/7): 各種サイトが復活したようです。以降は公式のガイドを利用するようにしてください。
https://3ds.hacks.guide/

関連記事:movable.sedって何だ?