Tutorial 3: Controller input

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.

u16 buttonsDown = PAD_ButtonsDown(0);

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.

if( buttonsDown & PAD_BUTTON_A ) {
	printf("Button A pressed.\n");
}

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.

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");
}

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.

if (PAD_StickY(0) > 18) {
	printf(“Joystick moved up.\n”);
}

if (PAD_StickY(0) < -18) {
	printf(“Joystick moved down.\n”);
}

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”);

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);
	}
}

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:

include $(DEVKITPPC)/gamecube_rules

Now we need to add the Wii and the Bluetooth libraries to our compiler. Modify the libs line to read:

LIBS    :=    -lwiiuse -lbte -logc -lm

Save the makefile and open up main.c.

In the include section include the wiiuse file:

#include <wiiuse/wpad.h>

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.

/*if (PAD_StickY(0) > 18) {
	printf("Joystick moved up.\n");
}

if (PAD_StickY(0) < -18) {
	printf("Joystick moved down.\n");
}*/

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:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <gccore.h>
#include <wiiuse/wpad.h>

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;
}

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.

86 Responses to “Tutorial 3: Controller input”

  1. niohubala says:

    This is just GREAT!

    Awsum thx. Such a great and clear explanation!!

  2. Pvt_Ryan says:

    @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.

  3. Speggy says:

    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?

  4. teknecal says:

    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.

  5. harry says:

    thanks very much! i’ll try this at home. sounds easy enough. i’m looking forward to using pointer functionality now.

  6. DCelso says:

    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.

  7. Blaine says:

    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.

  8. gabriel says:

    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

  9. gabriel says:

    missing the movement sensor now ;)

  10. gabriel says:

    Every homebrew code i snoope i see they using PAD_Read() and WPAD_Probe() instead of *_ButtonsDown()

  11. Seb says:

    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?

  12. teknecal says:

    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.

  13. Aknahs says:

    For those wondering the names of the other buttons, here is the list of the MACRO names and respective value:

    WPAD_BUTTON_2=0×0001
    WPAD_BUTTON_1=0×0002
    WPAD_BUTTON_B=0×0004
    WPAD_BUTTON_A=0×0008
    WPAD_BUTTON_MINUS=0×0010
    WPAD_BUTTON_HOME=0×0080
    WPAD_BUTTON_LEFT=0×0100
    WPAD_BUTTON_RIGHT=0×0200
    WPAD_BUTTON_DOWN=0×0400
    WPAD_BUTTON_UP=0×0800
    WPAD_BUTTON_PLUS=0×1000

    Nunchuck buttons:

    WPAD_NUNCHUK_BUTTON_Z=(0×0001<<16)
    WPAD_NUNCHUK_BUTTON_C=(0×0002<<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.

  14. durdadan says:

    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!

  15. durdadan says:

    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

  16. Jacic says:

    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?

    • teknecal says:

      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.

      • Tom says:

        Help! I’m on Windows and associated the .dol (and eve the .elf) with gcube.exe, but when I double-click any of them the gcube window appears for only a split second and disappears. I thought I could keep it there with an infinite loop, but then I remembered the source of this example already has one. What can I do?
        By the way, thanks for this tutorials and for your help.

  17. Jacic says:

    Ok it works now. Thanx for your help.

  18. Andrew says:

    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.

    • teknecal says:

      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”);
      }

      • teknecal says:

        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;

  19. ed says:

    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.)

    • teknecal says:

      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?

  20. Blaise says:

    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.

  21. Blaise says:

    ok thanks. Im trying to get in contact with him but i dont know how.

  22. Alexander says:

    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

    • teknecal says:

      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.

  23. Drag0nflamez says:

    And how about the Nunchuk? That one contains a joystick?

  24. funkamatic says:

    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?

  25. Devyn says:

    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+0×156): undefined reference to `__Arena2Lo’
    system.c:(.text.SYS_Init+0×15a): undefined reference to `__Arena2Lo’
    system.c:(.text.SYS_Init+0×162): undefined reference to `__Arena2Hi’
    system.c:(.text.SYS_Init+0×166): undefined reference to `__Arena2Hi’
    system.c:(.text.SYS_Init+0×16e): undefined reference to `__ipcbufferLo’
    system.c:(.text.SYS_Init+0×176): undefined reference to `__ipcbufferLo’
    system.c:(.text.SYS_Init+0×17a): undefined reference to `__ipcbufferHi’
    system.c:(.text.SYS_Init+0×182): 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.

    • Devyn says:

      OH, wait sorry, got it working.

    • Devyn says:

      Okay, got another problem: HBC says it’s not a valid app, using Wiiload.

      • Devyn says:

        Forgot to make the modifications for the Wii. Oops!

        Now the Wiimote won’t connect, and I do have WPAD_ScanPads(); and WPAD_Init(); .

        • Devyn says:

          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.

    • kevin says:

      what did you do to make the first errors you got work? i have the same problem :(

  26. FireFreek says:

    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).

    • teknecal says:

      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) ) {

      • FireFreek says:

        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?

        • teknecal says:

          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

          • FireFreek says:

            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!

        • shtuug says:

          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 0×0005. 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:
          0×0001 = 0000 0000 0000 0001
          0×0002 = 0000 0000 0000 0010
          0×0004 = 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.

          • FireFreek says:

            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).

  27. Sx2Kirby says:

    #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

  28. Sx2Kirby says:

    > “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

    • teknecal says:

      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”);
      }

  29. dawdawdo says:

    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.

  30. MadtKrandle says:

    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?

    • teknecal says:

      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?

      • MadtKrandle says:

        Sorry for the delay…

        I have compiled the template.c with a corresponding Makefile to no avail…. I end up with a wiimote that just blinks and is not recognized.

        I CAN get the “Hello World” text to print to screen, as long as I use a locate statement in front (widescreen monitor).

        I think, as well as you have mentioned, that it may be a compatibility issue… as the GameCube emulator will not run for me and never has. It opens briefly, then closes.

        Just to clarify, I have made sure the associated rules in the makefile are for Gamecube…

        I’m running Vista Ultimate on a Toshiba Qosmio lap with all the essentials… I could try it on any number of desktops in the network with different os’s to see if I get different results… but for right now I’m stuck here.

        I’m currently belting myself c, and c++, and eventually c# and asp.net (as I’m more familiar… VS Studio, etc.)… I’m a worker though. And as any elegant programmer, won’t succumb to defeat so easily.

        The progress so far has secured my interest, and I’m eager… I love the idea.

        Only if you have the time; I’m a very busy man myself as I assume you are… but I’ve got the means, and the technology.

        I downloaded the Developer’s Kit that is in the tutorial, and I have user account control disabled-although that shouldn’t matter (but the GC emu won’t load so… just covering the bases).

        Like I said… if you have time… you could certainly save me some…

        Thanks, and great tutorials btw.
        Madt

        • teknecal says:

          That’s quite odd, so do homebrew apps work fine with your wiimote? e.g. fceu, snes, mplayer, etc.

          For the gamecube emulator, I believe most of the examples you should be able to compile and run with gcube. Maybe try running it in Windows XP mode?

          • MadtKrandle says:

            Oh yeah…. homebrew apps work great..

            I’ll break it all down:

            WII

            LU64+ 4.1U Firmware (updated prior to softmod)
            Hombrew, BootMii, DVDX, (no preloader.. at least not yet.. I’m careful-so I haven’t needed it)

            CHANNELS

            USB Loaders, WII Earth, MPlayerCE, NES Emu (Fceu), SNES Emu (znes), SEGA Emu (Gens… I think), Gameboy Emu (GBA), NeoGeo Emu (GxGeo… fully working), Ocarina, and a couple select fav wads.—-Wiimote works with all that support it.

            PERIPHERALS

            WD 1TB USB HD, and the usual controllers/chucks/classic/GCPad, motion plus’, balance board, standard sensor bar.

            All working stellar (it better! I probably put 20 hours into it so far over the last month).

            I suspect the problem exists with this Lap that I’m using. It’s a wonderful Lap- I can’t complain- Toshiba’s are workhorses… But it’s a millitary issued (lot of family in the service, and I like their technology a little bit better than standard retail) but the thing’s got the IR fingerprint scanner, Camera and Assistant software, Harmon Kardon Audio, extensive On-Screen Pull down Menus, and all sorts of other things running on Vista Ultimate and the potential for issues IS there I guess… there’s just so much in this thing- though I haven’t experienced any issues that a simple update couldn’t fix… I remain the skeptic.

            Also (purely informative), after not being able to get the gcube to run, I started screwing with Dolphin even though it’s well-known that it won’t run on most laptops, and I had great success. I even dumped my nand backup and have the WII System Menu working….. on my laptop! With Bluetooth and Wiimote support.

            So I’m completely inclined to agree with you that I have to try these tutorials on a PC with XP. My best PC also runs Ultimate, so I’ll try it on one of the Dells that runs XP and post results. It’ll be a couple days since I don’t want to attempt this remotely and further complicate the troubleshooting, I’d rather be sitting at the PC, at the office for the best possible results.

            Thank you for the direction, I’ve always been a firm believer that two heads are better than one… and now I’m very intrigued about isolating this issue cos it’s now going to bother me until I do.

  31. Ike says:

    When I try to run the dol, it just blinked on gcube. What should I do?

    • teknecal says:

      Are you running the dol that has the gamecube controller code or the Wii code? Gcube only works with the gamecube controller code.

      • Cactis says:

        Same issue here. Downloaded SuperGCube from Zophar’s and it does the same thing. Was there an update to a part of the tool chain that broke compatibility? I just downloaded this morning.

        Win XP Professional on Dell e1505 laptop with Intel 950 GMA integrated chipset.

        • ThatbeGuy says:

          This is a bit of a late reply, but…
          I had the same problem as well. I downloaded another copy of gcube from another site and ran it on the .dol file inside cmd, and it gave me the error message: “Textured rectangle extension is not supported by your video card”. I don’t think there’s any solution to my problem but it’s also possible that you might be experiencing some other error that is fixable. Just run the program from the command line against the target .dol file and it should give you the problem.

  32. first_angel says:

    My question is simple.
    I follow instruction on this tutorial. I bought bluetooth. With bluesoleil connected with my PC. I start simple tutorial3-gamecube. Following instruction i seen black screen wiet HELLO WORLD. But after pressed button nothing changed.
    How can be changed if bluetooth is connect wiimote but nothing read signal from buttons and position. Is possible give me answer how connect wiimote with PC step by step?? For use simple from Yours tutorial.

  33. sonic says:

    keep getting this error

    make[1]: *** No rule to make target `basic’, needed by `/c/devkitPro/examples/gamecube/gamecube.elf’. Stop.
    “make”: *** [build] Error 2

    anyone got any ideas this is the code im using

    int main {

    Initialise();

    printf(“Hello World!n”);

    printf(“And yes i did it myself.n”);

    printf(“so 888888888888 smoke it.n”);

    while(1) {

    PAD_scanpads();

    u16 buttonsDown = PAD_buttonsDown(0);

    if( buttonsDown & PAD_BUTTON_A) {

    printf(“button A has been pressed.n”);

    }

    u16 buttonsHeld = PAD_buttonsHeld(0);

    if( buttonsHeld & PAD_BUTTON_A) {

    printf (“the A button is being held.n”);

    }

    u16 buttonsUp = PAD_buttonsUp(0);

    if ( buttonsUp & PAD_BUTTON_A) {

    printf (“The A button has been released.n”);

    }

    u16 buttonsDown = PAD_buttonsDown(0);

    if( buttonsDown & PAD_BUTTON_B) {

    printf(“button B has been pressed.n”);

    }

    u16 buttonsHeld = PAD_buttonsHeld(0);

    if( buttonsHeld & PAD_BUTTON_B) {

    printf (“the B button is being held.n”);

    }

    u16 buttonsUp = PAD_buttonsUp(0);

    if ( buttonsUp & PAD_BUTTON_B) {

    printf (“The B button has been released.n”);

    }

    u16 buttonsDown = PAD_buttonsDown(0);

    if( buttonsDown & PAD_BUTTON_PLUS) {

    printf(“the plus button has been pressed.n”);

    }

    u16 buttonsHeld = PAD_buttonsHeld(0);

    if( buttonsHeld & PAD_BUTTON_PLUS) {

    printf (“the plus button is being held.n”);

    }

    u16 buttonsUp = PAD_buttonsUp(0);

    if ( buttonsUp & PAD_BUTTON_PLUS) {

    printf (“The plus button has been released.n”);

    }

    u16 buttonsDown = PAD_buttonsDown(0);

    if( buttonsDown & PAD_BUTTON_MINUS) {

    printf(“the minus button has been pressed.n”);

    }

    u16 buttonsHeld = PAD_buttonsHeld(0);

    if( buttonsHeld & PAD_BUTTON_MINUS) {

    printf (“the minus button is being held.n”);

    }

    u16 buttonsUp = PAD_buttonsUp(0);

    if ( buttonsUp & PAD_BUTTON_MINUS) {

    printf (“The minus button has been released.n”);

    }

    u16 buttonsDown = PAD_buttonsDown(0);

    if( buttonsDown & PAD_BUTTON_HOME) {

    printf(“the home button has been pressed.n”);

    }

    u16 buttonsHeld = PAD_buttonsHeld(0);

    if( buttonsHeld & PAD_BUTTON_HOME) {

    printf (“the home button is being held.n”);

    }

    u16 buttonsUp = PAD_buttonsUp(0);

    if ( buttonsUp & PAD_BUTTON_HOME) {

    printf (“The home button has been released.n”);

    }

    if (PAD_StickY(0) > 18) {

    printf (” The joystick has moved up.n”);

    }

    if (PAD_StickY(0) 18) {

    printf (“The joystick has moved right.n”);

    }

    if (PAD_StickX(0) < -18) {

    printf ("The joystick has moved left.n");

    }

    return 0;
    }

  34. sonic says:

    got it sorted and worked on both gcube and wii just couldnt get the thumbstick to work on wii

  35. VbFx-Alien says:

    I Keep getting the following error when I compile….
    I checked the wpad.h inside my include lib and they are defined. what could be my problem?

    #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;
    }

    linking … tutorial3.elf
    main.o: In function `Initialise':
    c:/devkitpro/examples/gamecube/tutorial3/source/main.c:12: undefined reference to `WPAD_Init'
    main.o: In function `main':
    c:/devkitpro/examples/gamecube/tutorial3/source/main.c:32: undefined reference to `WPAD_ButtonsHeld'
    c:/devkitpro/examples/gamecube/tutorial3/source/main.c:36: undefined reference to `WPAD_ButtonsUp'
    c:/devkitpro/examples/gamecube/tutorial3/source/main.c:27: undefined reference to `WPAD_ScanPads'
    c:/devkitpro/examples/gamecube/tutorial3/source/main.c:28: undefined reference to `WPAD_ButtonsDown'
    c:/devkitpro/examples/gamecube/tutorial3/source/main.c:32: undefined reference to `WPAD_ButtonsHeld'
    c:/devkitpro/examples/gamecube/tutorial3/source/main.c:36: undefined reference to `WPAD_ButtonsUp'
    collect2: ld returned 1 exit status
    make[1]: *** [/c/devkitpro/examples/gamecube/tutorial3/tutorial3.elf] Error 1
    "make": *** [build] Error 2

    > Process Exit Code: 2
    > Time Taken: 00:01

    • teknecal says:

      If you are compiling for the Wii, make sure in the makefile near the top it should say “include $(DEVKITPPC)/wii_rules”.

      If you compile for the gamecube change this to “include $(DEVKITPPC)/gamecube_rules”

    • Jenkins says:

      The same exact thing happens to me. I took some programming classes a long time ago too, so I shouldn’t be totally stupid.

  36. Dmitry says:

    Thanks for the tutorials!

    I’ve got a problem with this one – keyboard doesn’t work on gcube. I’ve downloaded and compiled tutorial3-gamecube, and when I run it I get only “Hello World”, and none of the “pressed” messages. I’ve tried every single key, especially [Q]. Only [Esc] works, and it closes gcube.

    I’m using msys-1.0.11-RC2, devkitPPC_r21, libogc-1.8.3 and gcube-0.4.0 on Win7 x64.

    Also homebrew channel doesn’t accept gamecube executables, guess it can only run wii executables.

  37. Mathew Borum says:

    What about using a numchuck

  38. Mathew Borum says:

    gcube won’t open it just flashes up and dissapears

  39. Mia says:

    Could you pls provide me a link to the # 1 and # 2 tutorial?? I just found this one and I find it very interesting.. I want to put the together and start learning.. self learning.. :D TY in advance..

  40. Kate Thom says:

    Mia is right. You should do something and upgrade your website. It would be very useful for your visitors if you would have a list (somewhere in right maybe) with your previous post. :)

  41. Matt says:

    So, I hit the “Q” key and it works fine. I try to hit the “8″ & “5″ and it don’t print anything. Using a laptop keyboard with no 10 key. How do I fix that do I can do all my testing on my laptop:)

    Thank you!

  42. 4madd says:

    I have tried a few different times copy pasting the code and i still can’t get it to work. The Hello world message is printed, but for some reason the wii remote loses connection with the wii i initiated all of the libraries too. I initiated WPAD_Init(); I really want to continue programming my wii but no remote = no progress = :(

    LIBS := -lwiiuse -lbte -logc -lm

    #include
    #include
    #include
    #include
    #include
    #include
    #include

    static u32 *xfb;
    static GXRModeObj *rmode;

    void Initialise() {

    VIDEO_Init();
    //PAD_Init(); ___> Gamecube remote init
    WPAD_Init();

    //generic video stuff
    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!\nWhich button is being presssed?\n”);
    printf(“if you can see this you are working.”);

    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;
    }

Leave a Reply