Welcome to the third Wii programming tutorial that will cover the gamecube/Wii controller interaction and using gcube. I’m going to assume that you’ve read the previous 2 tutorials. You can grab the PDF of this tutorial here: codemii-tutorial-3
Firstly download this tutorial3-blank zip file which will contain some standard source code, the makefile and the programmer’s notepad project file. Extract this zip file in C:\devkitPro\examples\gamecube. Open up tutorial3.pnproj which is the programmer’s notepad project file, expand the source directory and then click on main.c to show the source code.
So in main.c we have our usual include statements, our screen variables and all of the initialisation of the video and controller in the Initialise function. Below the initialise function we have our main function, the function that is always run first, which calls Initialise to set up the video/controller and then print out “Hello World”; all stuff we should already know. Just in case you are wondering the \n in the printf statement is actually a line break. If we were to print some more text, it would appear on the next line down.
If you want, you can compile the source code (Alt + 1) and as usual you will see two files appear (tutorial3.dol and tutorial3.elf). The makefile that was included in the zip file uses the gamecube rules, so we can actually run tutorial3.dol on gcube. Double click to run tutorial3.dol and associate it with gcube (C:\devkitPro\emulators\gcube\gcube.exe). This will then bring up gcube and show the “Hello World!” text which has made things a lot easier for us. You can now close down gcube.
There is a slight difference on how we call the controller functions between the gamecube and the wii which you may have noticed. The difference is that for gamecube we have statements that start with PAD_ whilst on the Wii the statements start with WPAD_ (W for Wii).
So let’s begin with capturing the gamecube controller inputs. First things first, we need to scan for any input which is done by using PAD_ScanPads();. If you don’t have the call to this function then the controller will be useless.
There are 3 different button states which include whether the button has been pushed (PAD_ButtonsDown) if a button has been held down (PAD_ButtonsHeld) and if a button has been released (PAD_ButtonsUp).
In this example we want to check if a certain button, say the A button is has been pressed, in this case we would use the PAD_ButtonsDown as shown below.
[sourcecode language='c']u16 buttonsDown = PAD_ButtonsDown(0);[/sourcecode]
We are assigning the variable buttonsDown with the function of PAD_ButtonsDown. The 0 in brackets represents the controller number, 0 for the first controller, 1 for the second controller, etc.
Now we need to check if the A button was pressed by doing an if statement, firstly checking if the buttonsDown variable has a value and if the key that was pressed was the A button.
[sourcecode language=’c’]
if( buttonsDown & PAD_BUTTON_A ) {
printf(“Button A pressed.\n”);
}[/sourcecode]
You could say that the buttonsDown variable acts like a Boolean; if no button was pressed the variable remains as 0 (false) and if a button was pressed the variable will contain a value (true). So if a button was pressed and that button was A, it will print “Button A pressed.”
We can change button A to any of the other buttons which can be found in “C:\devkitPro\libogc\include\ogc\pad.h” The pad.h file lists all the buttons and functions which relate to the controller.
So now we want to check if the A button is held down and when the A button is released which is shown below. The code is similar to the code supplied above, except that we are using the different function names and assigning them to different variables.
[sourcecode language=’c’]
u16 buttonsHeld = PAD_ButtonsHeld(0);
if (buttonsHeld & PAD_BUTTON_A ) {
printf(“Button A is being held down.\n”);
}
u16 buttonsUp = PAD_ButtonsUp(0);
if (buttonsUp & PAD_BUTTON_A ) {
printf(“Button A released.\n”);
}[/sourcecode]
We have access to the 2 joysticks on the gamecube controller by using PAD_SubStickX, PAD_SubStickY, PAD_StickX and PAD_StickY. When using the joysticks you don’t need to call buttonsDown or anything else.
What you want is to define how much movement of the joystick relates to that input being detected in your application. Use a lower number to detect the slightest movement and a higher number to detect harsh movements. For example, if we wish to detect movements of the joystick when the joystick is moved right to the top and bottom we should use -18 and 18 as shown below. Remember in an x/y axis, negative y is down, positive y is up, negative x is left and positive x is right.
[sourcecode language=’c’]
if (PAD_StickY(0) > 18) {
printf(“Joystick moved up.\n”);
}
if (PAD_StickY(0) < -18) { printf(“Joystick moved down.\n”); }[/sourcecode] So what we are doing is checking if the joystick has been moved up or down and if so we print out which way it has been moved. Note that for the joystick it’s like the function PAD_ButtonsHeld, it will keep printing out moved up or moved down until you let go of the joystick. Now all we need to do is place all the above into a while statement so the controller state is continually scanned and the if statements can be run. We’ll also add in the if statement to detect when the start button is pressed, so it can terminate. Below is our final code (tutorial3-gamecube) with all of our modifications. Place this code after the printf(“Hello World.\n”);
[sourcecode language=’c’]
while(1) {
PAD_ScanPads();
u16 buttonsDown = PAD_ButtonsDown(0);
if( buttonsDown & PAD_BUTTON_A ) {
printf(“Button A pressed.\n”);
}
u16 buttonsHeld = PAD_ButtonsHeld(0);
if (buttonsHeld & PAD_BUTTON_A ) {
printf(“Button A is being held down.\n”);
}
u16 buttonsUp = PAD_ButtonsUp(0);
if (buttonsUp & PAD_BUTTON_A ) {
printf(“Button A released.\n”);
}
if (PAD_StickY(0) > 18) {
printf(“Joystick moved up.\n”);
}
if (PAD_StickY(0) < -18) {
printf("Joystick moved down.\n");
}
if (buttonsDown & PAD_BUTTON_START) {
exit(0);
}
}[/sourcecode]
Hit compile (Alt + 1) and then run the tutorial3.dol file again. The gcube A button is the Q key on your keyboard and the joystick up and down is the 8 and 5 on your keypad. Try pressing the A button and you will see it’ll print that the key is down and that it’s being held. Release the key and it will print that the A button has been released as we expected. Press the up and down on the joystick (8 and 2) and you’ll see that it will say repeatedly say it’s moving up or down.
So lets now go now and compile our project for the Wii instead of the gamecube. In the makefile, firstly change the gamecube_rules to wii_rules in line that reads:
[sourcecode language='c']
include $(DEVKITPPC)/gamecube_rules[/sourcecode]
Now we need to add the Wii and the Bluetooth libraries to our compiler. Modify the libs line to read:
[sourcecode language='c']
LIBS := -lwiiuse -lbte -logc -lm[/sourcecode]
Save the makefile and open up main.c.
In the include section include the wiiuse file:
[sourcecode language='c']
#include
We will need to comment out any PAD_Stick statements since the Wiimote doesn’t have a joystick on it. So comment out lines if (PAD_StickY(0) > 18) { to printf(“Joystick moved down.\n”); } as shown below.
[sourcecode language=’c’]
/*if (PAD_StickY(0) > 18) {
printf(“Joystick moved up.\n”);
}
if (PAD_StickY(0) < -18) { printf("Joystick moved down.\n"); }*/[/sourcecode] The last thing we need to do is change all instances of PAD_ to WPAD_ which is easy enough as well as changing the PAD_BUTTON_START text to WPAD_BUTTON_HOME. Your main.c file (tutorial3-wii) should look like the one found below:
[sourcecode language=’c’]
#include
#include
#include
#include
#include
#include
#include
static u32 *xfb;
static GXRModeObj *rmode;
void Initialise() {
VIDEO_Init();
WPAD_Init();
rmode = VIDEO_GetPreferredMode(NULL);
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(xfb);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
}
int main() {
Initialise();
printf(“Hello World!\n”);
while(1) {
WPAD_ScanPads();
u16 buttonsDown = WPAD_ButtonsDown(0);
if( buttonsDown & WPAD_BUTTON_A ) {
printf(“Button A pressed.\n”);
}
u16 buttonsHeld = WPAD_ButtonsHeld(0);
if (buttonsHeld & WPAD_BUTTON_A ) {
printf(“Button A is being held down.\n”);
}
u16 buttonsUp = WPAD_ButtonsUp(0);
if (buttonsUp & WPAD_BUTTON_A ) {
printf(“Button A released.\n”);
}
/*if (PAD_StickY(0) > 18) {
printf(“Joystick moved up.\n”);
}
if (PAD_StickY(0) < -18) { printf("Joystick moved down.\n"); }*/ if (buttonsDown & WPAD_BUTTON_HOME) { exit(0); } } return 0; }[/sourcecode] Clean (remove) the build folder and the elf/dol by pressing Alt + 2 and then recompile the source again. Now you can rename tutorial3.elf to boot.elf and place it in a directory called tutorial3 under the /apps/ directory of your SD card and Load it with the homebrew channel. Now you have a homebrew application that interacts with the Wiimote.
This is just GREAT!
Awsum thx. Such a great and clear explanation!!
@teknecal
I have created PDFs of all the Tutorials so far (individual and a unified one with bookmarks). Email me if you want me to send you the PDFs & the original ODTs.
Main Reason for creating these was to make the formating more printer friendly & for easy offline access.
I haven’t made them available as you have copyright & I figured you’d want to host them yourself rather than linking to another site.
thanks for the tutorial, I’m following these religiously. but I’m having problems with the Wii adaption of the code. i followed to instructions to the letter yet it won’t “make” . I’ve read through the error codes and i seem to be missing “wiiuse/wiipad.h” . Could you give me a hand?
So you’re probably getting an error message saying:
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:7:25: warning: wiiuse/wpad.h: No such file or directory
or
c:/devkitpro/devkitppc/bin/../lib/gcc/powerpc-gekko/4.2.3/../../../../powerpc-gekko/bin/ld.exe: cannot find -lwiiuse
Download this libogc_wiiuse zip file and extract it to the C:\devkitPro\libogc directory.
thanks very much! i’ll try this at home. sounds easy enough. i’m looking forward to using pointer functionality now.
thanks alot
I have done the gamecube example of this tutorial. But in the gcube emulator doesnt run correctly. Appears hello word but when I press the button A (q key in the emulator) the text button pressed is not writed.
For the example run correctly is needed add the video_waitvsync() funcion in the last line of while loop. I tried it and it run.
In other hand, it is a great tutorial, thanks for it.
You might want to change the tutorial, because the part where you tell people that the 0 in brackets represents the controller port number is incorrect. The 0 is in parenthesis. I am confident you know that there is a big difference between the two in C++. Thanks for the great tutorial. Although, I would not recommend to a noob.
Great explanation!
i would only suggest using conditionals like:
#if WII
#include
#else
…
#if WII
WPAD_Init( );
#else
PAD_Init();
#endif
…
#if WII
WPAD_ScanPads();
if( WPAD_ButtonsDown( WPAD_CHAN_0 ) & WPAD_BUTTON_HOME ) exit( 0 );
#else // gamecube
PAD_ScanPads();
if (PAD_ButtonsDown(0) & PAD_BUTTON_START) exit( 0 );
#endif
missing the movement sensor now 😉
Every homebrew code i snoope i see they using PAD_Read() and WPAD_Probe() instead of *_ButtonsDown()
always wondered what the “u16” stood for
you can use u8, u16, u32, ect
what does it all mean!?? lol
does it have to do with the about of bytes used to store what button\buttons it was?
u16 is the type of the variable and is just a unsigned integer (0 to more than 0) which ranges from 0 to 65,535. u8 ranges from 0 to 255 and u32 ranges from 0 to 4,294,967,295.
For those wondering the names of the other buttons, here is the list of the MACRO names and respective value:
WPAD_BUTTON_2=0x0001
WPAD_BUTTON_1=0x0002
WPAD_BUTTON_B=0x0004
WPAD_BUTTON_A=0x0008
WPAD_BUTTON_MINUS=0x0010
WPAD_BUTTON_HOME=0x0080
WPAD_BUTTON_LEFT=0x0100
WPAD_BUTTON_RIGHT=0x0200
WPAD_BUTTON_DOWN=0x0400
WPAD_BUTTON_UP=0x0800
WPAD_BUTTON_PLUS=0x1000
Nunchuck buttons:
WPAD_NUNCHUK_BUTTON_Z=(0x0001<<16)
WPAD_NUNCHUK_BUTTON_C=(0x0002<<16)
I guess that the least significant 16 bits of the u32 are reserved for the normal wiimote and the other 16 to the nunchuck, classic & guitar hero (so it will be ok for you to use u16 for the wiimote).
and the functions that check the status (for wii):
u32 pressed = WPAD_ButtonsDown(n);
u32 released = WPAD_ButtonsUp(n);
u32 held = WPAD_ButtonsHeld(n);
where n stands for the channel (probably the wiimote with the n blue led on). n goes from 0 to 3 for each of the 4 possible wiimotes and -1 if you want to check all at once.
Keep on the good work.
GOD DAMN MOTHER……….. GAH!!!!
I can’t get this to work!
I am frustrated!
#include
#include
#include
#include
#include
#include
#include
static u32 *xfb;
static GXRModeObj *rmode;
void Initialise() {
VIDEO_Init();
PAD_Init();
rmode = VIDEO_GetPreferredMode(NULL);
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(xfb);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
}
int main() {
Initialise();
printf(“Hello World!\n”);
while(1) {
WPAD_ScanPads();
u16 buttonDown = WPAD_ButtonsDown(0);
if (buttonDown & WPAD_BUTTON_A ) {
printf(“button A was pressed.\n”);
}
u16 buttonHeld = WPAD_ButtonsHeld(0);
if (buttonHeld & WPAD_BUTTON_A ) {
printf(“button A is being held.\n”);
}
u16 buttonUp = WPAD_ButtonsUp(0);
if (buttonUp & WPAD_BUTTON_A ) {
printf(“Button A was released.\n”);
}
if (buttonDown & WPAD_BUTTON_HOME) {
exit(0);
}
}
return 0;
}
this is My file
and i changed/added the following to my makefile.
include $(DEVKITPPC)/wii_rules
LIBS := -lwiiuse -lbte -logc -lm
if i copy and paste The tutorial it works. If i do it myself it doesn’t work
I don’t get any errors
And it compiles. But when the wii loads it, the black screen and the controllers don’t connect. and nothing happens.
But i checked the Blue tooth library, it’s there. There is something wrong But i can’t find it! I am frustrated. I re-did it 3 times to no avail!
The only thing I can see that’s different is your PAD_Init();
Change that to WPAD_Init();
don’t dawn you mother by God ! It’s terrible !!!
lol
Oh…. Thanks, i looked it over and re wrote it a few times, But i couldn;t See what was wrong, i must have over looked that one line
I followed all the instructions, but cant load it with Gcube. I double click on Gcube but it never loads. The readme says to put it in usr/local/bin, but I dont have that folder. Should I make one or is it talking about something else?
If you’re on windows, all you need to do is double click the .dol file that is created when you compile. It will then ask you which program to execute this file on, which you then navigate and choose the gcube.exe file.
Ok it works now. Thanx for your help.
Is there a way to clear the screen, as in have the text always pop up on the first line, instead of having it scroll down the page? VIDEO_ClearFrameBuffer doesn’t work.
Sure is. What you can do is add the following function which just sets all the framebuffer to black and then adjusts where the text will print right up the top left of the screen. [0;0H is the part of interest for this, [0 is the row and 0H is the column.
void clearscreen() {
int x,y;
for(y=0;y<486;y++)
for(x=0;x<320;x++)
xfb[x+320*y]=COLOR_BLACK;
printf("\x1b[0;0H");
}
Then just add this function before each printf like so:
if( buttonsDown & PAD_BUTTON_A ) {
clearscreen();
printf("Button A pressed.\n");
}
Also you can use:
VIDEO_ClearFrameBuffer (rmode, xfb, COLOR_BLACK);
instead of:
int x,y;
for(y=0;y<486;y++)
for(x=0;x<320;x++)
xfb[x+320*y]=COLOR_BLACK;
Thanks mate, your tuts are awesome! =D
(One small query though, I can’t get gcube to run, the window doesn’t appear tho the process does, anything I can do to fix this? Thanks.)
I’ve had that happen too, but only when I use wii_rules in the makefile. Can you advise if you compiled tutorial3-wii.zip or did you compile the tutorial3-blank.zip?
I was thinking of porting stepmania (DDR Sim) to the wii by just simply changing the controls to the wii. The problem is i dont know where the controls are in the source code in the file and how i would compile all that data. If you want to see the source code yourself go to. http://www.stepmania.com/wiki/Download_StepMania_Source_Code
If just changing the controls wont work is there another way to go about porting it to the wii.
I think it’s a little more complicated however looks like there is someone also working on it: http://www.wiibrew.org/wiki/User:Borbzz/StepMania
ok thanks. Im trying to get in contact with him but i dont know how.
Oh dammit! I can’t get it to work at all on my Wii! It works perfectly on gcube, but when I upgrade it to wii… I tryed on my own. No work. I tried Copy&Paste of the tutorial. Nothing! It doesn’t even print “Hello World!”. But I think the problem is about the screen update, since if I push the Home button, it returns to HBC, as it should; so the program is surely executed, but for some reasons it can’t print the words on the screen. Here’s my code:
#include
#include
#include
#include
#include
#include
#include
static u32 *xfb;
static GXRModeObj *rmode;
void Initialise() {
VIDEO_Init();
WPAD_Init();
rmode = VIDEO_GetPreferredMode(NULL);
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(xfb);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
}
int main() {
Initialise();
printf(“Hello World!n”);
while(1) {
WPAD_ScanPads();
u16 buttonsDown = WPAD_ButtonsDown(0);
if( buttonsDown & WPAD_BUTTON_A ) {
printf(“Button A pressed.n”);
}
u16 buttonsHeld = WPAD_ButtonsHeld(0);
if (buttonsHeld & WPAD_BUTTON_A ) {
printf(“Button A is being held down.n”);
}
u16 buttonsUp = WPAD_ButtonsUp(0);
if (buttonsUp & WPAD_BUTTON_A ) {
printf(“Button A released.n”);
}
/*if (PAD_StickY(0) > 18) {
printf(“Joystick moved up.n”);
}
if (PAD_StickY(0) < -18) {
printf(“Joystick moved down.n”);
}*/
if (buttonsDown & WPAD_BUTTON_HOME) {
exit(0);
}
VIDEO_WaitVSync();
}
return 0;
}
Makefile modifies:
include $(DEVKITPPC)/wii_rules
LIBS := -lwiiuse -lbte -logc -lm
Please add printf(“\x1b[2;0H”); before printf(”Hello World\n”);
This was added in an update to r15 I believe. It tells the system where on the screen to print the text.
And how about the Nunchuk? That one contains a joystick?
I get the
“c:/devkitpro/examples/gamecube/tutorial3/source/main.c:7:25: warning: wiiuse/wpad.h: No such file or directory”
also, but I know I already have the wiiuse library in the right place. I double checked.
Is it possible it’s because I installed devkitpro to a different folder than default?
Nevermind, I figured out my problem.
Hi, I got this to compile on Linux, but it won’t link:
linking … tutorial3.elf
/home/devyn/Applications/devkitPPC/lib/wii/libogc.a(system.o): In function `SYS_Init’:
system.c:(.text.SYS_Init+0x156): undefined reference to `__Arena2Lo’
system.c:(.text.SYS_Init+0x15a): undefined reference to `__Arena2Lo’
system.c:(.text.SYS_Init+0x162): undefined reference to `__Arena2Hi’
system.c:(.text.SYS_Init+0x166): undefined reference to `__Arena2Hi’
system.c:(.text.SYS_Init+0x16e): undefined reference to `__ipcbufferLo’
system.c:(.text.SYS_Init+0x176): undefined reference to `__ipcbufferLo’
system.c:(.text.SYS_Init+0x17a): undefined reference to `__ipcbufferHi’
system.c:(.text.SYS_Init+0x182): undefined reference to `__ipcbufferHi’
collect2: ld returned 1 exit status
make[1]: *** [/home/devyn/Downloads/wii/tutorial3/tutorial3.elf] Error 1
make: *** [build] Error 2
I’m using GCC.
OH, wait sorry, got it working.
Okay, got another problem: HBC says it’s not a valid app, using Wiiload.
Forgot to make the modifications for the Wii. Oops!
Now the Wiimote won’t connect, and I do have WPAD_ScanPads(); and WPAD_Init(); .
Okey dokey, finally works perfectly. Just a suggestion:
bool bye = false;
void begone() {
bye = true;
}
// in our main function
SYS_SetResetCallback(begone);
SYS_SetPowerCallback(begone);
while(!bye) //instead of while(1)
This will allow you to use the front buttons on the Wii.
In this line: if (buttonsHeld & PAD_BUTTON_A ) {
Why does it only use one ampersand? Isn’t that the bitwise operator? Could you explain the logic between this conditional? I want to understand so I would know what to do when, say something comes up where i have to check for multiple buttons to do the same action (like press A *OR* B to shoot).
That’s correct it is a bitwise operator, it’s the AND operator. You need both make it work I believe.
So to have code that is press A or B it would be:
if ( (buttonsHeld & PAD_BUTTON_A) || (buttonsHeld & PAD_BUTTON_B) ) {
Does buttonsHeld hold more than one button status at a time? I’m making a game where the aim is to mash as many buttons as possible. Luckily i made a good guess and figured asking “if (buttonsDown&buttonsUp)” would check if the same button that was pressed down was pressed up. But still, i’d like to understand how the u16 variable works and why using & would do what it does.
Also another quick question, how do you make your text show up in a certain part of the screen? Say I had a score gauge that I wanted in the top middle of the screen, and when the score went up it would just change the number?
buttonsHeld does allow more than one button status at a time. About how it works, I’m not too sure myself, I’ve always just accepted it, I’m hoping someone who knows will reply about this?
Depends on the text you wish to use. If you are making a console based applications, you can use something like printf(“\x1b[2;0H”);. The 2 is the vertical and the 0 is the horizontal.
If you are using a graphics library like GRRLIB, there is a version with freetype support which means you can dynamically generate text and place it in the same spot all the time and use something like:
GRRLIB_DrawImg(270, 376, 640, FONTSIZE_SMALL*2, progress, 0, 1.0, 1.0, 255);
Here is an example of using freetype and GRRLIB:
http://wiibrew.org/wiki/File:Grrfreetype.zip
Wow, compared to what we’ve been doing so far, GRRLIB seems much easier. I just need to learn what all the functions do and such. You should make your next tutorial over it.
Anyways thanks for the info!
As stated, the & is the AND operator. What is being done here is what is called bit masking.
In order to understand this, we need to look at the bits being stored for each of the values.
When buttonsHeld is loaded, it is assigned a value. For our example, let’s say it holds the hexadecimal value 0x0005. Each of the digits after the 0x is one hexadecimal digit. One hexadecimal digit can be converted to a binary representation of 4 bits. The 0’s each are 0000 in binary. The 5 is 0101. If you don’t understand hex or binary, please look on the web. I’m sure there are a lot of resources explaining them and how to convert between them.
Now, based on a post above, the following constants are being used:
WPAD_BUTTON_2=0×0001
WPAD_BUTTON_1=0×0002
WPAD_BUTTON_B=0×0004
Those values are in hex (note the 0x in front). The binary equivalents are:
0x0001 = 0000 0000 0000 0001
0x0002 = 0000 0000 0000 0010
0x0004 = 0000 0000 0000 0100
Notice that each one only has one ‘1’ in it.
Now what we do is mask the value of buttonsHeld with the constants above using the & operator. What this does is compare each bit. If both of them are 1 then the outcome is 1, otherwise the outcome is 0. Think of a mask for your face. The eyeholes let you see what is underneath, but the rest covers your face. The constants are like the mask. All the 0’s block what it is masking, but the 1’s let you see the value.
So if we take buttonsHeld:
0000 0000 0000 0101
And mask it with WPAD_BUTTON_2:
0000 0000 0000 0001
We get:
0000 0000 0000 0001
Which is not a value of 0, so that means that button 2 is being held. Note that in C a value of 0 is false and anything else is true.
If we mask buttonsHeld with WPAD_BUTTON_1:
0000 0000 0000 0010
We get:
0000 0000 0000 0000
That is a value of 0 so that means that button 1 is not being held.
If we mask buttonsHeld with WPAD_BUTTON_B
0000 0000 0000 0100
We get:
0000 0000 0000 0100
Which is not a value of 0, so that means that button B is being held.
That is how bit masking works and that is why the commands in the tutorial work.
Thanks for that explanation! I knew what binary and hexadecimal were, and i knew how the and operator worked, I just needed to understand what it all was doing(which you explained well).
I agree, well said shtuug and thanks for posting 🙂
#include
#include
#include
#include
#include
#include
#include
static u32 *xfb;
static GXRModeObj *rmode;
void Initialise() {
VIDEO_Init();
WPAD_Init();
rmode = VIDEO_GetPreferredMode(NULL);
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(xfb);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
}
int main() {
Initialise();
printf(“Hello World!n”);
while(1) {
WPAD_ScanPads();
u16 buttonsDown = WPAD_ButtonsDown(0);
if (buttonsDown & WPAD_BUTTON_A) {
printf(“Button A pressed.n”);
}
u16 buttonsHeld = WPAD_ButtonsHeld(0);
if (buttonsUp & WPAD_BUTTON_A) {
prinf(“Button A is being held down.n”);
}
u16 buttonsUp = WPAD_ButtonsUp(0);
if (buttonsUP & WPAD_BUTTON_A) {
printf(“Button A released.n”);
}
/*if (PAD_STICKY(0) > 18 {
printf(“Joystick moved up.n”);
}
if (PAD_STICKY(0) < -18 {
printf(“Joystick moved down.n”);
}*/
if (buttonsDown & WPAD_BUTTON_HOME) {
exit(0);
}
}
return 0;
}
help please
> “make”
main.c
c:/devkitpro/examples/gamecube/tutorial3/source/main.c: In function ‘main’:
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:50: error: ‘buttonsUp’ undeclared (first use in this function)
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:50: error: (Each undeclared identifier is reported only once
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:50: error: for each function it appears in.)
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:51: warning: implicit declaration of function ‘prinf’
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:56: error: ‘buttonsUP’ undeclared (first use in this function)
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:60: warning: implicit declaration of function ‘WPAD_STICKY’
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:60: error: expected ‘)’ before ‘{‘ token
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:74: error: expected expression before ‘}’ token
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:54: warning: unused variable ‘buttonsUp’
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:48: warning: unused variable ‘buttonsHeld’
c:/devkitpro/examples/gamecube/tutorial3/source/main.c:74: error: expected declaration or statement at end of input
make[1]: *** [main.o] Error 1
“make”: *** [build] Error 2
> Process Exit Code: 2
> Time Taken: 00:01
btw that is my error
Change
if (buttonsUp & WPAD_BUTTON_A) {
prinf(”Button A is being held down.n”);
}
to
if (buttonsHeld & WPAD_BUTTON_A) {
printf(”Button A is being held down.\n”);
}
Change
if (buttonsUP & WPAD_BUTTON_A) {
printf(”Button A released.n”);
}
to
if (buttonsUp & WPAD_BUTTON_A) {
printf(”Button A released.\n”);
}
Why not eliminate those static globals:
static u32 *xfb;
static GXRModeObj *rmode;
You can declare them in main, and change the Initialise() function to:
Initialise(u32& xfb, GXRModeObj& rmode).
That way the code is more portable and it is clear what must exist when you call it.
Also, this is a great series of tutorials. The best, in fact, for Wii beginners. Thanks a lot. I’ll hopefully have a fighting game out in a couple of months with this base in hand, and credit will go to you Tek.
Let me just start by saying wonderful tutorials. I’m on #3 and I just realized I’ve been up all night.
This particular tut will not load the wii remote for me though.
Compiles fine, even compiled from different directories. Tried both dol and elf files to no avail.
I’ve altered the code to match and then even tried the “tutoral3-wii” and I’m stuck looking at hello world on the wii with no chance of the wiimote loading (just flashes).
I’m a little new to C/C++ but I’ve used many others (Java, VB.NET, etc. ) so I am familiar with the code structures. I absolutely love the editor, and it’s versatility.
But jugding by the output to screen (Hello World), it would seem that it would either be a problem with the loop, or a problem with a library.
I’ll keep messing with it, but any ideas?
That is very strange, this tutorial was made for DevKitPPC r14 so that might have something to do with it.
If you check your C:\devkitPro\examples\wii\template\source directory, you should see the latest example of the hello world which actually contains wiimote button pressing. Could you try to compile that example and see if it works?