Check out the link for a refresher on the Key Register.
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
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
Check out this fun bitwise calculator to help understand the calculation here.
Links
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
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
