07. Controllers

There are 2 controller ports on the NES. You can read them anytime, using ports 4016 and 4017. Behind the scenes, it is strobing the 4016 port off and on, and then reading the buttons, 1 button at a time, times 8 reads, and then shifting them into a variable.

Neslib, use this function.

pad1 = pad_poll(0) to read controller 1.

pad2 = pad_poll(1) to read controller 2.

pad_state(0) or pad_state(1) if you forgot the value, and want to get it again without re-reading the controllers.

pad_trigger() gets the newly pressed buttons. I don’t use it. If you did, the order would be pad_trigger() and then pad_state(), since trigger runs the pad_poll() function.

I wrote a function get_pad_new(), which is similar to pad_trigger(), except you run pad_poll() first, and then get_pad_new().

pad1 = pad_poll(0); pad1_new = get_pad_new(0);

And, pad1_new would then have the newly pressed buttons. Like for triggering “Pause”. We don’t want it to continuously pause and unpause if you hold Start down. Only change modes if you let go of the Start button and press it once again.

pad1 is a char (8 bit), basically a bit field of 8 buttons. And we have to apply bit masks to get the individual button presses.

if(pad1_new & PAD_START){
    Pause();
}

.

Sprite vs. sprite collisions.

I have each sprite controlled by a different controller. When they collide, I’m changing the background color.

if (collision){
    pal_col(0,0x30); 
}

And, I wrote a funtion that can test any sprite objects to see if they are touching. But you have to pass 2 structs (or arrays) of 4 bytes each, where the byte order is (x, y, width, height). I made this function take in 2 void pointers, because I wanted to be able to use different types of structs in the future. At least, that was the plan.

Here’s the example in the code…

collision = check_collision(&BoxGuy1, &BoxGuy2);

I suppose we could have put this inside the if condition, if you like.

if(check_collision(&BoxGuy1, &BoxGuy2))

The ASM funtion is an optimized version of this code…

if((obj1_right >= obj2_left) &&

(obj2_right >= obj1_left) &&

(obj1_bottom >= obj2_top) &&

(obj2_bottom >= obj1_top)) return 1;

else return 0;

And we know it’s working, because the screen turns white when they touch. The code breaks a bit when one object is half off the edge of the screen. It’s working well enough for my needs.

https://github.com/nesdoug/08_Pads/blob/master/Pads.c

https://github.com/nesdoug/08_Pads

Last updated