ammianus wrote:I think you may be misunderstanding my question. It's not that the 32x code is slowing down, its that the apparent reading of the input is happening way too fast. So the slightest press of start button key is read as multiple presses of that button.
Ah - that comes back to Stef's suggestions... and general usage of controller values regardless of the platform. Let's look at some basics.
Most platforms give you joypad inputs as a field of positive values - each bit is SET when a button is pressed. In the case of my sample code for the 32X, each word looks like this:
type (upper 4 bits):buttons (lower 12 bits)
The type is either 0xF if no controller is present, 1 if a six button pad is present, or 0 if a three button pad is present. The buttons are SET to 1 if the corresponding button is pressed, and consist of:
(0 0 0 1 M X Y Z S A C B R L D U) or (0 0 0 0 0 0 0 0 S A C B R L D U)
Notice how the return value for a six button pad has 0 0 0 1 for the top four bits? That's that type field I mentioned.
Now that we know what's stored in the comm register, how do we use it? The simplest way is probably what you are doing - just looking if a bit is set. All that tells us is if the button is pressed or not. Good for some things, but "too fast" for others.
To see which buttons have changed, you need to exclusive-or the buttons with the last value you read... keep one variable called something like prev_buttons, and a new variable called buttons, like this
Code: Select all
unsigned short prev_buttons = 0, buttons, changed;
Notice how I preset the previous value to 0. Now when you read the buttons, you find the ones that changed this way:
Code: Select all
buttons = COMM8; // pad(0)
changed = (buttons & 0x0FFF) ^ prev_buttons;
prev_buttons = buttons & 0x0FFF;
Notice how we strip the type field - we don't want the pad type messing with our consideration of the buttons. At the end of the code, prev_buttons hold just the buttons currently read, and changed is just the buttons that have changed (either just pressed or just released). So now if we want to do something if a button was just pressed, we do this:
Code: Select all
if ((changed & SEGA_CTRL_A) && (buttons & SEGA_CTRL_A))
The first condition see if A changed, and the second sees if it changed by being pressed. Only if BOTH are true do we pass the if. To look for a button just released, do this:
Code: Select all
if ((changed & SEGA_CTRL_A) && !(buttons & SEGA_CTRL_A))
That looks to see if A changed, but the second condition now checks if it changed by NOT being set, i.e., just released.
If you do things when a button is pressed, or released, you do it ONCE for each time the button is pressed or released instead of every time through the loop. Sometimes you want to do something every time, but many times you just want to do things once.
One caution - notice how above I don't strip buttons just to look at it. Let's say we wish to wait until ANY button is pressed - you might try this:
Code: Select all
while (!buttons) buttons = COMM8;
and you would be wrong! There's that type field... if you have a six button pad, buttons will ALWAYS be 0x1000 when not pressing buttons, so the wait will NOT wait. That only works right for 3 button pads. To wait for any button, do this instead:
Code: Select all
while (!(buttons & 0x0FFF)) buttons = COMM8;
Strip that type field!