gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > Keypad : NULL?

#11967 - goro - Sat Oct 25, 2003 12:16 pm

Hi,

How do I make my character do something if no key is pressed.

I've tried:-
Code:

if (!(*KEYS == NULL))
   {
      Stand_normally();
   }


but it gives me :-
Code:
warning: NULL used in arithmetic


so, do I have to define NULL as 0 or something somewhere or
change my key detect code? (_ Tried defining NULL as (u16) 0 in my main .cpp but it gave me an error : parse error before `__null'!

please help!!!


Last edited by goro on Sat Oct 25, 2003 1:38 pm; edited 2 times in total

#11970 - NoMis - Sat Oct 25, 2003 12:57 pm

i have done it like this

#define NULL 0

and everywhere you write NULL the compiler puts 0 there instead. in c++ 0 is same as NULL but some compilers such as gcc don't understand NULL so you have to use 0. So you shouldn't use the (u16) stuff because NULL or 0 isn't a type.

NoMis

#11972 - goro - Sat Oct 25, 2003 1:30 pm

Now he continuously 'Stands normally' and ignores the rest of the animations.

It's probably because....well... I don't know!!!!

_ Let me clarify...

I want him to stand normally,
then, when 'RIGHT' is pressed I want him to go into his walking animation,
then when 'RIGHT' is released, I want him to go back to 'Stand normally'.


HELP!!!

#11976 - tepples - Sat Oct 25, 2003 3:28 pm

Try this:
Code:

#define KEYS ((volatile unsigned short *)0x04000130)

/*...*/

unsigned int j = (*KEYS ^ 0x03ff) & 0x03ff;  /* thanks Gopher for catching this */

if (j == 0)
   {
      Stand_normally();
   }

_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.


Last edited by tepples on Sat Oct 25, 2003 7:41 pm; edited 1 time in total

#11978 - Touchstone - Sat Oct 25, 2003 3:32 pm

goro wrote:
How do I make my character do something if no key is pressed.
Well, I would recommend you do a state machine for your character, or anything but reading the keypad directly. When the user press right on they keypad you set the state for your character to move right, or whatever it's supposed to do when right is pressed. Just reading if a key is pressed or not is not necessarily wrong but it could give odd side effects. For instance, when SELECT or START is pressed and you just read the keypad, do you want your character to stand normally?


goro wrote:
I've tried:-
Code:

if (!(*KEYS == NULL))
   {
      Stand_normally();
   }


but it gives me :-
Code:
warning: NULL used in arithmetic
First of all, NULL is defined as a pointer (#define NULL (void*)0) and you are comparing it to an arithmetic variable, thats why you get that warning.

And also, you are checking if the value of *KEYS is 0, and if it is NOT zero (you have the exclamation-mark before the *KEYS == 0 statement), that might be your problem. :)
_________________
You can't beat our meat

#11979 - goro - Sat Oct 25, 2003 4:16 pm

Thanks Tepples.

but I get
Code:
invalid operands of types `volatile
   u32*' and `int' to binary `operator^'


I also found out about checking for "No key pressed" here :-

http://forum.gbadev.org/viewtopic.php?t=1843&highlight=key+press

but I get different errors trying that stuff too.

PLEASE HELP!!!

Touchstone : true but aren't start & select translated as keys? in any case, There must be a quick check to see i f we are in start/select/pause/intro mode...

#11980 - Gopher - Sat Oct 25, 2003 6:58 pm

Nobody seems to have stated this tho Tepples posted code that implied it, the bits in KEYS will be 1 if the key is NOT pressed, and 0 if it is. This is why you always see the tests being negated ( with ! ).
When testing for no keys, tho, this means you must check for all the bits to be 1, not 0. KEYS will equal 0 only if ALL the keys are pressed, so !(KEYS==0) will be true if any key is not pressed, rather than if every key is not pressed.
As has been posted in code already, you need to mask KEYS by the set of all keys - there are 10, so the mask is 10 bits. 10 1s in binary 111111111 converted to hex is 0x3ff. I won't explain hex/binary now, but here's a link to the first online explanation I found on Google
http://www.learn-c.com/data_lines.htm

Ok, enough of why Tepples was mostly right. Now for why it's not working for you. Tepples example defined KEYS this way
Code:

#define KEYS ((volatile unsigned short *)0x04000130)

but tepples made one minor mistake. he defined KEYS as a pointer, but in his code later he used it thusly...
Code:

unsigned int j = (KEYS ^ 0x03ff) & 0x03ff;

which won't work because KEYS was defined as a pointer. Simplest fix: add a dereference to one or the other. If you're writing mostly in C/C++ it makes the most sense to add it to the macro, since you'll never want the address, just the value stored at it
Code:

#define KEYS (*(volatile unsigned short *)0x04000130)


That should fix the problem. But I'd strongly encourage you to learn your hex/binary number systems and C's bitwise operations, as a strong grasp of them is essential when doing low-level optimized code like GBA programming requires. From the sound of it you might also want to study & practice pointers more, too. Always strive to understand code, cutting and pasting other people's code without understanding it might help you make things faster, but when something goes wrong (like now) you end up with little hope of fixing it if you didn't understand why it worked in the first place.
_________________
"Only two things are infinite: the universe, and human stupidity. The first is debatable." -Albert Einstein

#11996 - goro - Sun Oct 26, 2003 11:05 am

Hi,

Thanks Gopher, I try to understand all code that I write (or cut&paste) by learning about it but sometimes the learning material isn't explained clearly so I ask here at the forum.

Quote:
Tepples example defined KEYS this way
Code:

#define KEYS ((volatile unsigned short *)0x04000130)


That's also how it is defined in my gba.h & when I tried to dereference it as you said i got :-

Code:
C:/devkitadv/GBA/1.cpp: In function `void GetInput()':
C:/devkitadv/GBA/1.cpp:70: invalid type argument of `unary *'
C:/devkitadv/GBA/1.cpp:80: invalid type argument of `unary *'
C:/devkitadv/GBA/1.cpp:90: invalid type argument of `unary *'
C:/devkitadv/GBA/1.cpp:133: invalid type argument of `unary *'
C:/devkitadv/GBA/1.cpp:206: invalid type argument of `unary *'
C:/devkitadv/GBA/1.cpp:212: invalid type argument of `unary *'
C:/devkitadv/GBA/1.cpp:222: invalid type argument of `unary *'
C:/devkitadv/GBA/1.cpp:232: invalid type argument of `unary *'
C:/devkitadv/GBA/1.cpp:242: invalid type argument of `unary *'
NMAKE : fatal error U1077: 'c:\devkitadv\bin\gcc' : return code '0x1'


To avoid these errors I need to dereference it at the other end i.e.
by turning
Code:
unsigned int j = (KEYS ^ 0x03ff) & 0x03ff;
into something like
Code:
unsigned int j = (*KEYS ^ 0x03ff) & 0x03ff;

but that makes he continuously 'Stands normally' and ignores the rest of the animations (even when I hold down 'LEFT' or 'RIGHT').

can you confirm that this is the correct way of dereferencing this and that my error lies elsewhere in my code?

#12007 - Gopher - Sun Oct 26, 2003 6:21 pm

I should have guessed you were using the variable in other places, so if I'd been thinking about it I would have at least pointed out that changing the macro would break everywhere that currently worked with it. The warnings just meant you were trying to dereference something that wasn't a pointer.

You do seem do be dereferencing correctly; looking at what you gave me I'm not clear what the problem is exactly. Sorry.

Is the character actually moving around but just not showing the correct animation, or is it not responding at all?
_________________
"Only two things are infinite: the universe, and human stupidity. The first is debatable." -Albert Einstein

#12028 - goro - Mon Oct 27, 2003 12:06 pm

Yeah, he moves around which means attribute 0 & 1 (his x + y positions are being updated) but he won't animate (attribute 2 isn't.)

Thanks for pointing out that I dereferenced properly, Now I'll trudge through the rest of the code to fix copying to oam or whatever else it could be.

-Edit : That's what it was : Although I was updating the hero_frame variable, I wasn't explicitly updating the
Code:
sprites[0].attribute2 = hero_frame;


Thanks again to Tepples, Touchstone, Gopher & everybody else that helped...

...Much appreciated...