2009年08月24日


広告


NP2 for PSPのmain()関数を解析する

今回はNP2 for PSPのプログラム解析を行います。

まずはmain()関数から見てみましょう。
main()関数は、psp/np2.cにあります。

エミュレータソフトウェアはほとんど以下のような構成になっています。

1. 初期化(ハードウェア、ソフトウェア初期化、設定ファイルの読み込み等)
2. メインループ開始
3. キー入力
4. 処理をちょっとだけ実行(CPU命令実行、サウンド再生等)
5. メインループ終了、2.に戻る
6. 終了処理(ハードウェア、ソフトウェア後始末、設定ファイル保存等)


NP2 for PSPも基本は変わりありません。
main()の最初に〜init()とか〜initaialize()とう関数を多数呼び出して初期化を行っています。

以下がメインループですね。

while(taskmng_isavail()) {
(中略)
}


以下の関数でキー入力などを行っています。

taskmng_rol()


以下の関数がエミュレータコアの実行部です。

pccore_exec()


そして、メインループを抜けると、終了処理が走ります。

次にPSP固有の処理について見てみます。

まず特徴的なのは以下の関数です。

int SetupCallbacks(void)
{
int thid;

thid = sceKernelCreateThread("update_thread", CallbackThread,
0x11, 0xFA0, 0, 0);
if (thid >= 0) {
sceKernelStartThread(thid, 0, 0);
}

return thid;
}

スレッドを作成して、実行しています。

スレッドとは、main()から始まる処理から分岐し、平行に動作する、main()の流れとは別の流れのことを言います。スレッドにより処理が平行に動作するように見えますが、実際に処理を行うCPUは一つですので、処理を細かく分けて、main()の流れをちょっと実行しては、別のスレッドの流れをちょっと実行して、ということを繰り返し行っています。

main()の流れ ----+--------------------->
|
別のスレッド +--------------------->

SetupCallbacks()でスレッドを作成し、成功すればそのスレッドを実行します。
実際に起動されるスレッドは、sceKernelCreateThread()の第2引数で指定される関数、つまり以下のCallbackThread()です。

int CallbackThread(void *arg)
{
int cbid;

cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid); //SetExitCallback(cbid);
cbid = sceKernelCreateCallback("Power Callback", power_callback, NULL);
scePowerRegisterCallback(0, cbid);

sceKernelSleepThreadCB(); //KernelPollCallbacks();

return 0;
}

上記CallbackThread()で、二つのcallback関数を登録しています。callback関数登録後、sceKernelSleepThreadCB()を呼び出してこのスレッドはイベント待ちのスリープに入ります。callback関数とは、あらかじめ登録しておき、何かイベントが発生したら、呼び出してもらう関数のことを言います。
CallbackThread()において、sceKernelRegisterExitCallback()でexit_callback()を登録し、scePowerRegisterCallback()でpower_callback()を登録しています。
それぞれ、PSPのホームボタンが押され、終了を選択した場合、電源オフを実行した場合に呼び出されます。
exit_callback()の先では、単に終了処理を実行しますが、パワーオフの場合は、単に終了処理をする場合と、スリープ対応の処理があります。スリープの場合は、一度電源オフのcallbackが実行されてしまったため、再度callback関数を登録して終了し。そのままスリープから再度電源オンを実行されるのを待つようです。

もう一つ、sceKernelWaitSema(), sceKernelSignalSema()を見ておきましょう。
使われているのは、

メインループの直前にsceKernelWaitSema()
メインループの直後にsceKernelSignalSema()
exit_proc()関数の最初、taskmng_exit()の直後にsceKernelWaitSema()
です。

exit_proc()の最初に実行されるtaskmng_exit()でtask_avail = FALSE;を実行しているが、実はこれがメインループを抜ける条件となります。
つまりホームボタン等でゲームを終了する場合に、メインループを完全に抜けてから終了処理を走らせたいため、メインループが抜けてsceKernelSignalSema()が実行されるまでは、exit_proc()は、sceKernelWaitSema()で待たされます。




タグ:NP2 for PSP PSP NP2
【PSPの最新記事】
posted by ひっそりぃ at 2009/08/24 16:07 | Comment(0) | TrackBack(0) | PSP | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:


この記事へのトラックバック
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。