#include <stdio.h>
#include <stdlib.h>
#include <gccore.h>
#include <wiiuse/wpad.h>
#include <wupc/wupc.h>
#include <stdarg.h>
#include <ogc/lwp_watchdog.h>
static void *xfb = NULL;
static GXRModeObj *rmode = NULL;
static int HWButton = -1;
enum HardwareButtons
{
RESET_BUTTON,
POWER_BUTTON
};
enum ProControllerButtons
{
PRO_CTRL_BUTTON_START = 0x04000000,
PRO_CTRL_BUTTON_SELECT = 0x10000000,
PRO_CTRL_BUTTON_HOME = 0x08000000,
PRO_CTRL_BUTTON_A = 0x00100000,
PRO_CTRL_BUTTON_B = 0x00400000,
PRO_CTRL_BUTTON_Y = 0x00200000,
PRO_CTRL_BUTTON_X = 0x00080000,
PRO_CTRL_BUTTON_L = 0x20000000,
PRO_CTRL_BUTTON_R = 0x02000000,
PRO_CTRL_BUTTON_ZL = 0x00800000,
PRO_CTRL_BUTTON_ZR = 0x00040000,
PRO_CTRL_BUTTON_UP = 0x00010000,
PRO_CTRL_BUTTON_DOWN = 0x40000000,
PRO_CTRL_BUTTON_LEFT = 0x00020000,
PRO_CTRL_BUTTON_RIGHT = 0x80000000,
};
void PowerCallback()
{
HWButton = POWER_BUTTON;
}
void ResetCallback()
{
HWButton = RESET_BUTTON;
}
void print_on_row(const int row, const char * const fmt, ...)
{
printf("\x1b[%d;0H", row);
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
int main(int argc, char **argv)
{
// Initialise the video system
VIDEO_Init();
// This function initialises the attached controllers
WUPC_Init();
WPAD_Init();
// Obtain the preferred video mode from the system
// This will correspond to the settings in the Wii menu
rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
// Initialise the console, required for printf
console_init(xfb, 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode
VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb);
// Make the display visible
VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware
VIDEO_Flush();
// Wait for Video setup to complete
VIDEO_WaitVSync();
if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
SYS_SetPowerCallback(PowerCallback);
SYS_SetResetCallback(ResetCallback);
int row = 0;
u32 proControllerButtons = 0;
s16 proControllerLeftStickX = 0;
s16 proControllerLeftStickY = 0;
s16 proControllerRightStickX = 0;
s16 proControllerRightStickY = 0;
bool exitComboPressed = false;
bool rumbling = false;
bool rumble = false;
bool proControllerIsConnected = false;
u32 timeToRumble = 0;
struct WUPCData *proControllerData = NULL;
while (!exitComboPressed)
{
VIDEO_ClearFrameBuffer(rmode, xfb, COLOR_BLACK);
VIDEO_SetBlack(FALSE);
// Call WPAD_ScanPads each loop, this reads the latest controller states
WPAD_ScanPads();
proControllerData = WUPC_Data(0);
if (proControllerData != NULL)
{
proControllerButtons = proControllerData->button;
proControllerLeftStickX = WUPC_lStickX(0);
proControllerLeftStickY = WUPC_lStickY(0);
proControllerRightStickX = WUPC_rStickX(0);
proControllerRightStickY = WUPC_rStickY(0);
proControllerIsConnected = true;
}
else proControllerIsConnected = false;
exitComboPressed = (proControllerButtons & PRO_CTRL_BUTTON_SELECT)
&& (proControllerButtons & PRO_CTRL_BUTTON_START);
row = 3;
print_on_row(++row, "Pro Controller is %s", proControllerIsConnected ? "connected" : "not connected. Please connect it to test it.\nOr press reset or power on your console to exit.");
if (proControllerIsConnected)
{
print_on_row(row, "Press select and start at the same time on your Pro Controller to exit.");
print_on_row(++row, "Press L and R at the same time to test rumble.");
print_on_row(++row, "Raw button status: %08x", proControllerButtons);
print_on_row(++row, "Left Stick X: %d", proControllerLeftStickX);
print_on_row(++row, "Left Stick Y : %d", proControllerLeftStickY);
print_on_row(++row, "Right Stick X: %d", proControllerRightStickX);
print_on_row(++row, "Right Stick Y : %d", proControllerRightStickY);
print_on_row(++row, "Select is: %s", proControllerButtons & PRO_CTRL_BUTTON_SELECT ? "pressed" : "not pressed");
print_on_row(++row, "Start is: %s", proControllerButtons & PRO_CTRL_BUTTON_START ? "pressed" : "not pressed");
print_on_row(++row, "Home is: %s", proControllerButtons & PRO_CTRL_BUTTON_HOME ? "pressed" : "not pressed");
print_on_row(++row, "A is: %s", proControllerButtons & PRO_CTRL_BUTTON_A ? "pressed" : "not pressed");
print_on_row(++row, "B is: %s", proControllerButtons & PRO_CTRL_BUTTON_B ? "pressed" : "not pressed");
print_on_row(++row, "Y is: %s", proControllerButtons & PRO_CTRL_BUTTON_Y ? "pressed" : "not pressed");
print_on_row(++row, "X is: %s", proControllerButtons & PRO_CTRL_BUTTON_X ? "pressed" : "not pressed");
print_on_row(++row, "L is: %s", proControllerButtons & PRO_CTRL_BUTTON_L ? "pressed" : "not pressed");
print_on_row(++row, "R is: %s", proControllerButtons & PRO_CTRL_BUTTON_R ? "pressed" : "not pressed");
print_on_row(++row, "ZL is: %s", proControllerButtons & PRO_CTRL_BUTTON_ZL ? "pressed" : "not pressed");
print_on_row(++row, "ZR is: %s", proControllerButtons & PRO_CTRL_BUTTON_ZR ? "pressed" : "not pressed");
print_on_row(++row, "Up is: %s", proControllerButtons & PRO_CTRL_BUTTON_UP ? "pressed" : "not pressed");
print_on_row(++row, "Down is: %s", proControllerButtons & PRO_CTRL_BUTTON_DOWN ? "pressed" : "not pressed");
print_on_row(++row, "Left is: %s", proControllerButtons & PRO_CTRL_BUTTON_LEFT ? "pressed" : "not pressed");
print_on_row(++row, "Right is: %s", proControllerButtons & PRO_CTRL_BUTTON_RIGHT ? "pressed" : "not pressed");
rumble = (proControllerButtons & PRO_CTRL_BUTTON_L)
&& (proControllerButtons & PRO_CTRL_BUTTON_R);
if (rumble)
{
if (!rumbling)
{
rumbling = true;
timeToRumble = ticks_to_millisecs(gettime());
WUPC_Rumble(0, true);
}
}
// Stop rumbling after 250ms.
if (ticks_to_millisecs(gettime()) > timeToRumble + 250 && rumbling)
{
WUPC_Rumble(0, false);
rumbling = false;
}
}
if (HWButton == POWER_BUTTON)
SYS_ResetSystem(SYS_POWEROFF_STANDBY, 0, 0);
if (HWButton == RESET_BUTTON)
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
// Wait for the next frame
VIDEO_WaitVSync();
}
WUPC_Shutdown();
WPAD_Shutdown();
exit(0);
return 0;
}