- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2023-04-22T19:58:33+09:00","","")
* キー入力とデバッグ [#wec9383b]
#freeze
#author("2023-05-30T10:39:20+09:00","","")
* ボタン入力とデバッグ [#wec9383b]
ボタン入力はアドレス0x4000130をu16単位で参照します。下位のビットから順番に、Aボタン、Bボタン、セレクトボタン、スタートボタン、十字キーの→、←、↑、↓、Rボタン、Lボタンとなっています。ビットが立っている時は押されていない状態、ビットが立っていない時は押されている状態です。どの程度の強さで押されているか、といった判定はできません。
** キー入力 [#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 |
ビットが立っている時は押されていない状態、ビットが立っていない時は押されている状態です。~
どの程度の強さで押されているか、といった判定はできません。~
- GBA Keypad Input
The built-in GBA gamepad has 4 direction keys, and 6 buttons.
4000130h - KEYINPUT - Key Status (R)
Bit Expl.
0 Button A (0=Pressed, 1=Released)
1 Button B (etc.)
2 Select (etc.)
3 Start (etc.)
4 Right (etc.)
5 Left (etc.)
6 Up (etc.)
7 Down (etc.)
8 Button R (etc.)
9 Button L (etc.)
10-15 Not used
It'd be usually recommended to read-out this register only once per frame, and to store the current state in memory.
As a side effect, this method avoids problems caused by switch bounce when a key is newly released or pressed.
** 取得方法 [#kaa95702]
キー入力を取得するには、メインループ中で毎回状態をチェックするか、~
割り込み機能を使って取得します。~
キー入力を取得するにはメインループ中で毎回状態をチェックするか、割り込み機能を使って取得します。今回は簡単な前者の方法を使ってみましょう。以下のenumを用意します。
今回は簡単な前者の方法を使ってみましょう。以下のマクロを用意します。~
#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]
入力の説明が簡単すぎたので別の話をさせてもらいます。~
今まで何気なくビットマップモードから説明をやってきました。~
* 横道な話 [#o24a73f2]
ところでボタン入力の説明が簡単すぎたので別の話をさせてもらいます。今まで何気なくビットマップモードから説明をしてきました。REG_DISPCNTなどのレジスタに設定したり、VRAMに色データを設定したり、そして今回のREG_KEYINPUTは値を読み取ってボタンの状態を確認しています。もう少し概念的にいうと、''決められた設定データをアドレスに配置する、または決められたアドレスの値を調べる、という考え方に集約されます''。設定を忘れたり、データを配置し忘れると当然うまくいきません。注意してください。ここではプログラマーの意図した結果になっているのか?という確認方法をまとめてご紹介します。
GBAは、REG_DISPCNTなどのメモリに設定を行い、~
とあるメモリ領域に決められたデータ(色データなど)を格納する仕組みが大半です。~
もう少し短めにいうと、''決められた設定を行い、決められたデータを配置する''、というのが~
主な流れです。設定を忘れたり、データを配置し忘れると当然うまくいきません。~
ここではプログラマーの意図した結果になっているか?という確認方法を~
まとめてご紹介します。~
*** Tools -> Memory viewer [#dd06572d]
エミュレータのMemory viewerです。Toolsからぶら下がっているものは~
すべて有用なので一度確認しておくことをおすすめします。~
エミュレータのMemory viewerです。Toolsからぶら下がっているものはすべて有用なので一度確認しておくことをおすすめします。
*** gritの出力結果 [#bf328660]
gritのオプションを間違うことはよくあることです。~
自分の意図したサイズかどうか、あと1、2バイト目のデータ構造ぐらいは~
確認した方がいいかもしれません。~
gritのオプションを間違うことはよくあることです。自分の意図したサイズかどうか、あと1、2バイト目のデータ構造ぐらいは確認した方がいいかもしれません。
*** printfデバッグ [#e81dda08]
使い方は以下のとおりです。
私のサンプルコード限定ですけれど、使い方は以下のとおりです。
u32 x = 1234;
TRACEOUT("%d %x\n", x, x);
TRACE("%d %x\n", x, x);
出力結果はエミュレータのTools->Loggingで確認できます。~
この関数は自作したものなので標準ライブラリと関係ありません。~
原理については[[Doc.10 エミュレータのデバッグコンソール>doc.10]]を見てください。~
出力結果はエミュレータのTools->Loggingで確認できます。この関数は自作したものなので標準ライブラリと関係ありません。原理については[[Doc.10 エミュレータのデバッグコンソール>doc.10]]に詳しく書かれています。ところで、話題に出てきた標準ライブラリは使えないのかという疑問も出てくると思います。
ところで、そろそろ標準ライブラリは使えないのかと疑問に思う方も出てくると思います。~
#include <stdio.h>
というように山括弧を使えばできますが、入出力関係の関数は全滅です。~
fopen、fgetcは、ファイルシステムがないので使えず。~
scanfは、キーボード入力が物理的にないので使えず。~
printfは、そもそも日本語フォントが内蔵されておらず、表示手段もないので使えず。。~
というように山括弧を使えば使用できますが、入出力関係の関数は全滅です。なぜならfopen、fgetcはファイルシステムがないので使えず、scanfはキーボード入力が物理的にないので使えず、printfはそもそも日本語フォントが内蔵されておらず、表示手段もないので使えず。。OSがないってなんて不便なんや、と文句いいたくなりますね。有用なのは数学関係の関数でしょうか。
OSないってなんて不便なんや、と文句いいたくなりますね。~
有用なのは数学関係の関数でしょうか。~
#include <math.h>
ただ標準ライブラリは全部カードリッジ領域''固定''なのでスピードが出ません。~
あとROMのサイズも増大するのであんまりおすすめしません。~
ただ標準ライブラリは全部カードリッジ領域''固定''なのでスピードが出ません。あとROMのサイズも増大するのであまりおすすめしません。
** キー入力の例 [#rc24903c]
今回のまとめです。
* ボタン入力 [#rc24903c]
ボタン入力のサンプルコードです。
#include "lib/gba.h"
//---------------------------------------------------------------------------
void WaitForVsync(void)
{
while(*(vu16*)0x4000006 >= 160) {};
while(*(vu16*)0x4000006 < 160) {};
}
//---------------------------------------------------------------------------
int main(void)
{
// モード設定なし
SetMode(MODE_3 | BG2_ENABLE);
u32 x = 1234;
u32 x = 0;
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++;
if( !(REG_KEYINPUT & KEY_UP) ) TRACE("上 ボタン\n");
if( !(REG_KEYINPUT & KEY_DOWN) ) TRACE("下 ボタン\n");
if( !(REG_KEYINPUT & KEY_RIGHT)) TRACE("右 ボタン\n");
if( !(REG_KEYINPUT & KEY_LEFT) ) TRACE("左 ボタン\n");
if( !(REG_KEYINPUT & KEY_A) ) TRACE("10進=%d 16進=0x%x 16進4桁=0x%04x \n", x, x, x);
if( !(REG_KEYINPUT & KEY_B) ) TRACE("変数x++ \n", x++);
}
}
ちなみにボタン入力はパソコンの物理キーボードの性能に依存しています。たとえば上下右左の4つのボタンを同時にした結果、正しいデバック表示になるかというとかなり怪しいです。個人的には安いキーボードほど同時ボタン処理が適当なイメージを持っています。実機の場合とでは動作が違うということを覚えておいてください。
*** デバッグ画面 [#z779c7ea]
#ref(clip_1.png,nolink)
動作画面は省略しました。~
#ref(1.png,nolink)
** 履歴 [#n0e506bc]
- 2023/04/24
- 2014/12/23