ホーム   »  スポンサー広告  »  スポンサーサイト   »  PSPプログラミング  »  第2弾 : Hello world! の詳細説明

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

第2弾 : Hello world! の詳細説明

前回の第1弾で作ってもらったHello world!のソースコードの詳細説明をします。
では、前回のソースコード main.c を開いて見て下さい。

7/6 説明に間違いがありました。
猫山猫宗氏ご指摘ありがとうございます。
修正個所は、pspDebugScreenSetXY関数の必要性についてです。
えー、まず、PSPSDKの説明が書いてあるHTML形式のファイルがあります。
たぶん スタートメニュー > すべてのプログラム > PSP DevKit に PSPSDK APIとあります。
それをブラウザで開いて下さい。
またはオンラインの
http://psp.jim.sh/pspsdk-doc/
を見て下さい。
PSPSDKに含まれるAPIの説明があります。
これをブックマークにでもいれておいて、何時でも見れるように。
英語ですが、頑張って読みましょう(笑)

では、ソースコードの説明ですね。

#include <pspkernel.h>
#include <pspdebug.h>


pspkernel.h は色々なデータ型の定義やマクロやらが定義されてます。
pspdebug.h はCUI環境を使用するためのものと思ってください。


PSP_MODULE_INFO( "HelloWorld", 0, 0, 1 );
PSP_MAIN_THREAD_ATTR( THREAD_ATTR_USER | THREAD_ATTR_VFPU );


この二行でプログラムの情報や実行モードを設定します。
PSP_MODULE_INFO( モジュール名, モード, メジャーバージョン, マイナーバージョン )
モジュール名は大体プログラム名を付けます。あまり気にしなくてOK。
モードについて 0がユーザーモード 0x1000 がカーネルモードです。ユーザーモードで行きましょう。
メジャー・マイナーバージョンは、バージョン管理に使用できます。気にせず進みましょう。

PSP_MAIN_THREAD_ATTR( メインスレッドの属性 );
これはmain関数の実行スレッドの属性を設定します。
THREAD_ATTR_USER : ユーザーモードスレッド
THREAD_ATTR_VFPU : VFPUからのアクセス許可(VFPU:浮動小数点演算装置)
ほか、色々定義されてるのでPSPSDK APIを見てください。


int end_flag = 0;

int exit_callback( int arg1, int arg2, void *common )
{
end_flag = 1;
return 0;
}

int CallbackThread( SceSize args, void *argp )
{
int cbid = sceKernelCreateCallback( "Exit Callback", exit_callback, NULL );
sceKernelRegisterExitCallback( cbid );
sceKernelSleepThreadCB();
return 0;
}

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

グローバル変数で int end_flag が宣言されてます。0で初期化されていることに注意。

次に exit_callback関数はコールバック関数です。
コールバック関数はWinAPIをやったことがある人なら解っていると思いますが、システムが必要に応じて呼び出す関数です。
処理はend_flagに1を格納し、リターンしています。覚えておいてください。

CallbackThread関数は スレッドです。
このスレッドとは、分割処理をする単位みたいなものです。
main関数を実行するのに1スレッド消費します。そして、このCallbakThread関数を実行するにも 1スレッド消費します。
スレッドは独立して動作します。
使用例は、ボタンを監視しながら他の演算をする場合、画面を書き換えながらボタンを監視する場合。
詳細はググってください。

それで、この関数の処理内容は
sceKernelCreateCallback関数でコールバックIDを取得し、そのIDをsceKernelRegisterExitCallback関数で登録、sceKernelSleepThreadCB関数でスレッドをスリープさせます。その後リターン。
ここでexit_callback関数がコールバック関数として登録され動作するようになります。
ExitCallbakはゲーム中にHOMEボタンを押すと表示されるゲーム終了画面で終了するを選ぶと呼ばれます。

新たに、sceKernelCreateCallback関数、sceKernelRegisterExitCallback関数、sceKernelSleepThreadCB関数が出てきましたが、これらがPSPSDKのAPIです。
さっそくPSPSDK APIで見てみましょう。
Modules > Thread Manager Library に sceKernelCreateCallback関数があります。

int sceKernelCreateCallback ( const char *name,
SceKernelCallbackFunction func,
void *arg
)
Create callback.

Example:
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_cb, NULL);

Parameters:
name - A textual name for the callback
func - A pointer to a function that will be called as the callback
arg - Argument for the callback ?

Returns:
>= 0 A callback id which can be used in subsequent functions, < 0 an error.

上記のように説明があります。
ExampleにAPIの使用例があり、ParametersにはこのAPIの引数の説明が、Returnsには戻り値があります。
nameはコールバックの名前のことのようです。
funcはコールバックされるコールバック関数へのポインタです。データ型は関数ポインタですね。
argはコールバック関数へ渡される引数?今は使わないのでNULLです。
戻り値は0よりも小さいとエラーで、0以上ならば正常であり、コールバックIDが返却されると書いてますね。

ほか、sceKernelRegisterExitCallback関数(Modules > LoadExec Library)と sceKernelSleepThreadCB関数(Modules > Thread Manager Library)もみて下さい。
このように解らない関数が出てきたらこまめに調べて何をするのか見て下さい。
大体載っている筈です。また、各関数がどのライブラリにあるのかも、徐々にでいいので覚えるべきです。

最後は、setupCallbacks関数です。
sceKernelCreateThread関数でスレッドIDを作り、sceKernelStartThread関数でスタートさせます。
この処理でCallbackThread関数を動かします。動くということは、コールバック関数が登録されるということです。

ここで一度関数の処理を追ってみて下さい。
setupCallbacks関数 → CallbackThread関数 → exit_callbak関数
というように呼ばれます。(厳密にはそうでないが、そうイメージして下さい。)


これでHOMEボタン監視のための処理説明が終わりました。
次はmain関数です。

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

while( end_flag != 1 )
{
pspDebugScreenSetXY( 0, 0 );
pspDebugScreenPrintf( "Hello world!\n" );
}

sceKernelExitGame();
return 0;
}


まず、setupCallbacks関数が呼ばれます。
次にpspDebugScreenInit関数です。
はい、PSPADK APIの出番です。
この関数の動作は画面の初期化です。文字を表示するために必要な初期化処理と覚えましょう。

次に whileループです。
ここで、グローバル変数のend_flagが出てきます。この変数の値が1の時、つまり、コールバック関数が動作したときです。
その場合、ループを終了します。

pspDebugScreenSetXY関数は文字の印字位置を座標で設定します。
pspDebugScreenPrintf関数は書式付文字列を表示します。

なぜ、ループ内でpspDebugScreenSetXY関数を呼びx=0, y=0に設定するかというと。
pspDebugScreenPrintf関数が呼ばれるたびにy座標が一文字分増えるからです。
pspDebugScreenPrintf関数は "Hello world!\n" のように最後に改行文字が入ると自動的にy座標を一文字文増やす(ずらす)ので、ループ毎に印字位置を x=0, y=0 で初期化しているのです。

そして、ループ終了後は sceKernelExitGame関数が呼ばれ、ゲームが終了します。
sceKernelExitGame関数は大事です。これが呼ばれずにmain関数がリターンしてもゲームが終了されないからです。
最後にreturn 0;で終了です。

はい、お終い!
さて、みなさんには課題を差し上げましょうw
課題は、変数の表示と、main関数の引数には何があるか表示させることです!
これは意外と大事です。が、簡単に出来る筈です。
次回は、このソースコードを弄って更なる理解を!
スポンサーサイト
Comment
>pspDebugScreenPrintf関数が呼ばれるたびにy座標が一文字分増えるからです。

正確に書くと、
pspDebugScreenPrintf( "Hello world!\n" );
と記述しているので、文字列描画の末尾にカーソル位置が移動し、'\n' で一行改行しているので一行下の行先頭へカーソル位置が移動する。

と・・・
Trackback
Trackback URL
Comment Form
管理者にだけ表示を許可する
Twitter...A

estuibal=Y.K < > Reload

検索フォーム
RSSリンクの表示
リンク
QRコード
QR
ブロとも申請フォーム
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。