mirror of
https://github.com/libretro/RetroArch.git
synced 2025-02-03 07:22:15 +00:00
(Wii) Add customized Wiiuse - should reduce overall input latency
(also debloats - no Guitar Hero 3/Wii Board/key down/key up)
This commit is contained in:
parent
1221b024cb
commit
5ee38b157d
@ -30,13 +30,13 @@ ELF2DOL = $(DEVKITPPC)/bin/elf2dol$(EXE_EXT)
|
||||
DOL_TARGET := retroarch_wii.dol
|
||||
ELF_TARGET := retroarch_wii.elf
|
||||
|
||||
INCLUDE := -I. -I$(DEVKITPRO)/libogc/include
|
||||
INCLUDE := -I. -I$(DEVKITPRO)/libogc/include -I$(DEVKITPRO)/libogc/include/ogc
|
||||
LIBDIRS := -L$(DEVKITPRO)/libogc/lib/wii -L.
|
||||
|
||||
MACHDEP := -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float
|
||||
CFLAGS += -Wall -std=gnu99 $(MACHDEP) $(INCLUDE)
|
||||
LDFLAGS := $(MACHDEP) -Wl,-Map,$(notdir $(ELF_TARGET)).map,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,strdup,-wrap,strndup,-wrap,malloc_usable_size -T gx/ld/rvl.ld
|
||||
LIBS := -lfat -lretro_wii -lwiiuse -logc -lbte
|
||||
LIBS := -lfat -lretro_wii -logc -lbte
|
||||
|
||||
APP_BOOTER_DIR = wii/app_booter
|
||||
|
||||
@ -57,7 +57,7 @@ CFLAGS += -DHAVE_FILE_LOGGER
|
||||
CFLAGS += -Iconsole/logger
|
||||
endif
|
||||
|
||||
CFLAGS += -std=gnu99 -DHAVE_DEFAULT_RETROPAD_INPUT -DHAVE_RGUI -DHAVE_THREAD -DRARCH_CONSOLE -DHAVE_LIBRETRO_MANAGEMENT -DHAVE_RARCH_EXEC -DHAVE_RMENU -DGEKKO -DHAVE_ZLIB -DWANT_RZLIB -DHAVE_RARCH_MAIN_WRAP -DHAVE_GRIFFIN=1 -DHAVE_SCREENSHOTS -DPACKAGE_VERSION=\"0.9.8-beta3\" -Dmain=rarch_main -Wno-char-subscripts
|
||||
CFLAGS += -std=gnu99 -DHAVE_DEFAULT_RETROPAD_INPUT -DHAVE_WIIUSE -DHAVE_RGUI -DHAVE_THREAD -DRARCH_CONSOLE -DHAVE_LIBRETRO_MANAGEMENT -DHAVE_RARCH_EXEC -DHAVE_RMENU -DGEKKO -DHAVE_ZLIB -DWANT_RZLIB -DHAVE_RARCH_MAIN_WRAP -DHAVE_GRIFFIN=1 -DHAVE_SCREENSHOTS -DPACKAGE_VERSION=\"0.9.8-beta3\" -Dmain=rarch_main -Wno-char-subscripts
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -O0 -g -DDEBUG
|
||||
|
@ -227,6 +227,20 @@ INPUT
|
||||
#include "../../input/overlay.c"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WIIUSE
|
||||
#include "../../wii/wiiuse/classic.c"
|
||||
#include "../../wii/wiiuse/dynamics.c"
|
||||
#include "../../wii/wiiuse/events.c"
|
||||
#include "../../wii/wiiuse/io.c"
|
||||
#include "../../wii/wiiuse/io_wii.c"
|
||||
#include "../../wii/wiiuse/ir.c"
|
||||
#include "../../wii/wiiuse/motion_plus.c"
|
||||
#include "../../wii/wiiuse/nunchuk.c"
|
||||
#include "../../wii/wiiuse/speaker.c"
|
||||
#include "../../wii/wiiuse/wiiuse.c"
|
||||
#include "../../wii/wiiuse/wpad.c"
|
||||
#endif
|
||||
|
||||
#if defined(__CELLOS_LV2__)
|
||||
#include "../../ps3/ps3_input.c"
|
||||
#elif defined(SN_TARGET_PSP2) || defined(PSP)
|
||||
|
194
wii/wiiuse/classic.c
Normal file
194
wii/wiiuse/classic.c
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This file is part of wiiuse.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/classic.c,v 1.7 2008-11-14 13:34:57 shagkur Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Classic controller expansion device.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "dynamics.h"
|
||||
#include "events.h"
|
||||
#include "classic.h"
|
||||
#include "io.h"
|
||||
|
||||
static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now);
|
||||
|
||||
/**
|
||||
* @brief Handle the handshake data from the classic controller.
|
||||
*
|
||||
* @param cc A pointer to a classic_ctrl_t structure.
|
||||
* @param data The data read in from the device.
|
||||
* @param len The length of the data block, in bytes.
|
||||
*
|
||||
* @return Returns 1 if handshake was successful, 0 if not.
|
||||
*/
|
||||
int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, ubyte* data, uword len) {
|
||||
//int i;
|
||||
int offset = 0;
|
||||
|
||||
cc->btns = 0;
|
||||
cc->btns_held = 0;
|
||||
cc->btns_released = 0;
|
||||
|
||||
/* decrypt data */
|
||||
/*
|
||||
for (i = 0; i < len; ++i)
|
||||
data[i] = (data[i] ^ 0x17) + 0x17;
|
||||
*/
|
||||
if (data[offset] == 0xFF) {
|
||||
/*
|
||||
* Sometimes the data returned here is not correct.
|
||||
* This might happen because the wiimote is lagging
|
||||
* behind our initialization sequence.
|
||||
* To fix this just request the handshake again.
|
||||
*
|
||||
* Other times it's just the first 16 bytes are 0xFF,
|
||||
* but since the next 16 bytes are the same, just use
|
||||
* those.
|
||||
*/
|
||||
if (data[offset + 16] == 0xFF) {
|
||||
/* get the calibration data again */
|
||||
//WIIUSE_DEBUG("Classic controller handshake appears invalid, trying again.");
|
||||
wiiuse_read_data(wm, data, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN, wiiuse_handshake_expansion);
|
||||
} else
|
||||
offset += 16;
|
||||
}
|
||||
|
||||
|
||||
/* joystick stuff */
|
||||
cc->ljs.max.x = data[0 + offset] / 4 == 0 ? 64 : data[0 + offset] / 4;
|
||||
cc->ljs.min.x = data[1 + offset] / 4;
|
||||
cc->ljs.center.x = data[2 + offset] / 4 == 0 ? 32 : data[2 + offset] / 4;
|
||||
cc->ljs.max.y = data[3 + offset] / 4 == 0 ? 64 : data[3 + offset] / 4;
|
||||
cc->ljs.min.y = data[4 + offset] / 4;
|
||||
cc->ljs.center.y = data[5 + offset] / 4 == 0 ? 32 : data[5 + offset] / 4;
|
||||
|
||||
cc->rjs.max.x = data[6 + offset] / 8 == 0 ? 32 : data[6 + offset] / 8;
|
||||
cc->rjs.min.x = data[7 + offset] / 8;
|
||||
cc->rjs.center.x = data[8 + offset] / 8 == 0 ? 16 : data[8 + offset] / 8;
|
||||
cc->rjs.max.y = data[9 + offset] / 8 == 0 ? 32 : data[9 + offset] / 8;
|
||||
cc->rjs.min.y = data[10 + offset] / 8;
|
||||
cc->rjs.center.y = data[11 + offset] / 8 == 0 ? 16 : data[11 + offset] / 8;
|
||||
|
||||
/* handshake done */
|
||||
wm->event = WIIUSE_CLASSIC_CTRL_INSERTED;
|
||||
wm->exp.type = EXP_CLASSIC;
|
||||
|
||||
#ifdef WIN32
|
||||
wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The classic controller disconnected.
|
||||
*
|
||||
* @param cc A pointer to a classic_ctrl_t structure.
|
||||
*/
|
||||
void classic_ctrl_disconnected(struct classic_ctrl_t* cc)
|
||||
{
|
||||
memset(cc, 0, sizeof(struct classic_ctrl_t));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle classic controller event.
|
||||
*
|
||||
* @param cc A pointer to a classic_ctrl_t structure.
|
||||
* @param msg The message specified in the event packet.
|
||||
*/
|
||||
void classic_ctrl_event(struct classic_ctrl_t* cc, ubyte* msg) {
|
||||
//int i;
|
||||
|
||||
/* decrypt data */
|
||||
/*
|
||||
for (i = 0; i < 6; ++i)
|
||||
msg[i] = (msg[i] ^ 0x17) + 0x17;
|
||||
*/
|
||||
classic_ctrl_pressed_buttons(cc, BIG_ENDIAN_SHORT(*(short*)(msg + 4)));
|
||||
|
||||
/* left/right buttons */
|
||||
cc->ls_raw = (((msg[2] & 0x60) >> 2) | ((msg[3] & 0xE0) >> 5));
|
||||
cc->rs_raw = (msg[3] & 0x1F);
|
||||
|
||||
/*
|
||||
* TODO - LR range hardcoded from 0x00 to 0x1F.
|
||||
* This is probably in the calibration somewhere.
|
||||
*/
|
||||
#ifndef GEKKO
|
||||
cc->r_shoulder = ((float)r / 0x1F);
|
||||
cc->l_shoulder = ((float)l / 0x1F);
|
||||
#endif
|
||||
/* calculate joystick orientation */
|
||||
cc->ljs.pos.x = (msg[0] & 0x3F);
|
||||
cc->ljs.pos.y = (msg[1] & 0x3F);
|
||||
cc->rjs.pos.x = ((msg[0] & 0xC0) >> 3) | ((msg[1] & 0xC0) >> 5) | ((msg[2] & 0x80) >> 7);
|
||||
cc->rjs.pos.y = (msg[2] & 0x1F);
|
||||
#ifndef GEKKO
|
||||
calc_joystick_state(&cc->ljs, cc->ljs.pos.x, cc->ljs.pos.y);
|
||||
calc_joystick_state(&cc->rjs, cc->rjs.pos.x, cc->rjs.pos.y);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Find what buttons are pressed.
|
||||
*
|
||||
* @param cc A pointer to a classic_ctrl_t structure.
|
||||
* @param msg The message byte specified in the event packet.
|
||||
*/
|
||||
static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now) {
|
||||
/* message is inverted (0 is active, 1 is inactive) */
|
||||
now = ~now & CLASSIC_CTRL_BUTTON_ALL;
|
||||
|
||||
/* preserve old btns pressed */
|
||||
cc->btns_last = cc->btns;
|
||||
|
||||
/* pressed now & were pressed, then held */
|
||||
cc->btns_held = (now & cc->btns);
|
||||
|
||||
/* were pressed or were held & not pressed now, then released */
|
||||
cc->btns_released = ((cc->btns | cc->btns_held) & ~now);
|
||||
|
||||
/* buttons pressed now */
|
||||
cc->btns = now;
|
||||
}
|
53
wii/wiiuse/classic.h
Normal file
53
wii/wiiuse/classic.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This file is part of wiiuse.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/classic.h,v 1.1 2008-05-08 09:42:14 shagkur Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Classic controller expansion device.
|
||||
*/
|
||||
|
||||
#ifndef CLASSIC_H_INCLUDED
|
||||
#define CLASSIC_H_INCLUDED
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, ubyte* data, uword len);
|
||||
|
||||
void classic_ctrl_disconnected(struct classic_ctrl_t* cc);
|
||||
|
||||
void classic_ctrl_event(struct classic_ctrl_t* cc, ubyte* msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CLASSIC_H_INCLUDED
|
55
wii/wiiuse/definitions.h
Normal file
55
wii/wiiuse/definitions.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef __DEFINITIONS_H__
|
||||
#define __DEFINITIONS_H__
|
||||
|
||||
#include "os.h"
|
||||
|
||||
#define WIIMOTE_PI 3.14159265f
|
||||
|
||||
//#define WITH_WIIUSE_DEBUG
|
||||
|
||||
/* Error output macros */
|
||||
#define WIIUSE_ERROR(fmt, ...) fprintf(stderr, "[ERROR] " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
/* Warning output macros */
|
||||
#define WIIUSE_WARNING(fmt, ...) fprintf(stderr, "[WARNING] " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
/* Information output macros */
|
||||
#define WIIUSE_INFO(fmt, ...) fprintf(stderr, "[INFO] " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
#ifdef WITH_WIIUSE_DEBUG
|
||||
#ifdef WIN32
|
||||
#define WIIUSE_DEBUG(fmt, ...) do { \
|
||||
char* file = __FILE__; \
|
||||
int i = strlen(file) - 1; \
|
||||
for (; i && (file[i] != '\\'); --i); \
|
||||
fprintf(stderr, "[DEBUG] %s:%i: " fmt "\n", file+i+1, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define WIIUSE_DEBUG(fmt, ...) fprintf(stderr, "[DEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__)
|
||||
#endif
|
||||
#else
|
||||
#define WIIUSE_DEBUG(fmt, ...)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define WII_DEBUG(fmt, ...) do { \
|
||||
printf("[WDEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__); \
|
||||
usleep(3000000); \
|
||||
} while (0)
|
||||
#else
|
||||
#define WII_DEBUG(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
/* Convert between radians and degrees */
|
||||
#define RAD_TO_DEGREE(r) ((r * 180.0f) / WIIMOTE_PI)
|
||||
#define DEGREE_TO_RAD(d) (d * (WIIMOTE_PI / 180.0f))
|
||||
|
||||
/* Convert to big endian */
|
||||
#define BIG_ENDIAN_LONG(i) (htonl(i))
|
||||
#define BIG_ENDIAN_SHORT(i) (htons(i))
|
||||
|
||||
#define absf(x) ((x >= 0) ? (x) : (x * -1.0f))
|
||||
#define diff_f(x, y) ((x >= y) ? (absf(x - y)) : (absf(y - x)))
|
||||
|
||||
#endif
|
230
wii/wiiuse/dynamics.c
Normal file
230
wii/wiiuse/dynamics.c
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This file is part of wiiuse.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/dynamics.c,v 1.2 2008-11-14 13:34:57 shagkur Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Handles the dynamics of the wiimote.
|
||||
*
|
||||
* The file includes functions that handle the dynamics
|
||||
* of the wiimote. Such dynamics include orientation and
|
||||
* motion sensing.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <float.h>
|
||||
#endif
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "ir.h"
|
||||
#include "dynamics.h"
|
||||
|
||||
/**
|
||||
* @brief Calculate the roll, pitch, yaw.
|
||||
*
|
||||
* @param ac An accelerometer (accel_t) structure.
|
||||
* @param accel [in] Pointer to a vec3w_t structure that holds the raw acceleration data.
|
||||
* @param orient [out] Pointer to a orient_t structure that will hold the orientation data.
|
||||
* @param rorient [out] Pointer to a orient_t structure that will hold the non-smoothed orientation data.
|
||||
* @param smooth If smoothing should be performed on the angles calculated. 1 to enable, 0 to disable.
|
||||
*
|
||||
* Given the raw acceleration data from the accelerometer struct, calculate
|
||||
* the orientation of the device and set it in the \a orient parameter.
|
||||
*/
|
||||
void calculate_orientation(struct accel_t* ac, struct vec3w_t* accel, struct orient_t* orient, int smooth) {
|
||||
float xg, yg, zg;
|
||||
float x, y, z;
|
||||
|
||||
/*
|
||||
* roll - use atan(z / x) [ ranges from -180 to 180 ]
|
||||
* pitch - use atan(z / y) [ ranges from -180 to 180 ]
|
||||
* yaw - impossible to tell without IR
|
||||
*/
|
||||
|
||||
/* yaw - set to 0, IR will take care of it if it's enabled */
|
||||
orient->yaw = 0.0f;
|
||||
|
||||
/* find out how much it has to move to be 1g */
|
||||
xg = (float)ac->cal_g.x;
|
||||
yg = (float)ac->cal_g.y;
|
||||
zg = (float)ac->cal_g.z;
|
||||
|
||||
/* find out how much it actually moved and normalize to +/- 1g */
|
||||
x = ((float)accel->x - (float)ac->cal_zero.x) / xg;
|
||||
y = ((float)accel->y - (float)ac->cal_zero.y) / yg;
|
||||
z = ((float)accel->z - (float)ac->cal_zero.z) / zg;
|
||||
|
||||
/* make sure x,y,z are between -1 and 1 for the tan functions */
|
||||
if (x < -1.0f) x = -1.0f;
|
||||
else if (x > 1.0f) x = 1.0f;
|
||||
if (y < -1.0f) y = -1.0f;
|
||||
else if (y > 1.0f) y = 1.0f;
|
||||
if (z < -1.0f) z = -1.0f;
|
||||
else if (z > 1.0f) z = 1.0f;
|
||||
|
||||
/* if it is over 1g then it is probably accelerating and not reliable */
|
||||
if (abs(accel->x - ac->cal_zero.x) <= (ac->cal_g.x+10)) {
|
||||
/* roll */
|
||||
x = RAD_TO_DEGREE(atan2f(x, z));
|
||||
if(isfinite(x)) {
|
||||
orient->roll = x;
|
||||
orient->a_roll = x;
|
||||
}
|
||||
}
|
||||
|
||||
if (abs(accel->y - ac->cal_zero.y) <= (ac->cal_g.y+10)) {
|
||||
/* pitch */
|
||||
y = RAD_TO_DEGREE(atan2f(y, z));
|
||||
if(isfinite(y)) {
|
||||
orient->pitch = y;
|
||||
orient->a_pitch = y;
|
||||
}
|
||||
}
|
||||
|
||||
/* smooth the angles if enabled */
|
||||
if (smooth) {
|
||||
apply_smoothing(ac, orient, SMOOTH_ROLL);
|
||||
apply_smoothing(ac, orient, SMOOTH_PITCH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calculate the gravity forces on each axis.
|
||||
*
|
||||
* @param ac An accelerometer (accel_t) structure.
|
||||
* @param accel [in] Pointer to a vec3w_t structure that holds the raw acceleration data.
|
||||
* @param gforce [out] Pointer to a gforce_t structure that will hold the gravity force data.
|
||||
*/
|
||||
void calculate_gforce(struct accel_t* ac, struct vec3w_t* accel, struct gforce_t* gforce) {
|
||||
float xg, yg, zg;
|
||||
|
||||
/* find out how much it has to move to be 1g */
|
||||
xg = (float)ac->cal_g.x;
|
||||
yg = (float)ac->cal_g.y;
|
||||
zg = (float)ac->cal_g.z;
|
||||
|
||||
/* find out how much it actually moved and normalize to +/- 1g */
|
||||
gforce->x = ((float)accel->x - (float)ac->cal_zero.x) / xg;
|
||||
gforce->y = ((float)accel->y - (float)ac->cal_zero.y) / yg;
|
||||
gforce->z = ((float)accel->z - (float)ac->cal_zero.z) / zg;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calculate the angle and magnitude of a joystick.
|
||||
*
|
||||
* @param js [out] Pointer to a joystick_t structure.
|
||||
* @param x The raw x-axis value.
|
||||
* @param y The raw y-axis value.
|
||||
*/
|
||||
void calc_joystick_state(struct joystick_t* js, float x, float y) {
|
||||
float rx, ry, ang;
|
||||
|
||||
/*
|
||||
* Since the joystick center may not be exactly:
|
||||
* (min + max) / 2
|
||||
* Then the range from the min to the center and the center to the max
|
||||
* may be different.
|
||||
* Because of this, depending on if the current x or y value is greater
|
||||
* or less than the assoicated axis center value, it needs to be interpolated
|
||||
* between the center and the minimum or maxmimum rather than between
|
||||
* the minimum and maximum.
|
||||
*
|
||||
* So we have something like this:
|
||||
* (x min) [-1] ---------*------ [0] (x center) [0] -------- [1] (x max)
|
||||
* Where the * is the current x value.
|
||||
* The range is therefore -1 to 1, 0 being the exact center rather than
|
||||
* the middle of min and max.
|
||||
*/
|
||||
if (x == js->center.x)
|
||||
rx = 0;
|
||||
else if (x >= js->center.x)
|
||||
rx = ((float)(x - js->center.x) / (float)(js->max.x - js->center.x));
|
||||
else
|
||||
rx = ((float)(x - js->min.x) / (float)(js->center.x - js->min.x)) - 1.0f;
|
||||
|
||||
if (y == js->center.y)
|
||||
ry = 0;
|
||||
else if (y >= js->center.y)
|
||||
ry = ((float)(y - js->center.y) / (float)(js->max.y - js->center.y));
|
||||
else
|
||||
ry = ((float)(y - js->min.y) / (float)(js->center.y - js->min.y)) - 1.0f;
|
||||
|
||||
/* calculate the joystick angle and magnitude */
|
||||
ang = RAD_TO_DEGREE(atanf(ry / rx));
|
||||
ang -= 90.0f;
|
||||
if (rx < 0.0f)
|
||||
ang -= 180.0f;
|
||||
js->ang = absf(ang);
|
||||
js->mag = (float) sqrt((rx * rx) + (ry * ry));
|
||||
}
|
||||
|
||||
|
||||
void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type) {
|
||||
switch (type) {
|
||||
case SMOOTH_ROLL:
|
||||
{
|
||||
/* it's possible last iteration was nan or inf, so set it to 0 if that happened */
|
||||
if (isnan(ac->st_roll) || isinf(ac->st_roll))
|
||||
ac->st_roll = 0.0f;
|
||||
|
||||
/*
|
||||
* If the sign changes (which will happen if going from -180 to 180)
|
||||
* or from (-1 to 1) then don't smooth, just use the new angle.
|
||||
*/
|
||||
if (((ac->st_roll < 0) && (orient->roll > 0)) || ((ac->st_roll > 0) && (orient->roll < 0))) {
|
||||
ac->st_roll = orient->roll;
|
||||
} else {
|
||||
orient->roll = ac->st_roll + (ac->st_alpha * (orient->a_roll - ac->st_roll));
|
||||
ac->st_roll = orient->roll;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case SMOOTH_PITCH:
|
||||
{
|
||||
if (isnan(ac->st_pitch) || isinf(ac->st_pitch))
|
||||
ac->st_pitch = 0.0f;
|
||||
|
||||
if (((ac->st_pitch < 0) && (orient->pitch > 0)) || ((ac->st_pitch > 0) && (orient->pitch < 0))) {
|
||||
ac->st_pitch = orient->pitch;
|
||||
} else {
|
||||
orient->pitch = ac->st_pitch + (ac->st_alpha * (orient->a_pitch - ac->st_pitch));
|
||||
ac->st_pitch = orient->pitch;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
56
wii/wiiuse/dynamics.h
Normal file
56
wii/wiiuse/dynamics.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This file is part of wiiuse.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/dynamics.h,v 1.2 2008-11-14 13:34:57 shagkur Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Handles the dynamics of the wiimote.
|
||||
*
|
||||
* The file includes functions that handle the dynamics
|
||||
* of the wiimote. Such dynamics include orientation and
|
||||
* motion sensing.
|
||||
*/
|
||||
|
||||
#ifndef DYNAMICS_H_INCLUDED
|
||||
#define DYNAMICS_H_INCLUDED
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void calculate_orientation(struct accel_t* ac, struct vec3w_t* accel, struct orient_t* orient, int smooth);
|
||||
void calculate_gforce(struct accel_t* ac, struct vec3w_t* accel, struct gforce_t* gforce);
|
||||
void calc_joystick_state(struct joystick_t* js, float x, float y);
|
||||
void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // DYNAMICS_H_INCLUDED
|
331
wii/wiiuse/events.c
Normal file
331
wii/wiiuse/events.c
Normal file
@ -0,0 +1,331 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dynamics.h"
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "events.h"
|
||||
#include "nunchuk.h"
|
||||
#include "classic.h"
|
||||
#include "motion_plus.h"
|
||||
#include "ir.h"
|
||||
#include "io.h"
|
||||
|
||||
|
||||
static void event_data_read(struct wiimote_t *wm,ubyte *msg)
|
||||
{
|
||||
ubyte err;
|
||||
ubyte len;
|
||||
uword offset;
|
||||
struct op_t *op;
|
||||
struct cmd_blk_t *cmd = wm->cmd_head;
|
||||
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
|
||||
if(!cmd) return;
|
||||
if(!(cmd->state==CMD_SENT && cmd->data[0]==WM_CMD_READ_DATA)) return;
|
||||
|
||||
//printf("event_data_read(%p)\n",cmd);
|
||||
|
||||
err = msg[2]&0x0f;
|
||||
op = (struct op_t*)cmd->data;
|
||||
if(err) {
|
||||
wm->cmd_head = cmd->next;
|
||||
|
||||
cmd->state = CMD_DONE;
|
||||
if(cmd->cb!=NULL) cmd->cb(wm,op->buffer,(op->readdata.size - op->wait));
|
||||
|
||||
__lwp_queue_append(&wm->cmdq,&cmd->node);
|
||||
wiiuse_send_next_command(wm);
|
||||
return;
|
||||
}
|
||||
|
||||
len = ((msg[2]&0xf0)>>4)+1;
|
||||
offset = BIG_ENDIAN_SHORT(*(uword*)(msg+3));
|
||||
|
||||
//printf("addr: %08x\noffset: %d\nlen: %d\n",req->addr,offset,len);
|
||||
|
||||
op->readdata.addr = (op->readdata.addr&0xffff);
|
||||
op->wait -= len;
|
||||
if(op->wait>=op->readdata.size) op->wait = 0;
|
||||
|
||||
memcpy((op->buffer+offset-op->readdata.addr),(msg+5),len);
|
||||
if(!op->wait) {
|
||||
wm->cmd_head = cmd->next;
|
||||
|
||||
wm->event = WIIUSE_READ_DATA;
|
||||
cmd->state = CMD_DONE;
|
||||
if(cmd->cb!=NULL) cmd->cb(wm,op->buffer,op->readdata.size);
|
||||
|
||||
__lwp_queue_append(&wm->cmdq,&cmd->node);
|
||||
wiiuse_send_next_command(wm);
|
||||
}
|
||||
}
|
||||
|
||||
static void event_ack(struct wiimote_t *wm,ubyte *msg)
|
||||
{
|
||||
struct cmd_blk_t *cmd = wm->cmd_head;
|
||||
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
|
||||
if(!cmd || cmd->state!=CMD_SENT || cmd->data[0]==WM_CMD_READ_DATA || cmd->data[0]==WM_CMD_CTRL_STATUS || cmd->data[0]!=msg[2]) {
|
||||
//WIIUSE_WARNING("Unsolicited event ack: report %02x status %02x", msg[2], msg[3]);
|
||||
return;
|
||||
}
|
||||
if(msg[3]) {
|
||||
//WIIUSE_WARNING("Command %02x %02x failed: status %02x", cmd->data[0], cmd->data[1], msg[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
//WIIUSE_DEBUG("Received ack for command %02x %02x", cmd->data[0], cmd->data[1]);
|
||||
|
||||
wm->cmd_head = cmd->next;
|
||||
|
||||
wm->event = WIIUSE_ACK;
|
||||
cmd->state = CMD_DONE;
|
||||
if(cmd->cb) cmd->cb(wm,NULL,0);
|
||||
|
||||
__lwp_queue_append(&wm->cmdq,&cmd->node);
|
||||
wiiuse_send_next_command(wm);
|
||||
}
|
||||
|
||||
static void event_status(struct wiimote_t *wm,ubyte *msg)
|
||||
{
|
||||
int ir = 0;
|
||||
int attachment = 0;
|
||||
int speaker = 0;
|
||||
//int led[4]= {0};
|
||||
struct cmd_blk_t *cmd = wm->cmd_head;
|
||||
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
|
||||
wm->event = WIIUSE_STATUS;
|
||||
//if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_1) led[0] = 1;
|
||||
//if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_2) led[1] = 1;
|
||||
//if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_3) led[2] = 1;
|
||||
//if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_4) led[3] = 1;
|
||||
|
||||
if((msg[2]&WM_CTRL_STATUS_BYTE1_ATTACHMENT)==WM_CTRL_STATUS_BYTE1_ATTACHMENT) attachment = 1;
|
||||
if((msg[2]&WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED)==WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED) speaker = 1;
|
||||
if((msg[2]&WM_CTRL_STATUS_BYTE1_IR_ENABLED)==WM_CTRL_STATUS_BYTE1_IR_ENABLED) ir = 1;
|
||||
|
||||
wm->battery_level = msg[5];
|
||||
|
||||
if(!ir && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR_INIT)) {
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR_INIT);
|
||||
wiiuse_set_ir(wm, 1);
|
||||
goto done;
|
||||
}
|
||||
if(ir && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR)) WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_IR);
|
||||
else if(!ir && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR)) WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
|
||||
|
||||
if(!speaker && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER_INIT)) {
|
||||
WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_SPEAKER_INIT);
|
||||
wiiuse_set_speaker(wm,1);
|
||||
goto done;
|
||||
}
|
||||
if(speaker && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER)) WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_SPEAKER);
|
||||
else if(!speaker && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER)) WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_SPEAKER);
|
||||
|
||||
if(attachment) {
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP) && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_FAILED) && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_HANDSHAKE)) {
|
||||
wiiuse_handshake_expansion_start(wm);
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_EXP_FAILED);
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP)) {
|
||||
wiiuse_disable_expansion(wm);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
wiiuse_set_report_type(wm,NULL);
|
||||
|
||||
done:
|
||||
if(!cmd) return;
|
||||
if(!(cmd->state==CMD_SENT && cmd->data[0]==WM_CMD_CTRL_STATUS)) return;
|
||||
|
||||
wm->cmd_head = cmd->next;
|
||||
|
||||
cmd->state = CMD_DONE;
|
||||
if(cmd->cb!=NULL) cmd->cb(wm,msg,6);
|
||||
|
||||
__lwp_queue_append(&wm->cmdq,&cmd->node);
|
||||
wiiuse_send_next_command(wm);
|
||||
}
|
||||
|
||||
static void handle_expansion(struct wiimote_t *wm,ubyte *msg)
|
||||
{
|
||||
switch (wm->exp.type) {
|
||||
case EXP_NUNCHUK:
|
||||
nunchuk_event(&wm->exp.nunchuk, msg);
|
||||
break;
|
||||
case EXP_CLASSIC:
|
||||
classic_ctrl_event(&wm->exp.classic, msg);
|
||||
break;
|
||||
case EXP_MOTION_PLUS:
|
||||
motion_plus_event(&wm->exp.mp, msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called on a cycle where no significant change occurs.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
*/
|
||||
void idle_cycle(struct wiimote_t* wm)
|
||||
{
|
||||
/*
|
||||
* Smooth the angles.
|
||||
*
|
||||
* This is done to make sure that on every cycle the orientation
|
||||
* angles are smoothed. Normally when an event occurs the angles
|
||||
* are updated and smoothed, but if no packet comes in then the
|
||||
* angles remain the same. This means the angle wiiuse reports
|
||||
* is still an old value. Smoothing needs to be applied in this
|
||||
* case in order for the angle it reports to converge to the true
|
||||
* angle of the device.
|
||||
*/
|
||||
//printf("idle_cycle()\n");///
|
||||
if (WIIUSE_USING_ACC(wm) && WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)) {
|
||||
apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_ROLL);
|
||||
apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_PITCH);
|
||||
}
|
||||
}
|
||||
|
||||
void parse_event(struct wiimote_t *wm)
|
||||
{
|
||||
ubyte event;
|
||||
ubyte *msg;
|
||||
|
||||
event = wm->event_buf[0];
|
||||
msg = wm->event_buf+1;
|
||||
//printf("parse_event(%02x,%p)\n",event,msg);
|
||||
switch(event) {
|
||||
case WM_RPT_CTRL_STATUS:
|
||||
event_status(wm,msg);
|
||||
return;
|
||||
case WM_RPT_READ:
|
||||
event_data_read(wm,msg);
|
||||
return;
|
||||
case WM_RPT_ACK:
|
||||
event_ack(wm,msg);
|
||||
return;
|
||||
case WM_RPT_BTN:
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
break;
|
||||
case WM_RPT_BTN_ACC:
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
|
||||
wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
|
||||
wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
|
||||
wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
|
||||
#ifndef GEKKO
|
||||
/* calculate the remote orientation */
|
||||
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||
|
||||
/* calculate the gforces on each axis */
|
||||
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||
#endif
|
||||
break;
|
||||
case WM_RPT_BTN_ACC_IR:
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
|
||||
wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
|
||||
wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
|
||||
wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
|
||||
#ifndef GEKKO
|
||||
/* calculate the remote orientation */
|
||||
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||
|
||||
/* calculate the gforces on each axis */
|
||||
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||
#endif
|
||||
calculate_extended_ir(wm, msg+5);
|
||||
break;
|
||||
case WM_RPT_BTN_EXP:
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
handle_expansion(wm,msg+2);
|
||||
break;
|
||||
case WM_RPT_BTN_ACC_EXP:
|
||||
/* button - motion - expansion */
|
||||
wiiuse_pressed_buttons(wm, msg);
|
||||
|
||||
wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
|
||||
wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
|
||||
wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
|
||||
#ifndef GEKKO
|
||||
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||
#endif
|
||||
handle_expansion(wm, msg+5);
|
||||
break;
|
||||
case WM_RPT_BTN_IR_EXP:
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
calculate_basic_ir(wm, msg+2);
|
||||
handle_expansion(wm,msg+12);
|
||||
break;
|
||||
case WM_RPT_BTN_ACC_IR_EXP:
|
||||
/* button - motion - ir - expansion */
|
||||
wiiuse_pressed_buttons(wm, msg);
|
||||
|
||||
wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
|
||||
wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
|
||||
wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
|
||||
#ifndef GEKKO
|
||||
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||
#endif
|
||||
/* ir */
|
||||
calculate_basic_ir(wm, msg+5);
|
||||
|
||||
handle_expansion(wm, msg+15);
|
||||
break;
|
||||
default:
|
||||
WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event);
|
||||
return;
|
||||
}
|
||||
|
||||
/* was there an event? */
|
||||
wm->event = WIIUSE_EVENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find what buttons are pressed.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param msg The message specified in the event packet.
|
||||
*/
|
||||
void wiiuse_pressed_buttons(struct wiimote_t* wm, ubyte* msg) {
|
||||
short now;
|
||||
|
||||
/* convert to big endian */
|
||||
now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL;
|
||||
|
||||
/* preserve old btns pressed */
|
||||
wm->btns_last = wm->btns;
|
||||
|
||||
/* pressed now & were pressed, then held */
|
||||
wm->btns_held = (now & wm->btns);
|
||||
|
||||
/* were pressed or were held & not pressed now, then released */
|
||||
wm->btns_released = ((wm->btns | wm->btns_held) & ~now);
|
||||
|
||||
/* buttons pressed now */
|
||||
wm->btns = now;
|
||||
}
|
14
wii/wiiuse/events.h
Normal file
14
wii/wiiuse/events.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __EVENTS_H__
|
||||
#define __EVENTS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void wiiuse_pressed_buttons(struct wiimote_t* wm, ubyte* msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
150
wii/wiiuse/io.c
Normal file
150
wii/wiiuse/io.c
Normal file
@ -0,0 +1,150 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "nunchuk.h"
|
||||
#include "classic.h"
|
||||
#include "motion_plus.h"
|
||||
#include "io.h"
|
||||
#include "lwp_wkspace.inl"
|
||||
|
||||
void wiiuse_handshake(struct wiimote_t *wm,ubyte *data,uword len)
|
||||
{
|
||||
ubyte *buf = NULL;
|
||||
struct accel_t *accel = &wm->accel_calib;
|
||||
|
||||
//printf("wiiuse_handshake(%d,%p,%d)\n",wm->handshake_state,data,len);
|
||||
|
||||
switch(wm->handshake_state) {
|
||||
case 0:
|
||||
wm->handshake_state++;
|
||||
|
||||
wiiuse_set_leds(wm,WIIMOTE_LED_NONE,NULL);
|
||||
|
||||
buf = __lwp_wkspace_allocate(sizeof(ubyte)*8);
|
||||
wiiuse_read_data(wm,buf,WM_MEM_OFFSET_CALIBRATION,7,wiiuse_handshake);
|
||||
break;
|
||||
case 1:
|
||||
wm->handshake_state++;
|
||||
|
||||
accel->cal_zero.x = ((data[0]<<2)|((data[3]>>4)&3));
|
||||
accel->cal_zero.y = ((data[1]<<2)|((data[3]>>2)&3));
|
||||
accel->cal_zero.z = ((data[2]<<2)|(data[3]&3));
|
||||
|
||||
accel->cal_g.x = (((data[4]<<2)|((data[7]>>4)&3)) - accel->cal_zero.x);
|
||||
accel->cal_g.y = (((data[5]<<2)|((data[7]>>2)&3)) - accel->cal_zero.y);
|
||||
accel->cal_g.z = (((data[6]<<2)|(data[7]&3)) - accel->cal_zero.z);
|
||||
__lwp_wkspace_free(data);
|
||||
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
|
||||
|
||||
wm->event = WIIUSE_CONNECT;
|
||||
wiiuse_status(wm,NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void wiiuse_handshake_expansion_start(struct wiimote_t *wm)
|
||||
{
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP) || WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_FAILED) || WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_HANDSHAKE))
|
||||
return;
|
||||
|
||||
wm->expansion_state = 0;
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
wiiuse_handshake_expansion(wm, NULL, 0);
|
||||
}
|
||||
|
||||
void wiiuse_handshake_expansion(struct wiimote_t *wm,ubyte *data,uword len)
|
||||
{
|
||||
int id;
|
||||
ubyte val;
|
||||
ubyte *buf = NULL;
|
||||
|
||||
switch(wm->expansion_state) {
|
||||
/* These two initialization writes disable the encryption */
|
||||
case 0:
|
||||
wm->expansion_state = 1;
|
||||
val = 0x55;
|
||||
wiiuse_write_data(wm,WM_EXP_MEM_ENABLE1,&val,1,wiiuse_handshake_expansion);
|
||||
break;
|
||||
case 1:
|
||||
wm->expansion_state = 2;
|
||||
val = 0x00;
|
||||
wiiuse_write_data(wm,WM_EXP_MEM_ENABLE2,&val,1,wiiuse_handshake_expansion);
|
||||
break;
|
||||
case 2:
|
||||
wm->expansion_state = 3;
|
||||
buf = __lwp_wkspace_allocate(sizeof(ubyte)*EXP_HANDSHAKE_LEN);
|
||||
wiiuse_read_data(wm,buf,WM_EXP_MEM_CALIBR,EXP_HANDSHAKE_LEN,wiiuse_handshake_expansion);
|
||||
break;
|
||||
case 3:
|
||||
if(!data || !len) return;
|
||||
id = BIG_ENDIAN_LONG(*(int*)(&data[220]));
|
||||
|
||||
switch(id) {
|
||||
case EXP_ID_CODE_NUNCHUK:
|
||||
if(!nunchuk_handshake(wm,&wm->exp.nunchuk,data,len)) return;
|
||||
break;
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING2:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING3:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC2:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC3:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC4:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC5:
|
||||
if(!classic_ctrl_handshake(wm,&wm->exp.classic,data,len)) return;
|
||||
break;
|
||||
default:
|
||||
if(!classic_ctrl_handshake(wm,&wm->exp.classic,data,len)) return;
|
||||
/*WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_EXP_FAILED);
|
||||
__lwp_wkspace_free(data);
|
||||
wiiuse_status(wm,NULL);
|
||||
return;*/
|
||||
}
|
||||
__lwp_wkspace_free(data);
|
||||
|
||||
WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_EXP);
|
||||
wiiuse_set_ir_mode(wm);
|
||||
wiiuse_status(wm,NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void wiiuse_disable_expansion(struct wiimote_t *wm)
|
||||
{
|
||||
if(!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) return;
|
||||
|
||||
/* tell the associated module the expansion was removed */
|
||||
switch(wm->exp.type) {
|
||||
case EXP_NUNCHUK:
|
||||
nunchuk_disconnected(&wm->exp.nunchuk);
|
||||
wm->event = WIIUSE_NUNCHUK_REMOVED;
|
||||
break;
|
||||
case EXP_CLASSIC:
|
||||
classic_ctrl_disconnected(&wm->exp.classic);
|
||||
wm->event = WIIUSE_CLASSIC_CTRL_REMOVED;
|
||||
break;
|
||||
case EXP_MOTION_PLUS:
|
||||
motion_plus_disconnected(&wm->exp.mp);
|
||||
wm->event = WIIUSE_MOTION_PLUS_REMOVED;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
|
||||
wm->exp.type = EXP_NONE;
|
||||
|
||||
wiiuse_set_ir_mode(wm);
|
||||
wiiuse_status(wm,NULL);
|
||||
}
|
23
wii/wiiuse/io.h
Normal file
23
wii/wiiuse/io.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef __IO_H__
|
||||
#define __IO_H__
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void wiiuse_handshake(struct wiimote_t* wm,ubyte *data,uword len);
|
||||
void wiiuse_handshake_expansion_start(struct wiimote_t *wm);
|
||||
void wiiuse_handshake_expansion(struct wiimote_t *wm,ubyte *data,uword len);
|
||||
void wiiuse_disable_expansion(struct wiimote_t *wm);
|
||||
|
||||
int wiiuse_io_read(struct wiimote_t* wm);
|
||||
int wiiuse_io_write(struct wiimote_t* wm, ubyte* buf, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
176
wii/wiiuse/io_wii.c
Normal file
176
wii/wiiuse/io_wii.c
Normal file
@ -0,0 +1,176 @@
|
||||
#ifdef GEKKO
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "events.h"
|
||||
#include "io.h"
|
||||
#include "lwp_wkspace.h"
|
||||
|
||||
#define MAX_COMMANDS 0x100
|
||||
#define MAX_WIIMOTES 5
|
||||
|
||||
static vu32* const _ipcReg = (u32*)0xCD000000;
|
||||
static u8 *__queue_buffer[MAX_WIIMOTES] = { 0, 0, 0, 0, 0 };
|
||||
|
||||
extern void parse_event(struct wiimote_t *wm);
|
||||
extern void idle_cycle(struct wiimote_t* wm);
|
||||
extern void hexdump(void *d, int len);
|
||||
|
||||
static __inline__ u32 ACR_ReadReg(u32 reg)
|
||||
{
|
||||
return _ipcReg[reg>>2];
|
||||
}
|
||||
|
||||
static __inline__ void ACR_WriteReg(u32 reg,u32 val)
|
||||
{
|
||||
_ipcReg[reg>>2] = val;
|
||||
}
|
||||
|
||||
static s32 __wiiuse_disconnected(void *arg,struct bte_pcb *pcb,u8 err)
|
||||
{
|
||||
struct wiimote_listen_t *wml = (struct wiimote_listen_t*)arg;
|
||||
struct wiimote_t *wm = wml->wm;
|
||||
|
||||
if(!wm) return ERR_OK;
|
||||
|
||||
//printf("wiimote disconnected\n");
|
||||
WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR|WIIMOTE_STATE_IR_INIT));
|
||||
WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_SPEAKER|WIIMOTE_STATE_SPEAKER_INIT));
|
||||
WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_EXP|WIIMOTE_STATE_EXP_HANDSHAKE|WIIMOTE_STATE_EXP_FAILED));
|
||||
WIIMOTE_DISABLE_STATE(wm,(WIIMOTE_STATE_CONNECTED|WIIMOTE_STATE_HANDSHAKE|WIIMOTE_STATE_HANDSHAKE_COMPLETE));
|
||||
|
||||
while(wm->cmd_head) {
|
||||
__lwp_queue_append(&wm->cmdq,&wm->cmd_head->node);
|
||||
wm->cmd_head = wm->cmd_head->next;
|
||||
}
|
||||
wm->cmd_tail = NULL;
|
||||
|
||||
if(wm->event_cb) wm->event_cb(wm,WIIUSE_DISCONNECT);
|
||||
|
||||
wml->wm = NULL;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static s32 __wiiuse_receive(void *arg,void *buffer,u16 len)
|
||||
{
|
||||
struct wiimote_listen_t *wml = (struct wiimote_listen_t*)arg;
|
||||
struct wiimote_t *wm = wml->wm;
|
||||
|
||||
if(!wm || !buffer || len==0) return ERR_OK;
|
||||
|
||||
//printf("__wiiuse_receive[%02x]\n",*(char*)buffer);
|
||||
wm->event = WIIUSE_NONE;
|
||||
|
||||
memcpy(wm->event_buf,buffer,len);
|
||||
memset(&(wm->event_buf[len]),0,(MAX_PAYLOAD - len));
|
||||
parse_event(wm);
|
||||
|
||||
if(wm->event!=WIIUSE_NONE) {
|
||||
if(wm->event_cb) wm->event_cb(wm,wm->event);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static s32 __wiiuse_connected(void *arg,struct bte_pcb *pcb,u8 err)
|
||||
{
|
||||
struct wiimote_listen_t *wml = (struct wiimote_listen_t*)arg;
|
||||
struct wiimote_t *wm;
|
||||
|
||||
wm = wml->assign_cb(&wml->bdaddr);
|
||||
|
||||
if(!wm) {
|
||||
bte_disconnect(wml->sock);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
wml->wm = wm;
|
||||
|
||||
wm->sock = wml->sock;
|
||||
wm->bdaddr = wml->bdaddr;
|
||||
|
||||
//printf("__wiiuse_connected()\n");
|
||||
WIIMOTE_ENABLE_STATE(wm,(WIIMOTE_STATE_CONNECTED|WIIMOTE_STATE_HANDSHAKE));
|
||||
|
||||
wm->handshake_state = 0;
|
||||
wiiuse_handshake(wm,NULL,0);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void __wiiuse_sensorbar_enable(int enable)
|
||||
{
|
||||
u32 val;
|
||||
u32 level;
|
||||
|
||||
level = IRQ_Disable();
|
||||
val = (ACR_ReadReg(0xc0)&~0x100);
|
||||
if(enable) val |= 0x100;
|
||||
ACR_WriteReg(0xc0,val);
|
||||
IRQ_Restore(level);
|
||||
}
|
||||
|
||||
int wiiuse_register(struct wiimote_listen_t *wml, struct bd_addr *bdaddr, struct wiimote_t *(*assign_cb)(struct bd_addr *bdaddr))
|
||||
{
|
||||
s32 err;
|
||||
|
||||
if(!wml || !bdaddr || !assign_cb) return 0;
|
||||
|
||||
wml->wm = NULL;
|
||||
wml->bdaddr = *bdaddr;
|
||||
wml->sock = bte_new();
|
||||
wml->assign_cb = assign_cb;
|
||||
if(wml->sock==NULL) return 0;
|
||||
|
||||
bte_arg(wml->sock,wml);
|
||||
bte_received(wml->sock,__wiiuse_receive);
|
||||
bte_disconnected(wml->sock,__wiiuse_disconnected);
|
||||
|
||||
err = bte_registerdeviceasync(wml->sock,bdaddr,__wiiuse_connected);
|
||||
if(err==ERR_OK) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wiiuse_disconnect(struct wiimote_t *wm)
|
||||
{
|
||||
if(wm==NULL || wm->sock==NULL) return;
|
||||
|
||||
WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_CONNECTED);
|
||||
bte_disconnect(wm->sock);
|
||||
}
|
||||
|
||||
void wiiuse_sensorbar_enable(int enable)
|
||||
{
|
||||
__wiiuse_sensorbar_enable(enable);
|
||||
}
|
||||
|
||||
|
||||
void wiiuse_init_cmd_queue(struct wiimote_t *wm)
|
||||
{
|
||||
u32 size;
|
||||
|
||||
if (!__queue_buffer[wm->unid]) {
|
||||
size = (MAX_COMMANDS*sizeof(struct cmd_blk_t));
|
||||
__queue_buffer[wm->unid] = __lwp_wkspace_allocate(size);
|
||||
if(!__queue_buffer[wm->unid]) return;
|
||||
}
|
||||
|
||||
__lwp_queue_initialize(&wm->cmdq,__queue_buffer[wm->unid],MAX_COMMANDS,sizeof(struct cmd_blk_t));
|
||||
}
|
||||
|
||||
int wiiuse_io_write(struct wiimote_t *wm,ubyte *buf,int len)
|
||||
{
|
||||
if(wm->sock) {
|
||||
return bte_senddata(wm->sock,buf,len);
|
||||
}
|
||||
|
||||
return ERR_CONN;
|
||||
}
|
||||
|
||||
#endif
|
834
wii/wiiuse/ir.c
Normal file
834
wii/wiiuse/ir.c
Normal file
@ -0,0 +1,834 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef GEKKO
|
||||
#include <ogcsys.h>
|
||||
#endif
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "ir.h"
|
||||
|
||||
static int ir_correct_for_bounds(float* x, float* y, enum aspect_t aspect, int offset_x, int offset_y);
|
||||
static void ir_convert_to_vres(float* x, float* y, enum aspect_t aspect, unsigned int vx, unsigned int vy);
|
||||
|
||||
/**
|
||||
* @brief Get the IR sensitivity settings.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param block1 [out] Pointer to where block1 will be set.
|
||||
* @param block2 [out] Pointer to where block2 will be set.
|
||||
*
|
||||
* @return Returns the sensitivity level.
|
||||
*/
|
||||
static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2) {
|
||||
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL1)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL1;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL1;
|
||||
return 1;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL2)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL2;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL2;
|
||||
return 2;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL3)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL3;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL3;
|
||||
return 3;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL4)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL4;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL4;
|
||||
return 4;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL5)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL5;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL5;
|
||||
return 5;
|
||||
}
|
||||
|
||||
*block1 = NULL;
|
||||
*block2 = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rotate_dots(struct fdot_t* in, struct fdot_t *out, int count, float ang) {
|
||||
float s, c;
|
||||
int i;
|
||||
|
||||
if (ang == 0) {
|
||||
for (i = 0; i < count; ++i) {
|
||||
out[i].x = in[i].x;
|
||||
out[i].y = in[i].y;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
s = sin(DEGREE_TO_RAD(ang));
|
||||
c = cos(DEGREE_TO_RAD(ang));
|
||||
|
||||
/*
|
||||
* [ cos(theta) -sin(theta) ][ ir->rx ]
|
||||
* [ sin(theta) cos(theta) ][ ir->ry ]
|
||||
*/
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
out[i].x = (c * in[i].x) + (-s * in[i].y);
|
||||
out[i].y = (s * in[i].x) + (c * in[i].y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Correct for the IR bounding box.
|
||||
*
|
||||
* @param x [out] The current X, it will be updated if valid.
|
||||
* @param y [out] The current Y, it will be updated if valid.
|
||||
* @param aspect Aspect ratio of the screen.
|
||||
* @param offset_x The X offset of the bounding box.
|
||||
* @param offset_y The Y offset of the bounding box.
|
||||
*
|
||||
* @return Returns 1 if the point is valid and was updated.
|
||||
*
|
||||
* Nintendo was smart with this bit. They sacrifice a little
|
||||
* precision for a big increase in usability.
|
||||
*/
|
||||
static int ir_correct_for_bounds(float* x, float* y, enum aspect_t aspect, int offset_x, int offset_y) {
|
||||
float x0, y0;
|
||||
int xs, ys;
|
||||
|
||||
if (aspect == WIIUSE_ASPECT_16_9) {
|
||||
xs = WM_ASPECT_16_9_X;
|
||||
ys = WM_ASPECT_16_9_Y;
|
||||
} else {
|
||||
xs = WM_ASPECT_4_3_X;
|
||||
ys = WM_ASPECT_4_3_Y;
|
||||
}
|
||||
|
||||
x0 = ((1024 - xs) / 2) + offset_x;
|
||||
y0 = ((768 - ys) / 2) + offset_y;
|
||||
|
||||
if ((*x >= x0)
|
||||
&& (*x <= (x0 + xs))
|
||||
&& (*y >= y0)
|
||||
&& (*y <= (y0 + ys)))
|
||||
{
|
||||
*x -= offset_x;
|
||||
*y -= offset_y;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Interpolate the point to the user defined virtual screen resolution.
|
||||
*/
|
||||
static void ir_convert_to_vres(float* x, float* y, enum aspect_t aspect, unsigned int vx, unsigned int vy) {
|
||||
int xs, ys;
|
||||
|
||||
if (aspect == WIIUSE_ASPECT_16_9) {
|
||||
xs = WM_ASPECT_16_9_X;
|
||||
ys = WM_ASPECT_16_9_Y;
|
||||
} else {
|
||||
xs = WM_ASPECT_4_3_X;
|
||||
ys = WM_ASPECT_4_3_Y;
|
||||
}
|
||||
|
||||
*x -= ((1024-xs)/2);
|
||||
*y -= ((768-ys)/2);
|
||||
|
||||
*x = (*x / (float)xs) * vx;
|
||||
*y = (*y / (float)ys) * vy;
|
||||
}
|
||||
|
||||
void wiiuse_set_ir_mode(struct wiimote_t *wm)
|
||||
{
|
||||
ubyte buf = 0x00;
|
||||
|
||||
if(!wm) return;
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR)) return;
|
||||
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP)) buf = WM_IR_TYPE_BASIC;
|
||||
else buf = WM_IR_TYPE_EXTENDED;
|
||||
wiiuse_write_data(wm,WM_REG_IR_MODENUM, &buf, 1, NULL);
|
||||
}
|
||||
|
||||
void wiiuse_set_ir(struct wiimote_t *wm,int status)
|
||||
{
|
||||
ubyte buf = 0x00;
|
||||
int ir_level = 0;
|
||||
char* block1 = NULL;
|
||||
char* block2 = NULL;
|
||||
|
||||
if(!wm) return;
|
||||
|
||||
/*
|
||||
* Wait for the handshake to finish first.
|
||||
* When it handshake finishes and sees that
|
||||
* IR is enabled, it will call this function
|
||||
* again to actually enable IR.
|
||||
*/
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
|
||||
WIIUSE_DEBUG("Tried to enable IR, will wait until handshake finishes.\n");
|
||||
if(status)
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_INIT);
|
||||
else
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR_INIT);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to make sure a sensitivity setting is selected.
|
||||
*/
|
||||
ir_level = get_ir_sens(wm, &block1, &block2);
|
||||
if (!ir_level) {
|
||||
WIIUSE_ERROR("No IR sensitivity setting selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
/* if already enabled then stop */
|
||||
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* if already disabled then stop */
|
||||
if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
buf = (status ? 0x04 : 0x00);
|
||||
wiiuse_sendcmd(wm,WM_CMD_IR,&buf,1,NULL);
|
||||
wiiuse_sendcmd(wm,WM_CMD_IR_2,&buf,1,NULL);
|
||||
|
||||
if (!status) {
|
||||
WIIUSE_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid);
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* enable IR, set sensitivity */
|
||||
buf = 0x08;
|
||||
wiiuse_write_data(wm,WM_REG_IR,&buf,1,NULL);
|
||||
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (ubyte*)block1, 9, NULL);
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (ubyte*)block2, 2, NULL);
|
||||
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP)) buf = WM_IR_TYPE_BASIC;
|
||||
else buf = WM_IR_TYPE_EXTENDED;
|
||||
wiiuse_write_data(wm,WM_REG_IR_MODENUM, &buf, 1, NULL);
|
||||
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the virtual screen resolution for IR tracking.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param status 1 to enable, 0 to disable.
|
||||
*/
|
||||
void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y) {
|
||||
if (!wm) return;
|
||||
|
||||
wm->ir.vres[0] = (x-1);
|
||||
wm->ir.vres[1] = (y-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the XY position for the IR cursor.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
*/
|
||||
void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos) {
|
||||
if (!wm) return;
|
||||
|
||||
wm->ir.pos = pos;
|
||||
|
||||
switch (pos) {
|
||||
|
||||
case WIIUSE_IR_ABOVE:
|
||||
wm->ir.offset[0] = 0;
|
||||
|
||||
if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
|
||||
wm->ir.offset[1] = WM_ASPECT_16_9_Y/2 - 70;
|
||||
else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
|
||||
wm->ir.offset[1] = WM_ASPECT_4_3_Y/2 - 100;
|
||||
|
||||
return;
|
||||
|
||||
case WIIUSE_IR_BELOW:
|
||||
wm->ir.offset[0] = 0;
|
||||
|
||||
if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
|
||||
wm->ir.offset[1] = -WM_ASPECT_16_9_Y/2 + 70;
|
||||
else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
|
||||
wm->ir.offset[1] = -WM_ASPECT_4_3_Y/2 + 100;
|
||||
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the aspect ratio of the TV/monitor.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param aspect Either WIIUSE_ASPECT_16_9 or WIIUSE_ASPECT_4_3
|
||||
*/
|
||||
void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect) {
|
||||
if (!wm) return;
|
||||
|
||||
wm->ir.aspect = aspect;
|
||||
|
||||
if (aspect == WIIUSE_ASPECT_4_3) {
|
||||
wm->ir.vres[0] = WM_ASPECT_4_3_X;
|
||||
wm->ir.vres[1] = WM_ASPECT_4_3_Y;
|
||||
} else {
|
||||
wm->ir.vres[0] = WM_ASPECT_16_9_X;
|
||||
wm->ir.vres[1] = WM_ASPECT_16_9_Y;
|
||||
}
|
||||
|
||||
/* reset the position offsets */
|
||||
wiiuse_set_ir_position(wm, wm->ir.pos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the IR sensitivity.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param level 1-5, same as Wii system sensitivity setting.
|
||||
*
|
||||
* If the level is < 1, then level will be set to 1.
|
||||
* If the level is > 5, then level will be set to 5.
|
||||
*/
|
||||
void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) {
|
||||
char* block1 = NULL;
|
||||
char* block2 = NULL;
|
||||
|
||||
if (!wm) return;
|
||||
|
||||
if (level > 5) level = 5;
|
||||
if (level < 1) level = 1;
|
||||
|
||||
WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL2 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL3 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL4 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL5));
|
||||
|
||||
switch (level) {
|
||||
case 1:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1);
|
||||
break;
|
||||
case 2:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2);
|
||||
break;
|
||||
case 3:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3);
|
||||
break;
|
||||
case 4:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4);
|
||||
break;
|
||||
case 5:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR)) return;
|
||||
|
||||
/* set the new sensitivity */
|
||||
get_ir_sens(wm, &block1, &block2);
|
||||
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (ubyte*)block1, 9,NULL);
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (ubyte*)block2, 2,NULL);
|
||||
|
||||
WIIUSE_DEBUG("Set IR sensitivity to level %i (unid %i)", level, wm->unid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calculate the data from the IR spots. Basic IR mode.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param data Data returned by the wiimote for the IR spots.
|
||||
*/
|
||||
void calculate_basic_ir(struct wiimote_t* wm, ubyte* data) {
|
||||
struct ir_dot_t* dot = wm->ir.dot;
|
||||
int i;
|
||||
|
||||
dot[0].rx = 1023 - (data[0] | ((data[2] & 0x30) << 4));
|
||||
dot[0].ry = data[1] | ((data[2] & 0xC0) << 2);
|
||||
|
||||
dot[1].rx = 1023 - (data[3] | ((data[2] & 0x03) << 8));
|
||||
dot[1].ry = data[4] | ((data[2] & 0x0C) << 6);
|
||||
|
||||
dot[2].rx = 1023 - (data[5] | ((data[7] & 0x30) << 4));
|
||||
dot[2].ry = data[6] | ((data[7] & 0xC0) << 2);
|
||||
|
||||
dot[3].rx = 1023 - (data[8] | ((data[7] & 0x03) << 8));
|
||||
dot[3].ry = data[9] | ((data[7] & 0x0C) << 6);
|
||||
|
||||
/* set each IR spot to visible if spot is in range */
|
||||
for (i = 0; i < 4; ++i) {
|
||||
dot[i].rx = BIG_ENDIAN_SHORT(dot[i].rx);
|
||||
dot[i].ry = BIG_ENDIAN_SHORT(dot[i].ry);
|
||||
|
||||
if (dot[i].ry == 1023)
|
||||
dot[i].visible = 0;
|
||||
else {
|
||||
dot[i].visible = 1;
|
||||
dot[i].size = 0; /* since we don't know the size, set it as 0 */
|
||||
}
|
||||
}
|
||||
#ifndef GEKKO
|
||||
interpret_ir_data(&wm->ir,&wm->orient,WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the data from the IR spots. Extended IR mode.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param data Data returned by the wiimote for the IR spots.
|
||||
*/
|
||||
void calculate_extended_ir(struct wiimote_t* wm, ubyte* data) {
|
||||
struct ir_dot_t* dot = wm->ir.dot;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
dot[i].rx = 1023 - (data[3*i] | ((data[(3*i)+2] & 0x30) << 4));
|
||||
dot[i].ry = data[(3*i)+1] | ((data[(3*i)+2] & 0xC0) << 2);
|
||||
|
||||
dot[i].size = data[(3*i)+2];
|
||||
|
||||
dot[i].rx = BIG_ENDIAN_SHORT(dot[i].rx);
|
||||
dot[i].ry = BIG_ENDIAN_SHORT(dot[i].ry);
|
||||
|
||||
dot[i].size = dot[i].size&0x0f;
|
||||
|
||||
/* if in range set to visible */
|
||||
if (dot[i].ry == 1023)
|
||||
dot[i].visible = 0;
|
||||
else
|
||||
dot[i].visible = 1;
|
||||
}
|
||||
#ifndef GEKKO
|
||||
interpret_ir_data(&wm->ir,&wm->orient,WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC));
|
||||
#endif
|
||||
}
|
||||
|
||||
enum {
|
||||
IR_STATE_DEAD = 0,
|
||||
IR_STATE_GOOD,
|
||||
IR_STATE_SINGLE,
|
||||
IR_STATE_LOST,
|
||||
};
|
||||
|
||||
// half-height of the IR sensor if half-width is 1
|
||||
#define HEIGHT (384.0f / 512.0f)
|
||||
// maximum sensor bar slope (tan(35 degrees))
|
||||
#define MAX_SB_SLOPE 0.7f
|
||||
// minimum sensor bar width in view, relative to half of the IR sensor area
|
||||
#define MIN_SB_WIDTH 0.1f
|
||||
// reject "sensor bars" that happen to have a dot towards the middle
|
||||
#define SB_MIDDOT_REJECT 0.05f
|
||||
|
||||
// physical dimensions
|
||||
// cm center to center of emitters
|
||||
#define SB_WIDTH 19.5f
|
||||
// half-width in cm of emitters
|
||||
#define SB_DOT_WIDTH 2.25f
|
||||
// half-height in cm of emitters (with some tolerance)
|
||||
#define SB_DOT_HEIGHT 1.0f
|
||||
|
||||
#define SB_DOT_WIDTH_RATIO (SB_DOT_WIDTH / SB_WIDTH)
|
||||
#define SB_DOT_HEIGHT_RATIO (SB_DOT_HEIGHT / SB_WIDTH)
|
||||
|
||||
// dots further out than these coords are allowed to not be picked up
|
||||
// otherwise assume something's wrong
|
||||
//#define SB_OFF_SCREEN_X 0.8f
|
||||
//#define SB_OFF_SCREEN_Y (0.8f * HEIGHT)
|
||||
|
||||
// disable, may be doing more harm than good due to sensor pickup glitches
|
||||
#define SB_OFF_SCREEN_X 0.0f
|
||||
#define SB_OFF_SCREEN_Y 0.0f
|
||||
|
||||
// if a point is closer than this to one of the previous SB points
|
||||
// when it reappears, consider it the same instead of trying to guess
|
||||
// which one of the two it is
|
||||
#define SB_SINGLE_NOGUESS_DISTANCE (100.0 * 100.0)
|
||||
|
||||
// width of the sensor bar in pixels at one meter from the Wiimote
|
||||
#define SB_Z_COEFFICIENT 256.0f
|
||||
|
||||
// distance in meters from the center of the FOV to the left or right edge,
|
||||
// when the wiimote is at one meter
|
||||
#define WIIMOTE_FOV_COEFFICIENT 0.39f
|
||||
|
||||
#define SQUARED(x) ((x)*(x))
|
||||
#define WMAX(x,y) ((x>y)?(x):(y))
|
||||
#define WMIN(x,y) ((x<y)?(x):(y))
|
||||
|
||||
/**
|
||||
* @brief Interpret IR data into more user friendly variables.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
*/
|
||||
void find_sensorbar(struct ir_t* ir, struct orient_t *orient) {
|
||||
struct fdot_t dots[4];
|
||||
struct fdot_t acc_dots[4];
|
||||
struct sb_t cand;
|
||||
struct sb_t candidates[6];
|
||||
struct sb_t sb;
|
||||
|
||||
fdot_t difference;
|
||||
|
||||
int num_candidates = 0;
|
||||
|
||||
int i;
|
||||
int j;
|
||||
int first, second;
|
||||
|
||||
WIIUSE_DEBUG("IR: orient angle: %.02f\n",orient->roll);
|
||||
|
||||
/* count visible dots and populate dots structure */
|
||||
/* dots[] is in -1..1 units for width */
|
||||
ir->num_dots = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (ir->dot[i].visible) {
|
||||
dots[ir->num_dots].x = (ir->dot[i].rx - 512.0f) / 512.0f;
|
||||
dots[ir->num_dots].y = (ir->dot[i].ry - 384.0f) / 512.0f;
|
||||
WIIUSE_DEBUG("IR: dot %d at (%d,%d) (%.03f,%.03f)\n",ir->num_dots,ir->dot[i].rx,ir->dot[i].ry,dots[ir->num_dots].x,dots[ir->num_dots].y);
|
||||
ir->num_dots++;
|
||||
}
|
||||
}
|
||||
|
||||
WIIUSE_DEBUG("IR: found %d dots\n",ir->num_dots);
|
||||
|
||||
// nothing to track
|
||||
if(ir->num_dots == 0) {
|
||||
if(ir->state != IR_STATE_DEAD)
|
||||
ir->state = IR_STATE_LOST;
|
||||
ir->ax = 0;
|
||||
ir->ay = 0;
|
||||
ir->distance = 0.0f;
|
||||
ir->raw_valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* ==== Find the Sensor Bar ==== */
|
||||
|
||||
// first rotate according to accelerometer orientation
|
||||
rotate_dots(dots, acc_dots, ir->num_dots, orient->roll);
|
||||
if(ir->num_dots > 1) {
|
||||
WIIUSE_DEBUG("IR: locating sensor bar candidates\n");
|
||||
|
||||
// iterate through all dot pairs
|
||||
for(first=0; first < (ir->num_dots-1); first++) {
|
||||
for(second=(first+1); second < ir->num_dots; second++) {
|
||||
WIIUSE_DEBUG("IR: trying dots %d and %d\n",first,second);
|
||||
// order the dots leftmost first into cand
|
||||
// storing both the raw dots and the accel-rotated dots
|
||||
if(acc_dots[first].x > acc_dots[second].x) {
|
||||
cand.dots[0] = dots[second];
|
||||
cand.dots[1] = dots[first];
|
||||
cand.acc_dots[0] = acc_dots[second];
|
||||
cand.acc_dots[1] = acc_dots[first];
|
||||
} else {
|
||||
cand.dots[0] = dots[first];
|
||||
cand.dots[1] = dots[second];
|
||||
cand.acc_dots[0] = acc_dots[first];
|
||||
cand.acc_dots[1] = acc_dots[second];
|
||||
}
|
||||
difference.x = cand.acc_dots[1].x - cand.acc_dots[0].x;
|
||||
difference.y = cand.acc_dots[1].y - cand.acc_dots[0].y;
|
||||
|
||||
// check angle
|
||||
if(fabsf(difference.y / difference.x) > MAX_SB_SLOPE)
|
||||
continue;
|
||||
WIIUSE_DEBUG("IR: passed angle check\n");
|
||||
// rotate to the true sensor bar angle
|
||||
cand.off_angle = -RAD_TO_DEGREE(atan2(difference.y, difference.x));
|
||||
cand.angle = cand.off_angle + orient->roll;
|
||||
rotate_dots(cand.dots, cand.rot_dots, 2, cand.angle);
|
||||
WIIUSE_DEBUG("IR: off_angle: %.02f, angle: %.02f\n", cand.off_angle, cand.angle);
|
||||
// recalculate x distance - y should be zero now, so ignore it
|
||||
difference.x = cand.rot_dots[1].x - cand.rot_dots[0].x;
|
||||
|
||||
// check distance
|
||||
if(difference.x < MIN_SB_WIDTH)
|
||||
continue;
|
||||
// middle dot check. If there's another source somewhere in the
|
||||
// middle of this candidate, then this can't be a sensor bar
|
||||
|
||||
for(i=0; i<ir->num_dots; i++) {
|
||||
float wadj, hadj;
|
||||
struct fdot_t tdot;
|
||||
if(i==first || i==second) continue;
|
||||
hadj = SB_DOT_HEIGHT_RATIO * difference.x;
|
||||
wadj = SB_DOT_WIDTH_RATIO * difference.x;
|
||||
rotate_dots(&dots[i], &tdot, 1, cand.angle);
|
||||
if( ((cand.rot_dots[0].x + wadj) < tdot.x) &&
|
||||
((cand.rot_dots[1].x - wadj) > tdot.x) &&
|
||||
((cand.rot_dots[0].y + hadj) > tdot.y) &&
|
||||
((cand.rot_dots[0].y - hadj) < tdot.y))
|
||||
break;
|
||||
}
|
||||
// failed middle dot check
|
||||
if(i < ir->num_dots) continue;
|
||||
WIIUSE_DEBUG("IR: passed middle dot check\n");
|
||||
|
||||
cand.score = 1 / (cand.rot_dots[1].x - cand.rot_dots[0].x);
|
||||
|
||||
// we have a candidate, store it
|
||||
WIIUSE_DEBUG("IR: new candidate %d\n",num_candidates);
|
||||
candidates[num_candidates++] = cand;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(num_candidates == 0) {
|
||||
int closest = -1;
|
||||
int closest_to = 0;
|
||||
float best = 999.0f;
|
||||
float d;
|
||||
float dx[2];
|
||||
struct sb_t sbx[2];
|
||||
// no sensor bar candidates, try to work with a lone dot
|
||||
WIIUSE_DEBUG("IR: no candidates\n");
|
||||
switch(ir->state) {
|
||||
case IR_STATE_DEAD:
|
||||
WIIUSE_DEBUG("IR: we're dead\n");
|
||||
// we've never seen a sensor bar before, so we're screwed
|
||||
ir->ax = 0.0f;
|
||||
ir->ay = 0.0f;
|
||||
ir->distance = 0.0f;
|
||||
ir->raw_valid = 0;
|
||||
return;
|
||||
case IR_STATE_GOOD:
|
||||
case IR_STATE_SINGLE:
|
||||
case IR_STATE_LOST:
|
||||
WIIUSE_DEBUG("IR: trying to keep track of single dot\n");
|
||||
// try to find the dot closest to the previous sensor bar position
|
||||
for(i=0; i<ir->num_dots; i++) {
|
||||
WIIUSE_DEBUG("IR: checking dot %d (%.02f, %.02f)\n",i, acc_dots[i].x,acc_dots[i].y);
|
||||
for(j=0; j<2; j++) {
|
||||
WIIUSE_DEBUG(" to dot %d (%.02f, %.02f)\n",j, ir->sensorbar.acc_dots[j].x,ir->sensorbar.acc_dots[j].y);
|
||||
d = SQUARED(acc_dots[i].x - ir->sensorbar.acc_dots[j].x);
|
||||
d += SQUARED(acc_dots[i].y - ir->sensorbar.acc_dots[j].y);
|
||||
if(d < best) {
|
||||
best = d;
|
||||
closest_to = j;
|
||||
closest = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
WIIUSE_DEBUG("IR: closest dot is %d to %d\n",closest,closest_to);
|
||||
if(ir->state != IR_STATE_LOST || best < SB_SINGLE_NOGUESS_DISTANCE) {
|
||||
// now work out where the other dot would be, in the acc frame
|
||||
sb.acc_dots[closest_to] = acc_dots[closest];
|
||||
sb.acc_dots[closest_to^1].x = ir->sensorbar.acc_dots[closest_to^1].x - ir->sensorbar.acc_dots[closest_to].x + acc_dots[closest].x;
|
||||
sb.acc_dots[closest_to^1].y = ir->sensorbar.acc_dots[closest_to^1].y - ir->sensorbar.acc_dots[closest_to].y + acc_dots[closest].y;
|
||||
// get the raw frame
|
||||
rotate_dots(sb.acc_dots, sb.dots, 2, -orient->roll);
|
||||
if((fabsf(sb.dots[closest_to^1].x) < SB_OFF_SCREEN_X) && (fabsf(sb.dots[closest_to^1].y) < SB_OFF_SCREEN_Y)) {
|
||||
// this dot should be visible but isn't, since the candidate section failed.
|
||||
// fall through and try to pick out the sensor bar without previous information
|
||||
WIIUSE_DEBUG("IR: dot falls on screen, falling through\n");
|
||||
} else {
|
||||
// calculate the rotated dots frame
|
||||
// angle tends to drift, so recalculate
|
||||
sb.off_angle = -RAD_TO_DEGREE(atan2(sb.acc_dots[1].y - sb.acc_dots[0].y, sb.acc_dots[1].x - sb.acc_dots[0].x));
|
||||
sb.angle = ir->sensorbar.off_angle + orient->roll;
|
||||
rotate_dots(sb.acc_dots, sb.rot_dots, 2, ir->sensorbar.off_angle);
|
||||
WIIUSE_DEBUG("IR: kept track of single dot\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
WIIUSE_DEBUG("IR: lost the dot and new one is too far away\n");
|
||||
}
|
||||
// try to find the dot closest to the sensor edge
|
||||
WIIUSE_DEBUG("IR: trying to find best dot\n");
|
||||
for(i=0; i<ir->num_dots; i++) {
|
||||
d = WMIN(1.0f - fabsf(dots[i].x), HEIGHT - fabsf(dots[i].y));
|
||||
if(d < best) {
|
||||
best = d;
|
||||
closest = i;
|
||||
}
|
||||
}
|
||||
WIIUSE_DEBUG("IR: best dot: %d\n",closest);
|
||||
// now try it as both places in the sensor bar
|
||||
// and pick the one that places the other dot furthest off-screen
|
||||
for(i=0; i<2; i++) {
|
||||
sbx[i].acc_dots[i] = acc_dots[closest];
|
||||
sbx[i].acc_dots[i^1].x = ir->sensorbar.acc_dots[i^1].x - ir->sensorbar.acc_dots[i].x + acc_dots[closest].x;
|
||||
sbx[i].acc_dots[i^1].y = ir->sensorbar.acc_dots[i^1].y - ir->sensorbar.acc_dots[i].y + acc_dots[closest].y;
|
||||
rotate_dots(sbx[i].acc_dots, sbx[i].dots, 2, -orient->roll);
|
||||
dx[i] = WMAX(fabsf(sbx[i].dots[i^1].x),fabsf(sbx[i].dots[i^1].y / HEIGHT));
|
||||
}
|
||||
if(dx[0] > dx[1]) {
|
||||
WIIUSE_DEBUG("IR: dot is LEFT: %.02f > %.02f\n",dx[0],dx[1]);
|
||||
sb = sbx[0];
|
||||
} else {
|
||||
WIIUSE_DEBUG("IR: dot is RIGHT: %.02f < %.02f\n",dx[0],dx[1]);
|
||||
sb = sbx[1];
|
||||
}
|
||||
// angle tends to drift, so recalculate
|
||||
sb.off_angle = -RAD_TO_DEGREE(atan2(sb.acc_dots[1].y - sb.acc_dots[0].y, sb.acc_dots[1].x - sb.acc_dots[0].x));
|
||||
sb.angle = ir->sensorbar.off_angle + orient->roll;
|
||||
rotate_dots(sb.acc_dots, sb.rot_dots, 2, ir->sensorbar.off_angle);
|
||||
WIIUSE_DEBUG("IR: found new dot to track\n");
|
||||
break;
|
||||
}
|
||||
sb.score = 0;
|
||||
ir->state = IR_STATE_SINGLE;
|
||||
} else {
|
||||
int bestidx = 0;
|
||||
float best = 0.0f;
|
||||
WIIUSE_DEBUG("IR: finding best candidate\n");
|
||||
// look for the best candidate
|
||||
// for now, the formula is simple: pick the one with the smallest distance
|
||||
for(i=0; i<num_candidates; i++) {
|
||||
if(candidates[i].score > best) {
|
||||
bestidx = i;
|
||||
best = candidates[i].score;
|
||||
}
|
||||
}
|
||||
WIIUSE_DEBUG("IR: best candidate: %d\n",bestidx);
|
||||
sb = candidates[bestidx];
|
||||
ir->state = IR_STATE_GOOD;
|
||||
}
|
||||
|
||||
ir->raw_valid = 1;
|
||||
ir->ax = ((sb.rot_dots[0].x + sb.rot_dots[1].x) / 2) * 512.0 + 512.0;
|
||||
ir->ay = ((sb.rot_dots[0].y + sb.rot_dots[1].y) / 2) * 512.0 + 384.0;
|
||||
ir->sensorbar = sb;
|
||||
ir->distance = (sb.rot_dots[1].x - sb.rot_dots[0].x) * 512.0;
|
||||
|
||||
}
|
||||
|
||||
#define SMOOTH_IR_RADIUS 8.0f
|
||||
#define SMOOTH_IR_SPEED 0.25f
|
||||
#define SMOOTH_IR_DEADZONE 2.5f
|
||||
|
||||
/**
|
||||
* @brief Smooth the IR pointer position
|
||||
*
|
||||
* @param ir Pointer to an ir_t structure.
|
||||
*/
|
||||
void apply_ir_smoothing(struct ir_t *ir) {
|
||||
f32 dx, dy, d, theta;
|
||||
|
||||
WIIUSE_DEBUG("Smooth: OK (%.02f, %.02f) LAST (%.02f, %.02f) ", ir->ax, ir->ay, ir->sx, ir->sy);
|
||||
dx = ir->ax - ir->sx;
|
||||
dy = ir->ay - ir->sy;
|
||||
d = sqrtf(dx*dx + dy*dy);
|
||||
if (d > SMOOTH_IR_DEADZONE) {
|
||||
if (d < SMOOTH_IR_RADIUS) {
|
||||
WIIUSE_DEBUG("INSIDE\n");
|
||||
ir->sx += dx * SMOOTH_IR_SPEED;
|
||||
ir->sy += dy * SMOOTH_IR_SPEED;
|
||||
} else {
|
||||
WIIUSE_DEBUG("OUTSIDE\n");
|
||||
theta = atan2f(dy, dx);
|
||||
ir->sx = ir->ax - cosf(theta) * SMOOTH_IR_RADIUS;
|
||||
ir->sy = ir->ay - sinf(theta) * SMOOTH_IR_RADIUS;
|
||||
}
|
||||
} else {
|
||||
WIIUSE_DEBUG("DEADZONE\n");
|
||||
}
|
||||
}
|
||||
|
||||
// max number of errors before cooked data drops out
|
||||
#define ERROR_MAX_COUNT 8
|
||||
// max number of glitches before cooked data updates
|
||||
#define GLITCH_MAX_COUNT 5
|
||||
// squared delta over which we consider something a glitch
|
||||
#define GLITCH_DIST (150.0f * 150.0f)
|
||||
|
||||
/**
|
||||
* @brief Interpret IR data into more user friendly variables.
|
||||
*
|
||||
* @param ir Pointer to an ir_t structure.
|
||||
* @param orient Pointer to an orient_t structure.
|
||||
*/
|
||||
void interpret_ir_data(struct ir_t* ir, struct orient_t *orient) {
|
||||
|
||||
float x,y;
|
||||
float d;
|
||||
|
||||
find_sensorbar(ir, orient);
|
||||
|
||||
if(ir->raw_valid) {
|
||||
ir->angle = ir->sensorbar.angle;
|
||||
ir->z = SB_Z_COEFFICIENT / ir->distance;
|
||||
orient->yaw = calc_yaw(ir);
|
||||
if(ir->error_cnt >= ERROR_MAX_COUNT) {
|
||||
ir->sx = ir->ax;
|
||||
ir->sy = ir->ay;
|
||||
ir->glitch_cnt = 0;
|
||||
} else {
|
||||
d = SQUARED(ir->ax - ir->sx) + SQUARED(ir->ay - ir->sy);
|
||||
if(d > GLITCH_DIST) {
|
||||
if(ir->glitch_cnt > GLITCH_MAX_COUNT) {
|
||||
apply_ir_smoothing(ir);
|
||||
ir->glitch_cnt = 0;
|
||||
} else {
|
||||
ir->glitch_cnt++;
|
||||
}
|
||||
} else {
|
||||
ir->glitch_cnt = 0;
|
||||
apply_ir_smoothing(ir);
|
||||
}
|
||||
}
|
||||
ir->smooth_valid = 1;
|
||||
ir->error_cnt = 0;
|
||||
} else {
|
||||
if(ir->error_cnt >= ERROR_MAX_COUNT) {
|
||||
ir->smooth_valid = 0;
|
||||
} else {
|
||||
ir->smooth_valid = 1;
|
||||
ir->error_cnt++;
|
||||
}
|
||||
}
|
||||
if(ir->smooth_valid) {
|
||||
x = ir->sx;
|
||||
y = ir->sy;
|
||||
if (ir_correct_for_bounds(&x, &y, ir->aspect, ir->offset[0], ir->offset[1])) {
|
||||
ir_convert_to_vres(&x, &y, ir->aspect, ir->vres[0], ir->vres[1]);
|
||||
ir->x = x;
|
||||
ir->y = y;
|
||||
ir->valid = 1;
|
||||
} else {
|
||||
ir->valid = 0;
|
||||
}
|
||||
} else {
|
||||
ir->valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate yaw given the IR data.
|
||||
*
|
||||
* @param ir IR data structure.
|
||||
*/
|
||||
float calc_yaw(struct ir_t* ir) {
|
||||
float x;
|
||||
|
||||
x = ir->ax - 512;
|
||||
x *= WIIMOTE_FOV_COEFFICIENT / 512.0;
|
||||
|
||||
return RAD_TO_DEGREE( atanf(x) );
|
||||
}
|
||||
|
22
wii/wiiuse/ir.h
Normal file
22
wii/wiiuse/ir.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef __IR_H__
|
||||
#define __IR_H__
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#define WII_VRES_X 560
|
||||
#define WII_VRES_Y 340
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void calculate_basic_ir(struct wiimote_t* wm, ubyte* data);
|
||||
void calculate_extended_ir(struct wiimote_t* wm, ubyte* data);
|
||||
float calc_yaw(struct ir_t* ir);
|
||||
void interpret_ir_data(struct ir_t* ir, struct orient_t *orient);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
641
wii/wiiuse/license_libogc.txt
Normal file
641
wii/wiiuse/license_libogc.txt
Normal file
@ -0,0 +1,641 @@
|
||||
This license is valid ONLY for libogc and what this license
|
||||
defines as a "covered work" or a "combined work" with libogc.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an officialder
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
18. Exceptions
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give
|
||||
you permission to link this library with independent modules to produce
|
||||
an executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from or
|
||||
based on this library. If you modify this library, you may extend this
|
||||
exception to your version of the library, but you are not obligated to
|
||||
do so. If you do not wish to do so, delete this exception statement from
|
||||
your version.
|
||||
|
49
wii/wiiuse/lwp_priority.inl
Normal file
49
wii/wiiuse/lwp_priority.inl
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef __LWP_PRIORITY_INL__
|
||||
#define __LWP_PRIORITY_INL__
|
||||
|
||||
static __inline__ void __lwp_priomap_init(prio_cntrl *theprio,u32 prio)
|
||||
{
|
||||
u32 major,minor,mask;
|
||||
|
||||
major = prio/16;
|
||||
minor = prio%16;
|
||||
|
||||
theprio->minor = &_prio_bitmap[major];
|
||||
|
||||
mask = 0x80000000>>major;
|
||||
theprio->ready_major = mask;
|
||||
theprio->block_major = ~mask;
|
||||
|
||||
mask = 0x80000000>>minor;
|
||||
theprio->ready_minor = mask;
|
||||
theprio->block_minor = ~mask;
|
||||
#ifdef _LWPPRIO_DEBUG
|
||||
printf("__lwp_priomap_init(%p,%d,%p,%d,%d,%d,%d)\n",theprio,prio,theprio->minor,theprio->ready_major,theprio->ready_minor,theprio->block_major,theprio->block_minor);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_priomap_addto(prio_cntrl *theprio)
|
||||
{
|
||||
*theprio->minor |= theprio->ready_minor;
|
||||
_prio_major_bitmap |= theprio->ready_major;
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_priomap_removefrom(prio_cntrl *theprio)
|
||||
{
|
||||
*theprio->minor &= theprio->block_minor;
|
||||
if(*theprio->minor==0)
|
||||
_prio_major_bitmap &= theprio->block_major;
|
||||
}
|
||||
|
||||
static __inline__ u32 __lwp_priomap_highest()
|
||||
{
|
||||
u32 major,minor;
|
||||
major = cntlzw(_prio_major_bitmap);
|
||||
minor = cntlzw(_prio_bitmap[major]);
|
||||
#ifdef _LWPPRIO_DEBUG
|
||||
printf("__lwp_priomap_highest(%d)\n",((major<<4)+minor));
|
||||
#endif
|
||||
return ((major<<4)+minor);
|
||||
}
|
||||
|
||||
#endif
|
93
wii/wiiuse/lwp_threads.inl
Normal file
93
wii/wiiuse/lwp_threads.inl
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef __LWP_INL__
|
||||
#define __LWP_INL__
|
||||
|
||||
static __inline__ u32 __lwp_thread_isexec(lwp_cntrl *thethread)
|
||||
{
|
||||
return (thethread==_thr_executing);
|
||||
}
|
||||
|
||||
static __inline__ u32 __lwp_thread_isheir(lwp_cntrl *thethread)
|
||||
{
|
||||
return (thethread==_thr_heir);
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_thread_calcheir()
|
||||
{
|
||||
_thr_heir = (lwp_cntrl*)_lwp_thr_ready[__lwp_priomap_highest()].first;
|
||||
#ifdef _LWPTHREADS_DEBUG
|
||||
printf("__lwp_thread_calcheir(%p)\n",_thr_heir);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ u32 __lwp_thread_isallocatedfp(lwp_cntrl *thethread)
|
||||
{
|
||||
return (thethread==_thr_allocated_fp);
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_thread_deallocatefp()
|
||||
{
|
||||
_thr_allocated_fp = NULL;
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_thread_dispatchinitialize()
|
||||
{
|
||||
_thread_dispatch_disable_level = 1;
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_thread_dispatchenable()
|
||||
{
|
||||
if((--_thread_dispatch_disable_level)==0)
|
||||
__thread_dispatch();
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_thread_dispatchdisable()
|
||||
{
|
||||
++_thread_dispatch_disable_level;
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_thread_dispatchunnest()
|
||||
{
|
||||
--_thread_dispatch_disable_level;
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_thread_unblock(lwp_cntrl *thethread)
|
||||
{
|
||||
__lwp_thread_clearstate(thethread,LWP_STATES_BLOCKED);
|
||||
}
|
||||
|
||||
static __inline__ void** __lwp_thread_getlibcreent()
|
||||
{
|
||||
return __lwp_thr_libc_reent;
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_thread_setlibcreent(void **libc_reent)
|
||||
{
|
||||
__lwp_thr_libc_reent = libc_reent;
|
||||
}
|
||||
|
||||
static __inline__ bool __lwp_thread_isswitchwant()
|
||||
{
|
||||
|
||||
return _context_switch_want;
|
||||
}
|
||||
|
||||
static __inline__ bool __lwp_thread_isdispatchenabled()
|
||||
{
|
||||
return (_thread_dispatch_disable_level==0);
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_thread_inittimeslice()
|
||||
{
|
||||
__lwp_wd_initialize(&_lwp_wd_timeslice,__lwp_thread_tickle_timeslice,LWP_TIMESLICE_TIMER_ID,NULL);
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_thread_starttimeslice()
|
||||
{
|
||||
__lwp_wd_insert_ticks(&_lwp_wd_timeslice,millisecs_to_ticks(1));
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_thread_stoptimeslice()
|
||||
{
|
||||
__lwp_wd_remove_ticks(&_lwp_wd_timeslice);
|
||||
}
|
||||
#endif
|
84
wii/wiiuse/lwp_watchdog.inl
Normal file
84
wii/wiiuse/lwp_watchdog.inl
Normal file
@ -0,0 +1,84 @@
|
||||
#ifndef __LWP_WATCHDOG_INL__
|
||||
#define __LWP_WATCHDOG_INL__
|
||||
|
||||
static __inline__ void __lwp_wd_initialize(wd_cntrl *wd,wd_service_routine routine,u32 id,void *usr_data)
|
||||
{
|
||||
wd->state = LWP_WD_INACTIVE;
|
||||
wd->id = id;
|
||||
wd->routine = routine;
|
||||
wd->usr_data = usr_data;
|
||||
}
|
||||
|
||||
static __inline__ wd_cntrl* __lwp_wd_first(lwp_queue *queue)
|
||||
{
|
||||
return (wd_cntrl*)queue->first;
|
||||
}
|
||||
|
||||
static __inline__ wd_cntrl* __lwp_wd_last(lwp_queue *queue)
|
||||
{
|
||||
return (wd_cntrl*)queue->last;
|
||||
}
|
||||
|
||||
static __inline__ wd_cntrl* __lwp_wd_next(wd_cntrl *wd)
|
||||
{
|
||||
return (wd_cntrl*)wd->node.next;
|
||||
}
|
||||
|
||||
static __inline__ wd_cntrl* __lwp_wd_prev(wd_cntrl *wd)
|
||||
{
|
||||
return (wd_cntrl*)wd->node.prev;
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_wd_activate(wd_cntrl *wd)
|
||||
{
|
||||
wd->state = LWP_WD_ACTIVE;
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_wd_deactivate(wd_cntrl *wd)
|
||||
{
|
||||
wd->state = LWP_WD_REMOVE;
|
||||
}
|
||||
|
||||
static __inline__ u32 __lwp_wd_isactive(wd_cntrl *wd)
|
||||
{
|
||||
return (wd->state==LWP_WD_ACTIVE);
|
||||
}
|
||||
|
||||
static __inline__ u64 __lwp_wd_calc_ticks(const struct timespec *time)
|
||||
{
|
||||
u64 ticks;
|
||||
|
||||
ticks = secs_to_ticks(time->tv_sec);
|
||||
ticks += nanosecs_to_ticks(time->tv_nsec);
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_wd_tickle_ticks()
|
||||
{
|
||||
__lwp_wd_tickle(&_wd_ticks_queue);
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_wd_insert_ticks(wd_cntrl *wd,s64 interval)
|
||||
{
|
||||
wd->start = gettime();
|
||||
wd->fire = (wd->start+LWP_WD_ABS(interval));
|
||||
__lwp_wd_insert(&_wd_ticks_queue,wd);
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_wd_adjust_ticks(u32 dir,s64 interval)
|
||||
{
|
||||
__lwp_wd_adjust(&_wd_ticks_queue,dir,interval);
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_wd_remove_ticks(wd_cntrl *wd)
|
||||
{
|
||||
__lwp_wd_remove(&_wd_ticks_queue,wd);
|
||||
}
|
||||
|
||||
static __inline__ void __lwp_wd_reset(wd_cntrl *wd)
|
||||
{
|
||||
__lwp_wd_remove(&_wd_ticks_queue,wd);
|
||||
__lwp_wd_insert(&_wd_ticks_queue,wd);
|
||||
}
|
||||
#endif
|
14
wii/wiiuse/lwp_wkspace.inl
Normal file
14
wii/wiiuse/lwp_wkspace.inl
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __LWP_WKSPACE_INL__
|
||||
#define __LWP_WKSPACE_INL__
|
||||
|
||||
static __inline__ void* __lwp_wkspace_allocate(u32 size)
|
||||
{
|
||||
return __lwp_heap_allocate(&__wkspace_heap,size);
|
||||
}
|
||||
|
||||
static __inline__ BOOL __lwp_wkspace_free(void *ptr)
|
||||
{
|
||||
return __lwp_heap_free(&__wkspace_heap,ptr);
|
||||
}
|
||||
|
||||
#endif
|
92
wii/wiiuse/motion_plus.c
Normal file
92
wii/wiiuse/motion_plus.c
Normal file
@ -0,0 +1,92 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "dynamics.h"
|
||||
#include "events.h"
|
||||
#include "io.h"
|
||||
|
||||
void wiiuse_motion_plus_check(struct wiimote_t *wm,ubyte *data,uword len)
|
||||
{
|
||||
u32 val;
|
||||
if(data == NULL)
|
||||
{
|
||||
wiiuse_read_data(wm, wm->motion_plus_id, WM_EXP_ID, 6, wiiuse_motion_plus_check);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_FAILED);
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
val = (data[3] << 16) | (data[2] << 24) | (data[4] << 8) | data[5];
|
||||
if(val == EXP_ID_CODE_MOTION_PLUS)
|
||||
{
|
||||
/* handshake done */
|
||||
wm->event = WIIUSE_MOTION_PLUS_ACTIVATED;
|
||||
wm->exp.type = EXP_MOTION_PLUS;
|
||||
|
||||
WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_EXP);
|
||||
wiiuse_set_ir_mode(wm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void wiiuse_set_motion_plus_clear2(struct wiimote_t *wm,ubyte *data,uword len)
|
||||
{
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_FAILED);
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
wiiuse_set_ir_mode(wm);
|
||||
wiiuse_status(wm,NULL);
|
||||
}
|
||||
|
||||
static void wiiuse_set_motion_plus_clear1(struct wiimote_t *wm,ubyte *data,uword len)
|
||||
{
|
||||
ubyte val = 0x00;
|
||||
wiiuse_write_data(wm,WM_EXP_MEM_ENABLE1,&val,1,wiiuse_set_motion_plus_clear2);
|
||||
}
|
||||
|
||||
|
||||
void wiiuse_set_motion_plus(struct wiimote_t *wm, int status)
|
||||
{
|
||||
ubyte val;
|
||||
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_HANDSHAKE))
|
||||
return;
|
||||
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
if(status)
|
||||
{
|
||||
val = 0x04;
|
||||
wiiuse_write_data(wm,WM_EXP_MOTION_PLUS_ENABLE,&val,1,wiiuse_motion_plus_check);
|
||||
}
|
||||
else
|
||||
{
|
||||
wiiuse_disable_expansion(wm);
|
||||
val = 0x55;
|
||||
wiiuse_write_data(wm,WM_EXP_MEM_ENABLE1,&val,1,wiiuse_set_motion_plus_clear1);
|
||||
}
|
||||
}
|
||||
|
||||
void motion_plus_disconnected(struct motion_plus_t* mp)
|
||||
{
|
||||
WIIUSE_DEBUG("Motion plus disconnected");
|
||||
memset(mp, 0, sizeof(struct motion_plus_t));
|
||||
}
|
||||
|
||||
void motion_plus_event(struct motion_plus_t* mp, ubyte* msg)
|
||||
{
|
||||
mp->rx = ((msg[5] & 0xFC) << 6) | msg[2]; // Pitch
|
||||
mp->ry = ((msg[4] & 0xFC) << 6) | msg[1]; // Roll
|
||||
mp->rz = ((msg[3] & 0xFC) << 6) | msg[0]; // Yaw
|
||||
|
||||
mp->ext = msg[4] & 0x1;
|
||||
mp->status = (msg[3] & 0x3) | ((msg[4] & 0x2) << 1); // roll, yaw, pitch
|
||||
}
|
23
wii/wiiuse/motion_plus.h
Normal file
23
wii/wiiuse/motion_plus.h
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Motion plus extension
|
||||
*/
|
||||
|
||||
#ifndef MOTION_PLUS_H_INCLUDED
|
||||
#define MOTION_PLUS_H_INCLUDED
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void motion_plus_disconnected(struct motion_plus_t* mp);
|
||||
|
||||
void motion_plus_event(struct motion_plus_t* mp, ubyte* msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
154
wii/wiiuse/nunchuk.c
Normal file
154
wii/wiiuse/nunchuk.c
Normal file
@ -0,0 +1,154 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dynamics.h"
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "nunchuk.h"
|
||||
#include "io.h"
|
||||
|
||||
/**
|
||||
* @brief Find what buttons are pressed.
|
||||
*
|
||||
* @param nc Pointer to a nunchuk_t structure.
|
||||
* @param msg The message byte specified in the event packet.
|
||||
*/
|
||||
static void nunchuk_pressed_buttons(struct nunchuk_t* nc, ubyte now) {
|
||||
/* message is inverted (0 is active, 1 is inactive) */
|
||||
now = ~now & NUNCHUK_BUTTON_ALL;
|
||||
|
||||
/* preserve old btns pressed */
|
||||
nc->btns_last = nc->btns;
|
||||
|
||||
/* pressed now & were pressed, then held */
|
||||
nc->btns_held = (now & nc->btns);
|
||||
|
||||
/* were pressed or were held & not pressed now, then released */
|
||||
nc->btns_released = ((nc->btns | nc->btns_held) & ~now);
|
||||
|
||||
/* buttons pressed now */
|
||||
nc->btns = now;
|
||||
}
|
||||
|
||||
int nunchuk_handshake(struct wiimote_t *wm,struct nunchuk_t *nc,ubyte *data,uword len)
|
||||
{
|
||||
//int i;
|
||||
int offset = 0;
|
||||
|
||||
nc->btns = 0;
|
||||
nc->btns_held = 0;
|
||||
nc->btns_released = 0;
|
||||
nc->flags = &wm->flags;
|
||||
nc->accel_calib = wm->accel_calib;
|
||||
|
||||
//for(i=0;i<len;i++) data[i] = (data[i]^0x17)+0x17;
|
||||
if(data[offset]==0xff) {
|
||||
if(data[offset+16]==0xff) {
|
||||
// try to read the calibration data again
|
||||
wiiuse_read_data(wm,data,WM_EXP_MEM_CALIBR,EXP_HANDSHAKE_LEN,wiiuse_handshake_expansion);
|
||||
} else
|
||||
offset += 16;
|
||||
}
|
||||
|
||||
nc->accel_calib.cal_zero.x = (data[offset + 0]<<2)|((data[offset + 3]>>4)&3);
|
||||
nc->accel_calib.cal_zero.y = (data[offset + 1]<<2)|((data[offset + 3]>>2)&3);
|
||||
nc->accel_calib.cal_zero.z = (data[offset + 2]<<2)|(data[offset + 3]&3);
|
||||
nc->accel_calib.cal_g.x = (data[offset + 4]<<2)|((data[offset + 7]>>4)&3);
|
||||
nc->accel_calib.cal_g.y = (data[offset + 5]<<2)|((data[offset + 7]>>2)&3);
|
||||
nc->accel_calib.cal_g.z = (data[offset + 6]<<2)|(data[offset + 7]&3);
|
||||
nc->js.max.x = data[offset + 8];
|
||||
nc->js.min.x = data[offset + 9];
|
||||
nc->js.center.x = data[offset + 10];
|
||||
nc->js.max.y = data[offset + 11];
|
||||
nc->js.min.y = data[offset + 12];
|
||||
nc->js.center.y = data[offset + 13];
|
||||
|
||||
// set to defaults (averages from 5 nunchuks) if calibration data is invalid
|
||||
if(nc->accel_calib.cal_zero.x == 0)
|
||||
nc->accel_calib.cal_zero.x = 499;
|
||||
if(nc->accel_calib.cal_zero.y == 0)
|
||||
nc->accel_calib.cal_zero.y = 509;
|
||||
if(nc->accel_calib.cal_zero.z == 0)
|
||||
nc->accel_calib.cal_zero.z = 507;
|
||||
if(nc->accel_calib.cal_g.x == 0)
|
||||
nc->accel_calib.cal_g.x = 703;
|
||||
if(nc->accel_calib.cal_g.y == 0)
|
||||
nc->accel_calib.cal_g.y = 709;
|
||||
if(nc->accel_calib.cal_g.z == 0)
|
||||
nc->accel_calib.cal_g.z = 709;
|
||||
if(nc->js.max.x == 0)
|
||||
nc->js.max.x = 223;
|
||||
if(nc->js.min.x == 0)
|
||||
nc->js.min.x = 27;
|
||||
if(nc->js.center.x == 0)
|
||||
nc->js.center.x = 126;
|
||||
if(nc->js.max.y == 0)
|
||||
nc->js.max.y = 222;
|
||||
if(nc->js.min.y == 0)
|
||||
nc->js.min.y = 30;
|
||||
if(nc->js.center.y == 0)
|
||||
nc->js.center.y = 131;
|
||||
|
||||
wm->event = WIIUSE_NUNCHUK_INSERTED;
|
||||
wm->exp.type = EXP_NUNCHUK;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The nunchuk disconnected.
|
||||
*
|
||||
* @param nc A pointer to a nunchuk_t structure.
|
||||
*/
|
||||
void nunchuk_disconnected(struct nunchuk_t* nc)
|
||||
{
|
||||
//printf("nunchuk_disconnected()\n");
|
||||
memset(nc, 0, sizeof(struct nunchuk_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle nunchuk event.
|
||||
*
|
||||
* @param nc A pointer to a nunchuk_t structure.
|
||||
* @param msg The message specified in the event packet.
|
||||
*/
|
||||
void nunchuk_event(struct nunchuk_t* nc, ubyte* msg) {
|
||||
//int i;
|
||||
|
||||
/* decrypt data */
|
||||
/*
|
||||
for (i = 0; i < 6; ++i)
|
||||
msg[i] = (msg[i] ^ 0x17) + 0x17;
|
||||
*/
|
||||
/* get button states */
|
||||
nunchuk_pressed_buttons(nc, msg[5]);
|
||||
|
||||
nc->js.pos.x = msg[0];
|
||||
nc->js.pos.y = msg[1];
|
||||
|
||||
/* extend min and max values to physical range of motion */
|
||||
if (nc->js.center.x) {
|
||||
if (nc->js.min.x > nc->js.pos.x) nc->js.min.x = nc->js.pos.x;
|
||||
if (nc->js.max.x < nc->js.pos.x) nc->js.max.x = nc->js.pos.x;
|
||||
}
|
||||
if (nc->js.center.y) {
|
||||
if (nc->js.min.y > nc->js.pos.y) nc->js.min.y = nc->js.pos.y;
|
||||
if (nc->js.max.y < nc->js.pos.y) nc->js.max.y = nc->js.pos.y;
|
||||
}
|
||||
|
||||
#ifndef GEKKO
|
||||
/* calculate joystick state */
|
||||
calc_joystick_state(&nc->js, nc->js.pos.x, nc->js.pos.y);
|
||||
#endif
|
||||
/* calculate orientation */
|
||||
nc->accel.x = (msg[2]<<2) + ((msg[5]>>2)&3);
|
||||
nc->accel.y = (msg[3]<<2) + ((msg[5]>>4)&3);
|
||||
nc->accel.z = (msg[4]<<2) + ((msg[5]>>6)&3);
|
||||
#ifndef GEKKO
|
||||
calculate_orientation(&nc->accel_calib, &nc->accel, &nc->orient, NUNCHUK_IS_FLAG_SET(nc, WIIUSE_SMOOTHING));
|
||||
calculate_gforce(&nc->accel_calib, &nc->accel, &nc->gforce);
|
||||
#endif
|
||||
}
|
||||
|
18
wii/wiiuse/nunchuk.h
Normal file
18
wii/wiiuse/nunchuk.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef __NUNCHUK_H__
|
||||
#define __NUNCHUK_H__
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, ubyte* data, uword len);
|
||||
void nunchuk_disconnected(struct nunchuk_t* nc);
|
||||
void nunchuk_event(struct nunchuk_t* nc, ubyte* msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
28
wii/wiiuse/os.h
Normal file
28
wii/wiiuse/os.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef __OS_H__
|
||||
#define __OS_H__
|
||||
|
||||
#ifdef WIN32
|
||||
/* windows */
|
||||
#define isnan(x) _isnan(x)
|
||||
#define isinf(x) !_finite(x)
|
||||
|
||||
/* disable warnings I don't care about */
|
||||
#pragma warning(disable:4244) /* possible loss of data conversion */
|
||||
#pragma warning(disable:4273) /* inconsistent dll linkage */
|
||||
#pragma warning(disable:4217)
|
||||
#else
|
||||
/* nix/gekko */
|
||||
#ifdef GEKKO
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <bte/bte.h>
|
||||
#include "network.h"
|
||||
#include <ogc/lwp_queue.h>
|
||||
#include <ogc/machine/asm.h>
|
||||
#include <ogc/machine/processor.h>
|
||||
#include <ogc/lwp_wkspace.h>
|
||||
#else
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
142
wii/wiiuse/speaker.c
Normal file
142
wii/wiiuse/speaker.c
Normal file
@ -0,0 +1,142 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef GEKKO
|
||||
#include <ogcsys.h>
|
||||
#endif
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "speaker.h"
|
||||
|
||||
#define WENCMIN(a,b) ((a)>(b)?(b):(a))
|
||||
#define ABS(x) ((s32)(x)>0?(s32)(x):-((s32)(x)))
|
||||
|
||||
static const int yamaha_indexscale[] = {
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
230, 230, 230, 230, 307, 409, 512, 614
|
||||
};
|
||||
|
||||
static const int yamaha_difflookup[] = {
|
||||
1, 3, 5, 7, 9, 11, 13, 15,
|
||||
-1, -3, -5, -7, -9, -11, -13, -15
|
||||
};
|
||||
|
||||
static ubyte __wiiuse_speaker_vol = 0x40;
|
||||
static ubyte __wiiuse_speaker_defconf[7] = { 0x00,0x00,0xD0,0x07,0x40,0x0C,0x0E };
|
||||
|
||||
static __inline__ short wenc_clip_short(int a)
|
||||
{
|
||||
if((a+32768)&~65535) return (a>>31)^32767;
|
||||
else return a;
|
||||
}
|
||||
|
||||
static __inline__ int wenc_clip(int a,int amin,int amax)
|
||||
{
|
||||
if(a<amin) return amin;
|
||||
else if(a>amax) return amax;
|
||||
else return a;
|
||||
}
|
||||
|
||||
ubyte wencdata(WENCStatus *info,short sample)
|
||||
{
|
||||
int nibble,delta;
|
||||
|
||||
if(!info->step) {
|
||||
info->predictor = 0;
|
||||
info->step = 127;
|
||||
}
|
||||
|
||||
delta = sample - info->predictor;
|
||||
nibble = WENCMIN(7,(ABS(delta)*4)/info->step) + ((delta<0)*8);
|
||||
|
||||
info->predictor += ((info->step*yamaha_difflookup[nibble])/8);
|
||||
info->predictor = wenc_clip_short(info->predictor);
|
||||
info->step = (info->step*yamaha_indexscale[nibble])>>8;
|
||||
info->step = wenc_clip(info->step,127,24576);
|
||||
|
||||
return nibble;
|
||||
}
|
||||
|
||||
void wiiuse_set_speaker(struct wiimote_t *wm,int status)
|
||||
{
|
||||
ubyte conf[7];
|
||||
ubyte buf = 0x00;
|
||||
|
||||
if(!wm) return;
|
||||
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
|
||||
WIIUSE_DEBUG("Tried to enable speaker, will wait until handshake finishes.\n");
|
||||
if(status)
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_SPEAKER_INIT);
|
||||
else
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_SPEAKER_INIT);
|
||||
return;
|
||||
}
|
||||
|
||||
if(status) {
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER)) {
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER)) {
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
buf = 0x04;
|
||||
wiiuse_sendcmd(wm,WM_CMD_SPEAKER_MUTE,&buf,1,NULL);
|
||||
|
||||
if (!status) {
|
||||
WIIUSE_DEBUG("Disabled speaker for wiimote id %i.", wm->unid);
|
||||
|
||||
buf = 0x01;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_REG1,&buf,1,NULL);
|
||||
|
||||
buf = 0x00;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_REG3,&buf,1,NULL);
|
||||
|
||||
buf = 0x00;
|
||||
wiiuse_sendcmd(wm,WM_CMD_SPEAKER_ENABLE,&buf,1,NULL);
|
||||
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(conf,__wiiuse_speaker_defconf,7);
|
||||
|
||||
buf = 0x04;
|
||||
wiiuse_sendcmd(wm,WM_CMD_SPEAKER_ENABLE,&buf,1,NULL);
|
||||
|
||||
buf = 0x01;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_REG3,&buf,1,NULL);
|
||||
|
||||
buf = 0x08;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_REG1,&buf,1,NULL);
|
||||
|
||||
conf[2] = 0xd0;
|
||||
conf[3] = 0x07;
|
||||
conf[4] = __wiiuse_speaker_vol;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_BLOCK,conf,7,NULL);
|
||||
|
||||
buf = 0x01;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_REG2,&buf,1,NULL);
|
||||
|
||||
buf = 0x00;
|
||||
wiiuse_sendcmd(wm,WM_CMD_SPEAKER_MUTE,&buf,1,NULL);
|
||||
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
void set_speakervol(struct wiimote_t *wm,ubyte vol)
|
||||
{
|
||||
__wiiuse_speaker_vol = vol;
|
||||
}
|
30
wii/wiiuse/speaker.h
Normal file
30
wii/wiiuse/speaker.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef __SPEAKER_H__
|
||||
#define __SPEAKER_H__
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _wencstatus
|
||||
{
|
||||
s32 predictor;
|
||||
s16 step_index;
|
||||
s32 step;
|
||||
s32 prev_sample;
|
||||
s16 sample1;
|
||||
s16 sample2;
|
||||
s32 coeff1;
|
||||
s32 coeff2;
|
||||
s32 idelta;
|
||||
} WENCStatus;
|
||||
|
||||
u8 wencdata(WENCStatus *info,s16 sample);
|
||||
void set_speakervol(struct wiimote_t *wm,ubyte vol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
330
wii/wiiuse/wiiuse.c
Normal file
330
wii/wiiuse/wiiuse.c
Normal file
@ -0,0 +1,330 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <Winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "io.h"
|
||||
|
||||
static struct wiimote_t** __wm = NULL;
|
||||
|
||||
void wiiuse_send_next_command(struct wiimote_t *wm)
|
||||
{
|
||||
struct cmd_blk_t *cmd = wm->cmd_head;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
|
||||
|
||||
if(!cmd) return;
|
||||
if(cmd->state!=CMD_READY) return;
|
||||
|
||||
cmd->state = CMD_SENT;
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) cmd->data[1] |= 0x01;
|
||||
|
||||
WIIUSE_DEBUG("Sending command: %02x %02x", cmd->data[0], cmd->data[1]);
|
||||
wiiuse_io_write(wm,cmd->data,cmd->len);
|
||||
}
|
||||
|
||||
static __inline__ void __wiiuse_push_command(struct wiimote_t *wm,struct cmd_blk_t *cmd)
|
||||
{
|
||||
uint level;
|
||||
|
||||
if(!wm || !cmd) return;
|
||||
|
||||
cmd->next = NULL;
|
||||
cmd->state = CMD_READY;
|
||||
|
||||
_CPU_ISR_Disable(level);
|
||||
if(wm->cmd_head==NULL) {
|
||||
wm->cmd_head = wm->cmd_tail = cmd;
|
||||
wiiuse_send_next_command(wm);
|
||||
} else {
|
||||
wm->cmd_tail->next = cmd;
|
||||
wm->cmd_tail = cmd;
|
||||
}
|
||||
_CPU_ISR_Restore(level);
|
||||
}
|
||||
|
||||
#ifndef GEKKO
|
||||
struct wiimote_t** wiiuse_init(int wiimotes) {
|
||||
#else
|
||||
extern void __wiiuse_sensorbar_enable(int enable);
|
||||
struct wiimote_t** wiiuse_init(int wiimotes, wii_event_cb event_cb) {
|
||||
#endif
|
||||
int i = 0;
|
||||
|
||||
if (!wiimotes)
|
||||
return NULL;
|
||||
|
||||
if (!__wm) {
|
||||
__wm = __lwp_wkspace_allocate(sizeof(struct wiimote_t*) * wiimotes);
|
||||
if(!__wm) return NULL;
|
||||
memset(__wm, 0, sizeof(struct wiimote_t*) * wiimotes);
|
||||
}
|
||||
|
||||
for (i = 0; i < wiimotes; ++i) {
|
||||
if(!__wm[i])
|
||||
__wm[i] = __lwp_wkspace_allocate(sizeof(struct wiimote_t));
|
||||
|
||||
memset(__wm[i], 0, sizeof(struct wiimote_t));
|
||||
__wm[i]->unid = i;
|
||||
|
||||
#if defined(WIN32)
|
||||
__wm[i]->dev_handle = 0;
|
||||
__wm[i]->stack = WIIUSE_STACK_UNKNOWN;
|
||||
__wm[i]->normal_timeout = WIIMOTE_DEFAULT_TIMEOUT;
|
||||
__wm[i]->exp_timeout = WIIMOTE_EXP_TIMEOUT;
|
||||
__wm[i]->timeout = __wm[i]->normal_timeout;
|
||||
#elif defined(GEKKO)
|
||||
__wm[i]->sock = NULL;
|
||||
__wm[i]->bdaddr = *BD_ADDR_ANY;
|
||||
__wm[i]->event_cb = event_cb;
|
||||
wiiuse_init_cmd_queue(__wm[i]);
|
||||
#elif defined(unix)
|
||||
__wm[i]->bdaddr = *BDADDR_ANY;
|
||||
__wm[i]->out_sock = -1;
|
||||
__wm[i]->in_sock = -1;
|
||||
#endif
|
||||
|
||||
__wm[i]->state = WIIMOTE_INIT_STATES;
|
||||
__wm[i]->flags = WIIUSE_INIT_FLAGS;
|
||||
|
||||
__wm[i]->event = WIIUSE_NONE;
|
||||
|
||||
__wm[i]->exp.type = EXP_NONE;
|
||||
|
||||
wiiuse_set_aspect_ratio(__wm[i], WIIUSE_ASPECT_4_3);
|
||||
wiiuse_set_ir_position(__wm[i], WIIUSE_IR_ABOVE);
|
||||
|
||||
__wm[i]->accel_calib.st_alpha = WIIUSE_DEFAULT_SMOOTH_ALPHA;
|
||||
}
|
||||
|
||||
return __wm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set flags for the specified wiimote.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param enable Flags to enable.
|
||||
* @param disable Flags to disable.
|
||||
*
|
||||
* @return The flags set after 'enable' and 'disable' have been applied.
|
||||
*
|
||||
* The values 'enable' and 'disable' may be any flags OR'ed together.
|
||||
* Flags are defined in wiiuse.h.
|
||||
*/
|
||||
int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable) {
|
||||
if (!wm) return 0;
|
||||
|
||||
/* remove mutually exclusive flags */
|
||||
enable &= ~disable;
|
||||
disable &= ~enable;
|
||||
|
||||
wm->flags |= enable;
|
||||
wm->flags &= ~disable;
|
||||
|
||||
return wm->flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set if the wiimote should report motion sensing.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param status 1 to enable, 0 to disable.
|
||||
*
|
||||
* Since reporting motion sensing sends a lot of data,
|
||||
* the wiimote saves power by not transmitting it
|
||||
* by default.
|
||||
*/
|
||||
void wiiuse_motion_sensing(struct wiimote_t* wm, int status)
|
||||
{
|
||||
if (status) {
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_ACC)) return;
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC);
|
||||
} else {
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_ACC)) return;
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC);
|
||||
}
|
||||
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) return;
|
||||
|
||||
wiiuse_status(wm,NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Toggle the state of the rumble.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
*/
|
||||
void wiiuse_toggle_rumble(struct wiimote_t* wm)
|
||||
{
|
||||
if (!wm) return;
|
||||
|
||||
WIIMOTE_TOGGLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) return;
|
||||
|
||||
wiiuse_set_leds(wm,wm->leds,NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the rumble.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param status 1 to enable, 0 to disable.
|
||||
*/
|
||||
void wiiuse_rumble(struct wiimote_t* wm, int status)
|
||||
{
|
||||
if (status && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) return;
|
||||
else if(!status && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) return;
|
||||
wiiuse_toggle_rumble(wm);
|
||||
}
|
||||
|
||||
void wiiuse_set_leds(struct wiimote_t *wm,int leds,cmd_blk_cb cb)
|
||||
{
|
||||
ubyte buf;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
|
||||
|
||||
wm->leds = (leds&0xf0);
|
||||
|
||||
buf = wm->leds;
|
||||
wiiuse_sendcmd(wm,WM_CMD_LED,&buf,1,cb);
|
||||
}
|
||||
|
||||
int wiiuse_set_report_type(struct wiimote_t *wm,cmd_blk_cb cb)
|
||||
{
|
||||
ubyte buf[2];
|
||||
int motion,ir,exp;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
|
||||
|
||||
buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00); /* set to 0x04 for continuous reporting */
|
||||
buf[1] = 0x00;
|
||||
|
||||
motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC) || WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
|
||||
exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP);
|
||||
ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
|
||||
|
||||
if (motion && ir && exp) buf[1] = WM_RPT_BTN_ACC_IR_EXP;
|
||||
else if (motion && exp) buf[1] = WM_RPT_BTN_ACC_EXP;
|
||||
else if (motion && ir) buf[1] = WM_RPT_BTN_ACC_IR;
|
||||
else if (ir && exp) buf[1] = WM_RPT_BTN_IR_EXP;
|
||||
else if (ir) buf[1] = WM_RPT_BTN_ACC_IR;
|
||||
else if (exp) buf[1] = WM_RPT_BTN_EXP;
|
||||
else if (motion) buf[1] = WM_RPT_BTN_ACC;
|
||||
else buf[1] = WM_RPT_BTN;
|
||||
|
||||
//WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]);
|
||||
|
||||
wiiuse_sendcmd(wm,WM_CMD_REPORT_TYPE,buf,2,cb);
|
||||
return buf[1];
|
||||
}
|
||||
|
||||
void wiiuse_status(struct wiimote_t *wm,cmd_blk_cb cb)
|
||||
{
|
||||
ubyte buf;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
|
||||
|
||||
buf = 0x00;
|
||||
wiiuse_sendcmd(wm,WM_CMD_CTRL_STATUS,&buf,1,cb);
|
||||
}
|
||||
|
||||
int wiiuse_read_data(struct wiimote_t *wm,ubyte *buffer,uint addr,uword len,cmd_blk_cb cb)
|
||||
{
|
||||
struct op_t *op;
|
||||
struct cmd_blk_t *cmd;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
|
||||
if(!buffer || !len) return 0;
|
||||
|
||||
cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
|
||||
if(!cmd) return 0;
|
||||
|
||||
cmd->cb = cb;
|
||||
cmd->len = 7;
|
||||
|
||||
op = (struct op_t*)cmd->data;
|
||||
op->cmd = WM_CMD_READ_DATA;
|
||||
op->buffer = buffer;
|
||||
op->wait = len;
|
||||
op->readdata.addr = BIG_ENDIAN_LONG(addr);
|
||||
op->readdata.size = BIG_ENDIAN_SHORT(len);
|
||||
__wiiuse_push_command(wm,cmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int wiiuse_write_data(struct wiimote_t *wm,uint addr,ubyte *data,ubyte len,cmd_blk_cb cb)
|
||||
{
|
||||
struct op_t *op;
|
||||
struct cmd_blk_t *cmd;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
|
||||
if(!data || !len) return 0;
|
||||
|
||||
cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
|
||||
if(!cmd) return 0;
|
||||
|
||||
cmd->cb = cb;
|
||||
cmd->len = 22;
|
||||
|
||||
op = (struct op_t*)cmd->data;
|
||||
op->cmd = WM_CMD_WRITE_DATA;
|
||||
op->buffer = NULL;
|
||||
op->wait = 0;
|
||||
op->writedata.addr = BIG_ENDIAN_LONG(addr);
|
||||
op->writedata.size = (len&0x0f);
|
||||
memcpy(op->writedata.data,data,len);
|
||||
memset(op->writedata.data+len,0,(16 - len));
|
||||
__wiiuse_push_command(wm,cmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int wiiuse_write_streamdata(struct wiimote_t *wm,ubyte *data,ubyte len,cmd_blk_cb cb)
|
||||
{
|
||||
struct cmd_blk_t *cmd;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
|
||||
if(!data || !len || len>20) return 0;
|
||||
|
||||
cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
|
||||
if(!cmd) return 0;
|
||||
|
||||
cmd->cb = cb;
|
||||
cmd->len = 22;
|
||||
cmd->data[0] = WM_CMD_STREAM_DATA;
|
||||
cmd->data[1] = (len<<3);
|
||||
memcpy(cmd->data+2,data,len);
|
||||
__wiiuse_push_command(wm,cmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int wiiuse_sendcmd(struct wiimote_t *wm,ubyte report_type,ubyte *msg,int len,cmd_blk_cb cb)
|
||||
{
|
||||
struct cmd_blk_t *cmd;
|
||||
|
||||
cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
|
||||
if(!cmd) return 0;
|
||||
|
||||
cmd->cb = cb;
|
||||
cmd->len = (1+len);
|
||||
|
||||
cmd->data[0] = report_type;
|
||||
memcpy(cmd->data+1,msg,len);
|
||||
if(report_type!=WM_CMD_READ_DATA && report_type!=WM_CMD_CTRL_STATUS)
|
||||
cmd->data[1] |= 0x02;
|
||||
|
||||
//WIIUSE_DEBUG("Pushing command: %02x %02x", cmd->data[0], cmd->data[1]);
|
||||
__wiiuse_push_command(wm,cmd);
|
||||
|
||||
return 1;
|
||||
}
|
275
wii/wiiuse/wiiuse_internal.h
Normal file
275
wii/wiiuse/wiiuse_internal.h
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This file is part of wiiuse.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/wiiuse_internal.h,v 1.8 2008-12-10 16:16:40 shagkur Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief General internal wiiuse stuff.
|
||||
*
|
||||
* Since Wiiuse is a library, wiiuse.h is a duplicate
|
||||
* of the API header.
|
||||
*
|
||||
* The code that would normally go in that file, but
|
||||
* which is not needed by third party developers,
|
||||
* is put here.
|
||||
*
|
||||
* So wiiuse_internal.h is included by other files
|
||||
* internally, wiiuse.h is included only here.
|
||||
*/
|
||||
|
||||
#ifndef WIIUSE_INTERNAL_H_INCLUDED
|
||||
#define WIIUSE_INTERNAL_H_INCLUDED
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <arpa/inet.h> /* htons() */
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#endif
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
/* wiiuse version */
|
||||
#define WIIUSE_VERSION "0.12"
|
||||
|
||||
/********************
|
||||
*
|
||||
* Wiimote internal codes
|
||||
*
|
||||
********************/
|
||||
|
||||
/* Communication channels */
|
||||
#define WM_OUTPUT_CHANNEL 0x11
|
||||
#define WM_INPUT_CHANNEL 0x13
|
||||
|
||||
#define WM_SET_REPORT 0x50
|
||||
#define WM_DATA 0xA0
|
||||
|
||||
/* commands */
|
||||
#define WM_CMD_RUMBLE 0x10
|
||||
#define WM_CMD_LED 0x11
|
||||
#define WM_CMD_REPORT_TYPE 0x12
|
||||
#define WM_CMD_IR 0x13
|
||||
#define WM_CMD_SPEAKER_ENABLE 0x14
|
||||
#define WM_CMD_CTRL_STATUS 0x15
|
||||
#define WM_CMD_WRITE_DATA 0x16
|
||||
#define WM_CMD_READ_DATA 0x17
|
||||
#define WM_CMD_STREAM_DATA 0x18
|
||||
#define WM_CMD_SPEAKER_MUTE 0x19
|
||||
#define WM_CMD_IR_2 0x1A
|
||||
|
||||
/* input report ids */
|
||||
#define WM_RPT_CTRL_STATUS 0x20
|
||||
#define WM_RPT_READ 0x21
|
||||
#define WM_RPT_ACK 0x22
|
||||
#define WM_RPT_BTN 0x30
|
||||
#define WM_RPT_BTN_ACC 0x31
|
||||
#define WM_RPT_BTN_ACC_IR 0x33
|
||||
#define WM_RPT_BTN_EXP 0x34
|
||||
#define WM_RPT_BTN_ACC_EXP 0x35
|
||||
#define WM_RPT_BTN_IR_EXP 0x36
|
||||
#define WM_RPT_BTN_ACC_IR_EXP 0x37
|
||||
|
||||
#define WM_BT_INPUT 0x01
|
||||
#define WM_BT_OUTPUT 0x02
|
||||
|
||||
/* Identify the wiimote device by its class */
|
||||
#define WM_DEV_CLASS_0 0x04
|
||||
#define WM_DEV_CLASS_1 0x25
|
||||
#define WM_DEV_CLASS_2 0x00
|
||||
#define WM_VENDOR_ID 0x057E
|
||||
#define WM_PRODUCT_ID 0x0306
|
||||
|
||||
/* controller status stuff */
|
||||
#define WM_MAX_BATTERY_CODE 0xC8
|
||||
|
||||
/* offsets in wiimote memory */
|
||||
#define WM_MEM_OFFSET_CALIBRATION 0x16
|
||||
#define WM_EXP_MEM_BASE 0x04A40000
|
||||
#define WM_EXP_MEM_ENABLE1 0x04A400F0
|
||||
#define WM_EXP_MEM_ENABLE2 0x04A400FB
|
||||
#define WM_EXP_MEM_KEY 0x04A40040
|
||||
#define WM_EXP_MEM_CALIBR 0x04A40020
|
||||
#define WM_EXP_MOTION_PLUS_ENABLE 0x04A600FE
|
||||
#define WM_EXP_ID 0x04A400FA
|
||||
|
||||
#define WM_REG_IR 0x04B00030
|
||||
#define WM_REG_IR_BLOCK1 0x04B00000
|
||||
#define WM_REG_IR_BLOCK2 0x04B0001A
|
||||
#define WM_REG_IR_MODENUM 0x04B00033
|
||||
|
||||
#define WM_REG_SPEAKER_REG1 0x04A20001
|
||||
#define WM_REG_SPEAKER_REG2 0x04A20008
|
||||
#define WM_REG_SPEAKER_REG3 0x04A20009
|
||||
#define WM_REG_SPEAKER_BLOCK 0x04A20001
|
||||
|
||||
/* ir block data */
|
||||
#define WM_IR_BLOCK1_LEVEL1 "\x02\x00\x00\x71\x01\x00\x64\x00\xfe"
|
||||
#define WM_IR_BLOCK2_LEVEL1 "\xfd\x05"
|
||||
#define WM_IR_BLOCK1_LEVEL2 "\x02\x00\x00\x71\x01\x00\x96\x00\xb4"
|
||||
#define WM_IR_BLOCK2_LEVEL2 "\xb3\x04"
|
||||
#define WM_IR_BLOCK1_LEVEL3 "\x02\x00\x00\x71\x01\x00\xaa\x00\x64"
|
||||
#define WM_IR_BLOCK2_LEVEL3 "\x63\x03"
|
||||
#define WM_IR_BLOCK1_LEVEL4 "\x02\x00\x00\x71\x01\x00\xc8\x00\x36"
|
||||
#define WM_IR_BLOCK2_LEVEL4 "\x35\x03"
|
||||
#define WM_IR_BLOCK1_LEVEL5 "\x07\x00\x00\x71\x01\x00\x72\x00\x20"
|
||||
#define WM_IR_BLOCK2_LEVEL5 "\x1f\x03"
|
||||
|
||||
#define WM_IR_TYPE_BASIC 0x01
|
||||
#define WM_IR_TYPE_EXTENDED 0x03
|
||||
#define WM_IR_TYPE_FULL 0x05
|
||||
|
||||
/* controller status flags for the first message byte */
|
||||
/* bit 1 is unknown */
|
||||
#define WM_CTRL_STATUS_BYTE1_ATTACHMENT 0x02
|
||||
#define WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED 0x04
|
||||
#define WM_CTRL_STATUS_BYTE1_IR_ENABLED 0x08
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_1 0x10
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_2 0x20
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_3 0x40
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_4 0x80
|
||||
|
||||
/* aspect ratio */
|
||||
#define WM_ASPECT_16_9_X 660
|
||||
#define WM_ASPECT_16_9_Y 370
|
||||
#define WM_ASPECT_4_3_X 560
|
||||
#define WM_ASPECT_4_3_Y 420
|
||||
|
||||
|
||||
/**
|
||||
* Expansion stuff
|
||||
*/
|
||||
|
||||
/* encrypted expansion id codes (located at 0x04A400FC) */
|
||||
#define EXP_ID_CODE_NUNCHUK 0xa4200000
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER 0xa4200101
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING 0x90908f00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING2 0x9e9f9c00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING3 0x908f8f00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC 0xa5a2a300
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC2 0x98999900
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC3 0xa0a1a000
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC4 0x8d8d8e00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC5 0x93949400
|
||||
//#define EXP_ID_CODE_GUITAR 0xa4200103
|
||||
//#define EXP_ID_CODE_WIIBOARD 0xa4200402
|
||||
#define EXP_ID_CODE_MOTION_PLUS 0xa4200405
|
||||
|
||||
#define EXP_HANDSHAKE_LEN 224
|
||||
|
||||
/********************
|
||||
*
|
||||
* End Wiimote internal codes
|
||||
*
|
||||
********************/
|
||||
|
||||
/* wiimote state flags - (some duplicated in wiiuse.h)*/
|
||||
#define WIIMOTE_STATE_DEV_FOUND 0x00001
|
||||
//#define WIIMOTE_STATE_DEV_REGISTER 0x00002
|
||||
#define WIIMOTE_STATE_HANDSHAKE 0x00004 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_HANDSHAKE_COMPLETE 0x00008 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_CONNECTED 0x00010
|
||||
#define WIIMOTE_STATE_EXP_HANDSHAKE 0x00020 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_EXP_FAILED 0x00040 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_RUMBLE 0x00080
|
||||
#define WIIMOTE_STATE_ACC 0x00100
|
||||
#define WIIMOTE_STATE_EXP 0x00200
|
||||
#define WIIMOTE_STATE_IR 0x00400
|
||||
#define WIIMOTE_STATE_SPEAKER 0x00800
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL1 0x01000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL2 0x02000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL3 0x04000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL4 0x08000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL5 0x10000
|
||||
#define WIIMOTE_STATE_IR_INIT 0x20000
|
||||
#define WIIMOTE_STATE_SPEAKER_INIT 0x40000
|
||||
|
||||
#define WIIMOTE_INIT_STATES (WIIMOTE_STATE_IR_SENS_LVL3)
|
||||
|
||||
/* macro to manage states */
|
||||
#define WIIMOTE_IS_SET(wm, s) ((wm->state & (s)) == (s))
|
||||
#define WIIMOTE_ENABLE_STATE(wm, s) (wm->state |= (s))
|
||||
#define WIIMOTE_DISABLE_STATE(wm, s) (wm->state &= ~(s))
|
||||
#define WIIMOTE_TOGGLE_STATE(wm, s) ((wm->state & (s)) ? WIIMOTE_DISABLE_STATE(wm, s) : WIIMOTE_ENABLE_STATE(wm, s))
|
||||
|
||||
#define WIIMOTE_IS_FLAG_SET(wm, s) ((wm->flags & (s)) == (s))
|
||||
#define WIIMOTE_ENABLE_FLAG(wm, s) (wm->flags |= (s))
|
||||
#define WIIMOTE_DISABLE_FLAG(wm, s) (wm->flags &= ~(s))
|
||||
#define WIIMOTE_TOGGLE_FLAG(wm, s) ((wm->flags & (s)) ? WIIMOTE_DISABLE_FLAG(wm, s) : WIIMOTE_ENABLE_FLAG(wm, s))
|
||||
|
||||
#define NUNCHUK_IS_FLAG_SET(wm, s) ((*(wm->flags) & (s)) == (s))
|
||||
|
||||
/* misc macros */
|
||||
#define WIIMOTE_ID(wm) (wm->unid)
|
||||
#define WIIMOTE_IS_CONNECTED(wm) (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED))
|
||||
|
||||
/*
|
||||
* Smooth tilt calculations are computed with the
|
||||
* exponential moving average formula:
|
||||
* St = St_last + (alpha * (tilt - St_last))
|
||||
* alpha is between 0 and 1
|
||||
*/
|
||||
#define WIIUSE_DEFAULT_SMOOTH_ALPHA 0.3f
|
||||
|
||||
#define SMOOTH_ROLL 0x01
|
||||
#define SMOOTH_PITCH 0x02
|
||||
|
||||
#include <wiiuse/wiiuse.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct op_t
|
||||
{
|
||||
ubyte cmd;
|
||||
union {
|
||||
struct {
|
||||
uint addr;
|
||||
uword size;
|
||||
} readdata;
|
||||
struct {
|
||||
uint addr;
|
||||
ubyte size;
|
||||
ubyte data[16];
|
||||
} writedata;
|
||||
ubyte __data[MAX_PAYLOAD];
|
||||
};
|
||||
|
||||
void *buffer;
|
||||
int wait;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* not part of the api */
|
||||
void wiiuse_init_cmd_queue(struct wiimote_t *wm);
|
||||
void wiiuse_send_next_command(struct wiimote_t *wm);
|
||||
int wiiuse_set_report_type(struct wiimote_t* wm,cmd_blk_cb cb);
|
||||
int wiiuse_sendcmd(struct wiimote_t *wm,ubyte report_type,ubyte *msg,int len,cmd_blk_cb cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIIUSE_INTERNAL_H_INCLUDED */
|
1242
wii/wiiuse/wpad.c
Normal file
1242
wii/wiiuse/wpad.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user