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

How to use the Wiimote (Commented)

From WiiBrew
Jump to navigation Jump to search

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

int main(int argc, char **argv) {
	int res;
	
	void *xfb[2];
	u32 type;
	int i;
	int fbi = 0;
	float theta;
	WPADData *wd;
	
	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);
		res = WPAD_Probe(0, &type);
		switch(res) {
			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);
		if(res == WPAD_ERR_NONE) {
                        //Makes the var wd point to the data on the wiimote
			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_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