ボタンの入力は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 |
ビットが立っている時は押されていない状態、ビットが立っていない時は押されている状態です。
どの程度の強さで押されているか、といった判定はできません。
キー入力を取得するには、メインループ中で毎回状態をチェックするか、
割り込み機能を使って取得します。
今回は簡単な前者の方法を使ってみましょう。以下のマクロを用意します。
#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;
入力の説明が簡単すぎたので別の話をさせてもらいます。
今まで何気なくビットマップモードから説明をやってきました。
GBAは、REG_DISPCNTなどのメモリに設定を行い、
とあるメモリ領域に決められたデータ(色データなど)を格納する仕組みが大半です。
もう少し短めにいうと、決められた設定を行い、決められたデータを配置する、というのが
主な流れです。設定を忘れたり、データを配置し忘れると当然うまくいきません。
ここではプログラマーの意図した結果になっているか?という確認方法を
まとめてご紹介します。
エミュレータのMemory viewerです。Toolsからぶら下がっているものは
すべて有用なので一度確認しておくことをおすすめします。
gritのオプションを間違うことはよくあることです。
自分の意図したサイズかどうか、あと1、2バイト目のデータ構造ぐらいは
確認した方がいいかもしれません。
使い方は以下のとおりです。
u32 x = 1234;
TRACEOUT("%d %x\n", x, x);
出力結果はエミュレータのTools->Loggingで確認できます。
この関数は自作したものなので標準ライブラリと関係ありません。
原理についてはDoc.10 エミュレータのデバッグコンソールを見てください。
ところで、そろそろ標準ライブラリは使えないのかと疑問に思う方も出てくると思います。
#include <stdio.h>
というように山括弧を使えばできますが、入出力関係の関数は全滅です。
fopen、fgetcは、ファイルシステムがないので使えず。
scanfは、キーボード入力が物理的にないので使えず。
printfは、そもそも日本語フォントが内蔵されておらず、表示手段もないので使えず。。
OSないってなんて不便なんや、と文句いいたくなりますね。
有用なのは数学関係の関数でしょうか。
#include <math.h>
ただ標準ライブラリは全部カードリッジ領域固定なのでスピードが出ません。
あとROMのサイズも増大するのであんまりおすすめしません。
今回のまとめです。
#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++;
}
}
#ref(): File not found: "clip_1.png" at page "tutorial.6"
動作画面は省略しました。