Buttons

You'd have a hard time making a game if you couldn't interact with any of the buttons. The Game Boy Advance has 10 buttons that you can use: Up, Down, Left, Right, A, B, L, R, Select, and Start.

In this section we'll learn the necessary code that you need to put into your project for the kind of button presses you'll need. There are two basic types of button presses: continuous and discrete. You want to use continous button press when you're moving a character, for example. This usually corresponds to the directional pad. Discrete button presses are when you only want a single thing to happen with each button press, like selecting something in the menu or using the A or B buttons to advance the text or what have you. The continous button press is the simplest as we'll see. But we'll go over what you need to know for both of them.


Register


Continous Button Presses

Like mentioned above, a continous button press is when you press and hold a button and expect something to continously happen. Like moving your character. You want to just press the directional pad and hold the button down as your character moves across the screen.

Remember that when you press a button that action is being recorded in the Key register. So we need to be able to read that register. Just create a dereferenced pointer like the one shown. Now you can read it just like any other variable. Remember that you just can't write to it since that register is read-only. For our example we'll also define a Mask for the B button. This is the bit that corresponds to the B button press in the key register.

Finally, to determine if we are in fact pressing down the B button we need to have this if statement somewhere in our code. We do this by flipping all of the bits in the key register. Remember, that all of the bits are set to 1 if no buttons are being pressed. When you press a button, the B button for example, that bit gets set to 0 in the key register. So by flipping all of the bits then all of the bits will be 0 instead of the bit for the button your pressing. It just makes more logical sense to do that. Then we do a bitwise and with the B Mask. If the result is 0, then you're not pressing the B button and the statement is false. Otherwise the statement is true.

main.cpp

                         
#define REG_KEY    *(vu16*)0x04000130
#define MASK_B      0x0002


if (~REG_KEY & MASK_B) {
    //Do something continously
}

                        
                    

Continuous Button press Step-by-Step Explanation

It may be hard to visualize why the code above works for continuous button presses. So checkout the explanation below to see how it all works step-by-step. For simplicity sake I'm only going to use 4 bits, but this can be extended to however many bits you want to use.

In this example, white boxes mean a 0 bit and black boxes mean a 1 bit.

Initial States: Button B not pressed


REG_KEY = 0xF: Default value of the Key Register or REG_KEY.

~REG_KEY = 0x0: Flip all of the bits in the Key register.

MASK_B = 0x2: The mask value for the B button.

~REG_KEY & MASK_B = 0x0: Results in 0 or False

Button B is pressed


REG_KEY = 0xD: Pressing button B will flip the bit in the register automatically.

~REG_KEY = 0x2: Flip all of the bits in the Key register.

MASK_B = 0x2: The mask value for the B button.

~REG_KEY & MASK_B = 0x2: Results in non-zero or True


Bitwise Calculator Link


Discrete Button Presses

Discrete button presses are a bit more complicated. It's when we want to press down a button, button B for example, and only do something once while that button is being held down. Then it will only do that action again if you release the button and press it down again. This is a very common thing to have usually in menus.

To do this we'll need to create a new variable called 'prev' which will hold the previous key register state. Initially, we set it to the same state as the register (No buttons pressed). Then in the if statement we need to include it in our bitwise and operation. If that's true, then we set the prev variable to the state where B is being pressed down. This will cause the next call to this if statement to be false if the button is still being pressed down. Then we need to check if the user has released the B button in the else statement. If so, we simply set the prev variable to the key register. Then we can press the B button down again to do something and so on.

main.cpp

                         
#define REG_KEY    *(vu16*)0x04000130
#define MASK_B      0x0002
vu16 prev = REG_KEY;


if ((~REG_KEY & prev) & MASK_B) {
    prev = REG_KEY;
    //Do something once
}
else if( REG_KEY & ~prev & MASK_B) {
    prev = REG_KEY;

}

                        
                    

Discrete Button press Step-by-Step Explanation

It may be hard to visualize why the code above works for discrete button presses. So checkout the explanation below to see how it all works step-by-step. For simplicity sake I'm only going to use 4 bits, but this can be extended to however many bits you want to use.

In this example, white boxes mean a 0 bit and black boxes mean a 1 bit.

Initial States: Button B not pressed


REG_KEY = 0xF: Default value of the Key Register or REG_KEY.

prev = 0xF: The prev variable set to the value in REG_KEY.

~REG_KEY = 0x0: Flip all of the bits in the Key register.

MASK_B = 0x2: The mask value for the B button.

~REG_KEY & prev & MASK_B = 0x0: Results in 0 or False

Button B is pressed down


REG_KEY = 0xD: Button B pressed so second bit is cleared in register.

prev = 0xF: The prev variable shows the REG_KEY previous state.

~REG_KEY = 0x2: Flip all of the bits in the Key register.

MASK_B = 0x2: The mask value for the B button.

~REG_KEY & prev & MASK_B = 0x2: Results in non-zero or True. Do something once in the if statement.

Button B is pressed down still


REG_KEY = 0xD: Button B pressed so second bit is cleared in register.

prev = 0xD: The prev variable shows the REG_KEY previous state. Sets to REG_KEY in the if statement.

~REG_KEY = 0x2: Flip all of the bits in the Key register.

MASK_B = 0x2: The mask value for the B button.

~REG_KEY & prev & MASK_B = 0x0: Results in zero or False. Will not enter if statement again.

Button B is released


REG_KEY = 0xF: Button B is released so bit goes back to 1 in REG_KEY.

prev = 0xD: The prev variable shows the REG_KEY previous state.

~REG_KEY = 0x2: Flip all of the bits in the Key register.

MASK_B = 0x2: The mask value for the B button.

~REG_KEY & prev & MASK_B = 0x0: Results in zero or False. Will not enter if statement again.

~prev = 0x0: Flip the prev bits.

REG_KEY & ~prev & MASK_B = 0x2: Results in non-zero or True. The else statement will set prev to the current state of REG_KEY.

Back to Initial States: Button B not pressed


REG_KEY = 0xF: Default value of the Key Register or REG_KEY.

prev = 0xF: The prev variable set to the value in REG_KEY.

~REG_KEY = 0x0: Flip all of the bits in the Key register.

MASK_B = 0x2: The mask value for the B button.

~REG_KEY & prev & MASK_B = 0x0: Results in 0 or False