In memory of Ben “bushing” Byer, who passed away on Monday, February 8th, 2016.

How to use the Wiimote (Commented): Difference between revisions

From WiiBrew
Jump to navigation Jump to search
mNo edit summary
little refactoring: make each function to fit on screen.
Line 26: Line 26:
#include <math.h>
#include <math.h>
#include <wiiuse/wpad.h>
#include <wiiuse/wpad.h>
 
static GXRModeObj *rmode = NULL;
static GXRModeObj *rmode = NULL;
 
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
//doreload - a flag that tells the program to quit looping and exit the program to the HBChannel.
//doreload - a flag that tells the program to quit looping and exit the program to the HBChannel.
//dooff - a flag that tells the program to quit looping and properly shutdown the system.
//dooff - a flag that tells the program to quit looping and properly shutdown the system.
int doreload=0, dooff=0;
int doreload=0, dooff=0;
 
//Calling the function will end the while loop and properly exit the program to the HBChannel.  
//Calling the function will end the while loop and properly exit the program to the HBChannel.  
void reload(void) {
void reload(void) {
doreload=1;
doreload=1;
}
}
 
//Calling the function will end the while loop and properly shutdown the system.
//Calling the function will end the while loop and properly shutdown the system.
void shutdown(void) {
void shutdown(void) {
dooff=1;
dooff=1;
}
}
 
//Draw a square on the screen (May draw rectangles as well, I am uncertain).  
//Draw a square on the screen (May draw rectangles as well, I am uncertain).  
//*xfb - !unsure!
//*xfb - !unsure!
Line 53: Line 53:
//color - the color of the rectangle (Examples: COLOR_YELLOW, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_BLACK, COLOR_WHITE)
//color - the color of the rectangle (Examples: COLOR_YELLOW, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_BLACK, COLOR_WHITE)
void drawdot(void *xfb, GXRModeObj *rmode, float w, float h, float fx, float fy, u32 color) {
void drawdot(void *xfb, GXRModeObj *rmode, float w, float h, float fx, float fy, u32 color) {
       
        //*fb - !unsure!
//*fb - !unsure!
        //px - !unsure!
//px - !unsure!
        //py - !unsure!
//py - !unsure!
        //x - !unsure!
//x - !unsure!
        //y - !unsure!
//y - !unsure!
 
u32 *fb;
u32 *fb;
int px,py;
int px,py;
int x,y;
int x,y;
       
 
fb = (u32*)xfb;
fb = (u32*)xfb;
 
y = fy * rmode->xfbHeight / h;
y = fy * rmode->xfbHeight / h;
x = fx * rmode->fbWidth / w / 2;
x = fx * rmode->fbWidth / w / 2;
for(py=y-4; py<=(y+4); py++) {
for(py=y-4; py<=(y+4); py++) {
if(py < 0 || py >= rmode->xfbHeight)
if(py < 0 || py >= rmode->xfbHeight)
Line 79: Line 79:
}
}
}
}
 
}
}
 
int evctr = 0;
int evctr = 0;
 
void countevs(int chan, const WPADData *data) {
void countevs(int chan, const WPADData *data) {
evctr++;
evctr++;
}
}


void print_wiimote_connection_status(int wiimote_connection_status) {
switch(wiimote_connection_status) {
case WPAD_ERR_NO_CONTROLLER:
printf("  Wiimote not connected\n");
break;
case WPAD_ERR_NOT_READY:
printf("  Wiimote not ready\n");
break;
case WPAD_ERR_NONE:
printf("  Wiimote ready\n");
break;
default:
printf("  Unknown Wimote state %d\n",wiimote_connection_status);
}
}
void print_wiimote_buttons(WPADData *wd) {
printf("  Buttons down:\n  ");
if(wd->btns_h & WPAD_BUTTON_A) printf("A ");
if(wd->btns_h & WPAD_BUTTON_B) printf("B ");
if(wd->btns_h & WPAD_BUTTON_1) printf("1 ");
if(wd->btns_h & WPAD_BUTTON_2) printf("2 ");
if(wd->btns_h & WPAD_BUTTON_MINUS) printf("MINUS ");
if(wd->btns_h & WPAD_BUTTON_HOME) printf("HOME ");
if(wd->btns_h & WPAD_BUTTON_PLUS) printf("PLUS ");
printf("\n  ");
if(wd->btns_h & WPAD_BUTTON_LEFT) printf("LEFT ");
if(wd->btns_h & WPAD_BUTTON_RIGHT) printf("RIGHT ");
if(wd->btns_h & WPAD_BUTTON_UP) printf("UP ");
if(wd->btns_h & WPAD_BUTTON_DOWN) printf("DOWN ");
printf("\n");
}
void print_and_draw_wiimote_data(void *screen_buffer) {
//Makes the var wd point to the data on the wiimote
WPADData *wd = WPAD_Data(0);
printf("  Data->Err: %d\n",wd->err);
printf("  IR Dots:\n");
int i;
for(i=0; i<4; i++) {
if(wd->ir.dot[i].visible) {
printf("  %4d, %3d\n", wd->ir.dot[i].rx, wd->ir.dot[i].ry);
drawdot(screen_buffer, rmode, 1024, 768, wd->ir.dot[i].rx, wd->ir.dot[i].ry, COLOR_YELLOW);
} else {
printf("  None\n");
}
}
//ir.valid - TRUE is the wiimote is pointing at the screen, else it is false
if(wd->ir.valid) {
float theta = wd->ir.angle / 180.0 * M_PI;
//ir.x/ir.y - The x/y coordinates that the wiimote is pointing to, relative to the screen.
//ir.angle - how far (in degrees) the wiimote is twisted (based on ir)
printf("  Cursor: %.02f,%.02f\n",wd->ir.x, wd->ir.y);
printf("    @ %.02f deg\n",wd->ir.angle);
drawdot(screen_buffer, rmode, rmode->fbWidth, rmode->xfbHeight, wd->ir.x, wd->ir.y, COLOR_RED);
drawdot(screen_buffer, rmode, rmode->fbWidth, rmode->xfbHeight, wd->ir.x + 10*sinf(theta), wd->ir.y - 10*cosf(theta), COLOR_BLUE);       
} else {
printf("  No Cursor\n\n");
}
if(wd->ir.raw_valid) {
//ir.z - How far away the wiimote is from the screen in meters
printf("  Distance: %.02fm\n", wd->ir.z);
//orient.yaw - The left/right angle of the wiimote to the screen
printf("  Yaw: %.02f deg\n", wd->orient.yaw);
} else {
printf("\n\n");
}
printf("  Accel:\n");
//accel.x/accel.y/accel.z - analog values for the accelleration of the wiimote
//(Note: Gravity pulls downwards, so even if the wiimote is not moving,
//one(or more) axis will have a reading as if it is moving "upwards")
printf("  XYZ: %3d,%3d,%3d\n",wd->accel.x,wd->accel.y,wd->accel.z);
//orient.pitch - how far the wiimote is "tilted" in degrees
printf("  Pitch: %.02f\n",wd->orient.pitch);
//orient.roll - how far the wiimote is "twisted" in degrees (uses accelerometer)
printf("  Roll:  %.02f\n",wd->orient.roll);
print_wiimote_buttons(wd);
if(wd->ir.raw_valid) {
for(i=0; i<2; i++) {
drawdot(screen_buffer, rmode, 4, 4, wd->ir.sensorbar.rot_dots[i].x+2, wd->ir.sensorbar.rot_dots[i].y+2, COLOR_GREEN);
}
}
if(wd->btns_h & WPAD_BUTTON_1) doreload=1;
}
int main(int argc, char **argv) {
int main(int argc, char **argv) {
int res;
void *xfb[2];
void *xfb[2];
u32 type;
u32 type;
int i;
int fbi = 0;
int fbi = 0;
float theta;
WPADData *wd;
VIDEO_Init();
VIDEO_Init();
PAD_Init();
PAD_Init();
WPAD_Init();
WPAD_Init();
 
rmode = VIDEO_GetPreferredMode(NULL);
rmode = VIDEO_GetPreferredMode(NULL);
 
xfb[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
xfb[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
xfb[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
xfb[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
VIDEO_Configure(rmode);
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(xfb);
VIDEO_SetNextFramebuffer(xfb);
Line 113: Line 198:
VIDEO_WaitVSync();
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
 
SYS_SetResetCallback(reload);
SYS_SetResetCallback(reload);
SYS_SetPowerCallback(shutdown);
SYS_SetPowerCallback(shutdown);
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
WPAD_SetVRes(0, rmode->fbWidth, rmode->xfbHeight);
WPAD_SetVRes(0, rmode->fbWidth, rmode->xfbHeight);
while(!doreload && !dooff) {
while(!doreload && !dooff) {
CON_Init(xfb[fbi],0,0,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
CON_Init(xfb[fbi],0,0,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
Line 125: Line 210:
printf("\n\n\n");
printf("\n\n\n");
WPAD_ReadPending(WPAD_CHAN_ALL, countevs);
WPAD_ReadPending(WPAD_CHAN_ALL, countevs);
res = WPAD_Probe(0, &type);
int wiimote_connection_status = WPAD_Probe(0, &type);
switch(res) {
print_wiimote_connection_status(wiimote_connection_status);
case WPAD_ERR_NO_CONTROLLER:
 
printf("  Wiimote not connected\n");
break;
case WPAD_ERR_NOT_READY:
printf("  Wiimote not ready\n");
break;
case WPAD_ERR_NONE:
printf("  Wiimote ready\n");
break;
default:
printf("  Unknown Wimote state %d\n",res);
}
printf("  Event count: %d\n",evctr);
printf("  Event count: %d\n",evctr);
if(res == WPAD_ERR_NONE) {
if(wiimote_connection_status == WPAD_ERR_NONE) {
                        //Makes the var wd point to the data on the wiimote
print_and_draw_wiimote_data(xfb[fbi]);
wd = WPAD_Data(0);
printf("  Data->Err: %d\n",wd->err);
printf("  IR Dots:\n");
for(i=0; i<4; i++) {
if(wd->ir.dot[i].visible) {
printf("  %4d, %3d\n", wd->ir.dot[i].rx, wd->ir.dot[i].ry);
} else {
printf("  None\n");
}
}
                        //ir.valid - TRUE is the wiimote is pointing at the screen, else it is false
if(wd->ir.valid) {
                                //ir.x/ir.y - The x/y coordinates that the wiimote is pointing to, relative to the screen.
                                //ir.angle - how far (in degrees) the wiimote is twisted (based on ir)
printf("  Cursor: %.02f,%.02f\n",wd->ir.x, wd->ir.y);
printf("    @ %.02f deg\n",wd->ir.angle);
} else {
printf("  No Cursor\n\n");
}
if(wd->ir.raw_valid) {
                                //ir.z - How far away the wiimote is from the screen in meters
printf("  Distance: %.02fm\n", wd->ir.z);
                                //orient.yaw - The left/right angle of the wiimote to the screen
printf("  Yaw: %.02f deg\n", wd->orient.yaw);
} else {
printf("\n\n");
}
printf("  Accel:\n");
                        //accel.x/accel.y/accel.z - analog values for the accelleration of the wiimote
                        //(Note: Gravity pulls downwards, so even if the wiimote is not moving,
                        //one(or more) axis will have a reading as if it is moving "upwards")
printf("  XYZ: %3d,%3d,%3d\n",wd->accel.x,wd->accel.y,wd->accel.z);
                        //orient.pitch - how far the wiimote is "tilted" in degrees
printf("  Pitch: %.02f\n",wd->orient.pitch);
                        //orient.roll - how far the wiimote is "twisted" in degrees (uses accelerometer)
printf("  Roll:  %.02f\n",wd->orient.roll);
printf("  Buttons down:\n  ");
                        //btns_h - returns (in a binary sequence) which buttons are being held down
                        //Notice the single "&", compares the two binary numbers, if the "a" slot is 1, then it returns true.
if(wd->btns_h & WPAD_BUTTON_A) printf("A ");
if(wd->btns_h & WPAD_BUTTON_B) printf("B ");
if(wd->btns_h & WPAD_BUTTON_1) printf("1 ");
if(wd->btns_h & WPAD_BUTTON_2) printf("2 ");
if(wd->btns_h & WPAD_BUTTON_MINUS) printf("MINUS ");
if(wd->btns_h & WPAD_BUTTON_HOME) printf("HOME ");
if(wd->btns_h & WPAD_BUTTON_PLUS) printf("PLUS ");
printf("\n  ");
if(wd->btns_h & WPAD_BUTTON_LEFT) printf("LEFT ");
if(wd->btns_h & WPAD_BUTTON_RIGHT) printf("RIGHT ");
if(wd->btns_h & WPAD_BUTTON_UP) printf("UP ");
if(wd->btns_h & WPAD_BUTTON_DOWN) printf("DOWN ");
printf("\n");
for(i=0; i<4; i++) {
if(wd->ir.dot[i].visible) {
drawdot(xfb[fbi], rmode, 1024, 768, wd->ir.dot[i].rx, wd->ir.dot[i].ry, COLOR_YELLOW);
}
}
if(wd->ir.raw_valid) {
for(i=0; i<2; i++) {
drawdot(xfb[fbi], rmode, 4, 4, wd->ir.sensorbar.rot_dots[i].x+2, wd->ir.sensorbar.rot_dots[i].y+2, COLOR_GREEN);
}
}
if(wd->ir.valid) {
theta = wd->ir.angle / 180.0 * 3.1415;
drawdot(xfb[fbi], rmode, rmode->fbWidth, rmode->xfbHeight, wd->ir.x, wd->ir.y, COLOR_RED);
drawdot(xfb[fbi], rmode, rmode->fbWidth, rmode->xfbHeight, wd->ir.x + 10*sinf(theta), wd->ir.y - 10*cosf(theta), COLOR_BLUE);
}
                        //sets flag for you to exit back to the homebrew channel
if(wd->btns_h & WPAD_BUTTON_1) doreload=1;
}
}
VIDEO_SetNextFramebuffer(xfb[fbi]);
VIDEO_SetNextFramebuffer(xfb[fbi]);
Line 220: Line 224:
if(doreload) return 0;
if(doreload) return 0;
if(dooff) SYS_ResetSystem(SYS_SHUTDOWN,0,0);
if(dooff) SYS_ResetSystem(SYS_SHUTDOWN,0,0);
 
return 0;
return 0;
}
}
</source>
</source>


To make this example work, extra libraries must be linked in.  Modify the standard Makefile LIBS line as follows:<br>
To make this example work, extra libraries must be linked in.  Modify the standard Makefile LIBS line as follows:<br>
<code>LIBS := -lwiiuse -lbte -logc</code>
<code>LIBS := -lwiiuse -lbte -logc</code>

Revision as of 15:21, 28 July 2008

Please add comments to the code on this page. If enough higher-ups/WinterMute feel that the uncommented version is not needed, then feel free to have them/him do whatever.

PLEASE help us comment this code.

Only add if you really know what it means, and no obvious comments.

Wrong:

//Declares Integer 'dooff' and sets to Zero"
int doreload=0, dooff=0;


Correct:

//dooff(Do Off) is a flag that tells the program to quit looping and properly shuts down the wii
int dooff=0;


//code by WinterMute
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <gccore.h>
#include <stdarg.h>
#include <ctype.h>
#include <math.h>
#include <wiiuse/wpad.h>
 
static GXRModeObj *rmode = NULL;
 
//-----------------------------------------------------------------------------------
//doreload - a flag that tells the program to quit looping and exit the program to the HBChannel.
//dooff - a flag that tells the program to quit looping and properly shutdown the system.
int doreload=0, dooff=0;
 
//Calling the function will end the while loop and properly exit the program to the HBChannel. 
void reload(void) {
	doreload=1;
}
 
//Calling the function will end the while loop and properly shutdown the system.
void shutdown(void) {
	dooff=1;
}
 
//Draw a square on the screen (May draw rectangles as well, I am uncertain). 
//*xfb - !unsure!
//*rmode - !unsure!
//w - !unsure!
//h -!unsure!
//fx - X coordinate to draw on the screen
//fy - Y coordinate to draw on the screen
//color - the color of the rectangle (Examples: COLOR_YELLOW, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_BLACK, COLOR_WHITE)
void drawdot(void *xfb, GXRModeObj *rmode, float w, float h, float fx, float fy, u32 color) {
 
	//*fb - !unsure!
	//px - !unsure!
	//py - !unsure!
	//x - !unsure!
	//y - !unsure!
 
	u32 *fb;
	int px,py;
	int x,y;
 
 
	fb = (u32*)xfb;
 
	y = fy * rmode->xfbHeight / h;
	x = fx * rmode->fbWidth / w / 2;
 
	for(py=y-4; py<=(y+4); py++) {
		if(py < 0 || py >= rmode->xfbHeight)
				continue;
		for(px=x-2; px<=(x+2); px++) {
			if(px < 0 || px >= rmode->fbWidth/2)
				continue;
			fb[rmode->fbWidth/VI_DISPLAY_PIX_SZ*py + px] = color;
		}
	}
 
}
 
int evctr = 0;
 
void countevs(int chan, const WPADData *data) {
	evctr++;
}

void print_wiimote_connection_status(int wiimote_connection_status) {
	switch(wiimote_connection_status) {
		case WPAD_ERR_NO_CONTROLLER:
			printf("  Wiimote not connected\n");
			break;
		case WPAD_ERR_NOT_READY:
			printf("  Wiimote not ready\n");
			break;
		case WPAD_ERR_NONE:
			printf("  Wiimote ready\n");
			break;
		default:
			printf("  Unknown Wimote state %d\n",wiimote_connection_status);
	}
}

void print_wiimote_buttons(WPADData *wd) {
	printf("  Buttons down:\n   ");
	if(wd->btns_h & WPAD_BUTTON_A) printf("A ");
	if(wd->btns_h & WPAD_BUTTON_B) printf("B ");
	if(wd->btns_h & WPAD_BUTTON_1) printf("1 ");
	if(wd->btns_h & WPAD_BUTTON_2) printf("2 ");
	if(wd->btns_h & WPAD_BUTTON_MINUS) printf("MINUS ");
	if(wd->btns_h & WPAD_BUTTON_HOME) printf("HOME ");
	if(wd->btns_h & WPAD_BUTTON_PLUS) printf("PLUS ");
	printf("\n   ");
	if(wd->btns_h & WPAD_BUTTON_LEFT) printf("LEFT ");
	if(wd->btns_h & WPAD_BUTTON_RIGHT) printf("RIGHT ");
	if(wd->btns_h & WPAD_BUTTON_UP) printf("UP ");
	if(wd->btns_h & WPAD_BUTTON_DOWN) printf("DOWN ");
	printf("\n");
}

void print_and_draw_wiimote_data(void *screen_buffer) {
	//Makes the var wd point to the data on the wiimote
	WPADData *wd = WPAD_Data(0);
	printf("  Data->Err: %d\n",wd->err);
	printf("  IR Dots:\n");
	int i;
	for(i=0; i<4; i++) {
		if(wd->ir.dot[i].visible) {
			printf("   %4d, %3d\n", wd->ir.dot[i].rx, wd->ir.dot[i].ry);
			drawdot(screen_buffer, rmode, 1024, 768, wd->ir.dot[i].rx, wd->ir.dot[i].ry, COLOR_YELLOW);
		} else {
			printf("   None\n");
		}
	}
	//ir.valid - TRUE is the wiimote is pointing at the screen, else it is false
	if(wd->ir.valid) {
		float theta = wd->ir.angle / 180.0 * M_PI;
	
		//ir.x/ir.y - The x/y coordinates that the wiimote is pointing to, relative to the screen.
		//ir.angle - how far (in degrees) the wiimote is twisted (based on ir)
		printf("  Cursor: %.02f,%.02f\n",wd->ir.x, wd->ir.y);
		printf("    @ %.02f deg\n",wd->ir.angle);
		
		drawdot(screen_buffer, rmode, rmode->fbWidth, rmode->xfbHeight, wd->ir.x, wd->ir.y, COLOR_RED);
		drawdot(screen_buffer, rmode, rmode->fbWidth, rmode->xfbHeight, wd->ir.x + 10*sinf(theta), wd->ir.y - 10*cosf(theta), COLOR_BLUE);        
	} else {
		printf("  No Cursor\n\n");
	}
	if(wd->ir.raw_valid) {
		//ir.z - How far away the wiimote is from the screen in meters
		printf("  Distance: %.02fm\n", wd->ir.z);
		//orient.yaw - The left/right angle of the wiimote to the screen 
		printf("  Yaw: %.02f deg\n", wd->orient.yaw);
	} else {
		printf("\n\n");
	}
	printf("  Accel:\n");
	//accel.x/accel.y/accel.z - analog values for the accelleration of the wiimote
	//(Note: Gravity pulls downwards, so even if the wiimote is not moving, 
	//one(or more) axis will have a reading as if it is moving "upwards")
	printf("   XYZ: %3d,%3d,%3d\n",wd->accel.x,wd->accel.y,wd->accel.z);
	//orient.pitch - how far the wiimote is "tilted" in degrees
	printf("   Pitch: %.02f\n",wd->orient.pitch);
	//orient.roll - how far the wiimote is "twisted" in degrees (uses accelerometer)
	printf("   Roll:  %.02f\n",wd->orient.roll);

	print_wiimote_buttons(wd);

	if(wd->ir.raw_valid) {
		for(i=0; i<2; i++) {
			drawdot(screen_buffer, rmode, 4, 4, wd->ir.sensorbar.rot_dots[i].x+2, wd->ir.sensorbar.rot_dots[i].y+2, COLOR_GREEN);
		}
	}

	if(wd->btns_h & WPAD_BUTTON_1) doreload=1;
}
 
int main(int argc, char **argv) {
	void *xfb[2];
	u32 type;
	int fbi = 0;
 
	VIDEO_Init();
	PAD_Init();
	WPAD_Init();
 
	rmode = VIDEO_GetPreferredMode(NULL);
 
	xfb[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
	xfb[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
 
	VIDEO_Configure(rmode);
	VIDEO_SetNextFramebuffer(xfb);
	VIDEO_SetBlack(FALSE);
	VIDEO_Flush();
	VIDEO_WaitVSync();
	if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
 
	SYS_SetResetCallback(reload);
	SYS_SetPowerCallback(shutdown);
 
	WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
	WPAD_SetVRes(0, rmode->fbWidth, rmode->xfbHeight);
 
	while(!doreload && !dooff) {
		CON_Init(xfb[fbi],0,0,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
		//VIDEO_ClearFrameBuffer(rmode,xfb[fbi],COLOR_BLACK);
		printf("\n\n\n");
		WPAD_ReadPending(WPAD_CHAN_ALL, countevs);
		int wiimote_connection_status = WPAD_Probe(0, &type);
		print_wiimote_connection_status(wiimote_connection_status);

		printf("  Event count: %d\n",evctr);
		if(wiimote_connection_status == WPAD_ERR_NONE) {
			print_and_draw_wiimote_data(xfb[fbi]);
		}
		VIDEO_SetNextFramebuffer(xfb[fbi]);
		VIDEO_Flush();
		VIDEO_WaitVSync();
		fbi ^= 1;
	}
	if(doreload) return 0;
	if(dooff) SYS_ResetSystem(SYS_SHUTDOWN,0,0);
 
	return 0;
}

To make this example work, extra libraries must be linked in. Modify the standard Makefile LIBS line as follows:
LIBS := -lwiiuse -lbte -logc