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.

[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 [/sourcecode]

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.

54 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=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.

  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.

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

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

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

          • 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?

Leave a Reply for teknecal