ホーム   »  スポンサー広告  »  スポンサーサイト   »  PSPプログラミング  »  第5弾 : ボタン入力の詳細説明

スポンサーサイト

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

第5弾 : ボタン入力の詳細説明

前回の第4弾 : ボタン入力の詳細と補足情報を説明します。

なので、前回作成したKeyLoggerのソースコードを開いておいてください。

チラつくのは仕様ですw
見るに堪えない程ではないと、これ以上複雑化するのは避けるべきだと思ったのでw

まず、新しいインクルードファイルが増えました。

#include <pspctrl.h>

pspctrl.hヘッダーファイルにはPSPのボタン入力に関することが定義されています。
その中に以下の構造体がtypedefで定義されています。

typedef struct SceCtrlData {
unsigned int TimeStamp;
unsigned int Buttons;
unsigned char Lx;
unsigned char Ly;
unsigned char Rsrv[6];
} SceCtrlData;

この構造体をボタン入力を知る関数に渡してあげると、Buttonsメンバに押されているボタンが格納されます。
どのボタンが押されているかは、調べたいボタンの数値とButtonsメンバをビット演算でマスク(AND演算)してやると分かります。
そのほか、TimeStampにはフレーム番号が格納され、Rsrvは予約領域といい、使えないメンバです。
Lx, Ly についてはあとで説明します。

ほかに pspctrl.h ヘッダーファイルに定義されているのは、ボタンとモードです。

enum PspCtrlButtons
{
PSP_CTRL_SELECT = 0x000001,
PSP_CTRL_START = 0x000008,
PSP_CTRL_UP = 0x000010,
PSP_CTRL_RIGHT = 0x000020,
PSP_CTRL_DOWN = 0x000040,
PSP_CTRL_LEFT = 0x000080,
PSP_CTRL_LTRIGGER = 0x000100,
PSP_CTRL_RTRIGGER = 0x000200,
PSP_CTRL_TRIANGLE = 0x001000,
PSP_CTRL_CIRCLE = 0x002000,
PSP_CTRL_CROSS = 0x004000,
PSP_CTRL_SQUARE = 0x008000,
PSP_CTRL_HOME = 0x010000,
PSP_CTRL_HOLD = 0x020000,
PSP_CTRL_NOTE = 0x800000, // ♪
PSP_CTRL_SCREEN = 0x400000, // 画面輝度調整
PSP_CTRL_VOLUP = 0x100000, // 音量調節上
PSP_CTRL_VOLDOWN = 0x200000, // 音量調節下
PSP_CTRL_WLAN_UP = 0x040000, // ワイヤレスLANスイッチON
PSP_CTRL_REMOTE = 0x080000, // ?
PSP_CTRL_DISC = 0x1000000, // おそらくUMDが入っているかどうか
PSP_CTRL_MS = 0x2000000, // おそらくメモリースティックが入っているかどうか
};

ボタンです。色々ありますが、 PSP_CTRL_HOME , PSP_CTRL_NOTE , PSP_CTRL_SCREEN , PSP_CTRL_VOLUP , PSP_CTRL_VOLDOWN , PSP_CTRL_WLAN_UP , PSP_CTRL_REMOTE , PSP_CTRL_DISC , PSP_CTRL_MS についてはカーネルモードで取得できます。なので、前回のソースコードでもこれらの処理は省いてあります。


enum PspCtrlMode
{
/* Digitial. */
PSP_CTRL_MODE_DIGITAL = 0,
/* Analog. */
PSP_CTRL_MODE_ANALOG
};

モードと言うのは、デジタルかアナログかというモードです。
sceCtrlSetSamplingMode 関数で設定します。
アナログモードにすると、アナログスティックが使えます。逆にデジタルモードだと使えません。


次にこんなマクロ定義を追加しました。

#define printf pspDebugScreenPrintf

単純に printf を pspDebugScreenPrintf に置き換えるマクロですね。
使用率が高いのに関数名が長いのでは、疲れてしまいます。 ということで、楽をする為と、ソースコードの可読性を向上させる目的で定義しています。
このような楽をする技術もプログラミングには必要です。


んで、恒例のコールバック周りの処理は飛ばして、次に来るのが自作したShowCtrlData関数です(PrintCtrlData の方が良かったかもしれない orz)。

void ShowCtrlData( SceCtrlData *pad )
{
unsigned int keys[13] = {
PSP_CTRL_SELECT,
PSP_CTRL_START,
PSP_CTRL_UP,
PSP_CTRL_RIGHT,
PSP_CTRL_DOWN,
PSP_CTRL_LEFT,
PSP_CTRL_LTRIGGER,
PSP_CTRL_RTRIGGER,
PSP_CTRL_TRIANGLE,
PSP_CTRL_CIRCLE,
PSP_CTRL_CROSS,
PSP_CTRL_SQUARE,
PSP_CTRL_HOLD
};
char *msg[13] = {
"SELECT",
"START",
"UP",
"RIGHT",
"DOWN",
"LEFT",
"LTRIGGER",
"RTRIGGER",
"TRIANGLE",
"CIRCLE",
"CROSS",
"SQUARE",
"HOLD",
};

printf( "X = %03d Y = %03d\n", pad->Lx, pad->Ly );
if( pad->Buttons != 0 ) {
int n;
for( n = 0; n < 13; n++ ) {
if( pad->Buttons & keys[n] ) {
printf( "Pressed button is %s.\n", msg[n] );
}
}
}
}

この関数は渡されたSceCtrlData構造体の Buttons メンバと Lx , Ly メンバを画面に表示する関数です。
引数のSceCtrlData構造体はポインタなので注意してください。
メンバへのアクセスはアロー演算子(->)を使用します。

keys には入力されたかどうか調べたいボタンを格納しておきます。
今回はユーザーモードで取得可能な分だけ格納してあります。
同様に msg には keys に格納されたボタンと対応するように、画面に表示する文字列を格納しています。

変数の宣言後に SceCtrlData構造体の Lx , Ly メンバの表示をしています。
printf( "X = %03d Y = %03d\n", pad->Lx, pad->Ly );
Lx , Ly にはアナログスティックの位置情報が格納されます。
精度が悪いようなので実用するならば、±5ぐらいの誤差を考慮して下さい。
中央ならば理論的には Lx = 127 , Ly = 127 です。

その後、Buttonsメンバに値が入力されているかチェックし、入っていた場合はどのボタンが押されたかをビットマスク(&演算子)でチェックします。
for文で keys msg の数だけループします。13回ですね。
int n;
for( n = 0; n < 13; n++ ) {
if( pad->Buttons & keys[n] ) {
printf( "Pressed button is %s.\n", msg[n] );
}
}
pad->Buttons & Keys[n] で kyes[n] に格納されたボタンが押されているかチェックしています。
1回目のループの場合
keys[0] = PSP_CTRL_SELECT;
pad->Buttons & keys[0]
となる。
つまり
pad->Buttons & PSP_CTRL_SELECT
となるのです。
結果、SELECTボタンが押されていたのであれば
Pressed button is SELECT.
と表示されます。


ここまでいいですか?
解らなければ、読み返して、駄目なら質問をして下さい。


はい、最後にmain関数を見て下さい。
関数内で新たに SceCtrlData pad; と定義してあります。
上記で説明しましたね。入力されたボタン情報を格納する構造体です。

次に sceCtrlSetSamplingCycle関数です。
ブックマークにいれた PSPSDK APIを見て下さい。
File Listよりpspctrl.hを探しだして、その中にありますね。
この関数はボタン入力の間隔(サイクル)を設定します。
通常は ゼロ を設定します。
戻り値は設定前のサイクル数です。

次に、アナログパッド使用かどうかのモード設定です。
sceCtrlSetSamplingMode関数 です。

そして、whileループに辿り着きます。
sceDisplayWaitVblank関数は、画面の垂直同期を待ちます。
sceDisplayWaitVblankStart関数との違いは、知らないので、各自調べてみて欲しいw

そして、重要なボタン取得関数である
sceCtrlReadBufferPositive関数
です。
PSPSDK APIのpspctrl.hに説明があります。
第一引数 : SceCtrlData構造体の配列
第二引数 : 第一引数の配列の数
今回は、配列を使用しなかったので
sceCtrlReadBufferPositive( &pad, 1 );
と使ってます。
戻り値は不明です。

その後、上記で説明済みのShowCtrlData関数で押されているボタン名を画面に表示しています。

それから、ループ内で pspDebugScreenInit関数を呼んでいるのは、前回ループ時に表示したボタン名が残るからです。
試しにやってみて下さい。実は、これがチラつきの原因だったりします。遅いw

では、次回は入力されているボタンをテキストファイルに記録してみましょう。
スポンサーサイト
Comment
Trackback
Trackback URL
Comment Form
管理者にだけ表示を許可する
Twitter...A

estuibal=Y.K < > Reload

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