#author("2023-04-22T19:58:33+09:00","","")
* キー入力とデバッグ [#wec9383b]

** キー入力 [#j20dcb9f]
ボタンの入力はI/Oレジスタの''0x4000130、0x4000131''の値で判定します。~

下位のビットから順番に、Aボタン、Bボタン、セレクトボタン、スタートボタン、~
十字キーの→、←、↑、↓、最後はRボタン、Lボタンとなっています。~

| ビット | 15 | 14 | 13 | 12 | 11 | 10 |  9 |  8 |  7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
| ボタン |    |    |    |    |    |    |  L |  R | ↓ | ↑ | ← | → | ST | SL |  B |  A |

ビットが立っている時は押されていない状態、ビットが立っていない時は押されている状態です。~
どの程度の強さで押されているか、といった判定はできません。~

** 取得方法 [#kaa95702]
キー入力を取得するには、メインループ中で毎回状態をチェックするか、~
割り込み機能を使って取得します。~

今回は簡単な前者の方法を使ってみましょう。以下のマクロを用意します。~

 #define REG_KEYINPUT	*(vu16*)(REG_BASE + 0x130)  // Key Input
 
 typedef enum KEYPAD_BITS {
 	KEY_A		=	(1<<0),	/*!< keypad A button */
 	KEY_B		=	(1<<1),	/*!< keypad B button */
 	KEY_SELECT	=	(1<<2),	/*!< keypad SELECT button */
 	KEY_START	=	(1<<3),	/*!< keypad START button */
 	KEY_RIGHT	=	(1<<4),	/*!< dpad RIGHT */
 	KEY_LEFT	=	(1<<5),	/*!< dpad LEFT */
 	KEY_UP		=	(1<<6),	/*!< dpad UP */
 	KEY_DOWN	=	(1<<7),	/*!< dpad DOWN */
 	KEY_R		=	(1<<8),	/*!< Right shoulder button */
 	KEY_L		=	(1<<9),	/*!< Left shoulder button */
 
 	KEYIRQ_ENABLE	=	(1<<14),	/*!< Enable keypad interrupt */
 	KEYIRQ_OR	=	(0<<15),	/*!< interrupt logical OR mode */
 	KEYIRQ_AND	=	(1<<15),	/*!< interrupt logical AND mode */
 	DPAD 		=	(KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT) /*!< mask all dpad buttons */
 } KEYPAD_BITS;

** デバッグ小話 [#o24a73f2]
入力の説明が簡単すぎたので別の話をさせてもらいます。~
今まで何気なくビットマップモードから説明をやってきました。~

GBAは、REG_DISPCNTなどのメモリに設定を行い、~
とあるメモリ領域に決められたデータ(色データなど)を格納する仕組みが大半です。~

もう少し短めにいうと、''決められた設定を行い、決められたデータを配置する''、というのが~
主な流れです。設定を忘れたり、データを配置し忘れると当然うまくいきません。~

ここではプログラマーの意図した結果になっているか?という確認方法を~
まとめてご紹介します。~

*** Tools -> Memory viewer [#dd06572d]
エミュレータのMemory viewerです。Toolsからぶら下がっているものは~
すべて有用なので一度確認しておくことをおすすめします。~

***  gritの出力結果 [#bf328660]
gritのオプションを間違うことはよくあることです。~
自分の意図したサイズかどうか、あと1、2バイト目のデータ構造ぐらいは~
確認した方がいいかもしれません。~

***  printfデバッグ [#e81dda08]
使い方は以下のとおりです。

 u32 x = 1234;
 
 TRACEOUT("%d %x\n", x, x);

出力結果はエミュレータのTools->Loggingで確認できます。~
この関数は自作したものなので標準ライブラリと関係ありません。~
原理については[[Doc.10 エミュレータのデバッグコンソール>doc.10]]を見てください。~

ところで、そろそろ標準ライブラリは使えないのかと疑問に思う方も出てくると思います。~

 #include <stdio.h>

というように山括弧を使えばできますが、入出力関係の関数は全滅です。~
fopen、fgetcは、ファイルシステムがないので使えず。~
scanfは、キーボード入力が物理的にないので使えず。~
printfは、そもそも日本語フォントが内蔵されておらず、表示手段もないので使えず。。~

OSないってなんて不便なんや、と文句いいたくなりますね。~
有用なのは数学関係の関数でしょうか。~

 #include <math.h>

ただ標準ライブラリは全部カードリッジ領域''固定''なのでスピードが出ません。~
あとROMのサイズも増大するのであんまりおすすめしません。~

** キー入力の例 [#rc24903c]
今回のまとめです。

 #include "lib/gba.h"
 
 //---------------------------------------------------------------------------
 void WaitForVsync(void)
 {
 	while(*(vu16*)0x4000006 >= 160) {};
 	while(*(vu16*)0x4000006 <  160) {};
 }
 //---------------------------------------------------------------------------
 int main(void)
 {
 	// モード設定なし
 
 	u32 x = 1234;
 
 	for(;;)
 	{
 		WaitForVsync();
 
 		if( !(REG_KEYINPUT & KEY_UP)  ) TRACEOUT("上 ボタン\n");
 		if( !(REG_KEYINPUT & KEY_DOWN)) TRACEOUT("下 ボタン\n");
 		if( !(REG_KEYINPUT & KEY_A)   ) TRACEOUT("10進=%d 16進4桁=0x%04x \n", x, x, x);
 		if( !(REG_KEYINPUT & KEY_B)   ) x++;
 	}
 }

*** デバッグ画面 [#z779c7ea]
#ref(clip_1.png,nolink)
動作画面は省略しました。~


** 履歴 [#n0e506bc]
- 2014/12/23


トップ   一覧 検索 最終更新   ヘルプ   最終更新のRSS