MAJOR and long ago overdue wiiuse and real wiimote sourcecode cleanup. Removed "recording" in old wiimote plugin and other not necessary functions(EEPROM reading, we 'll just do a reconnect instead to use default accel calibration data etc). Recording is not needed anymore(playback of recorded moves should be still working). Everything the recording feature offered, the new wiimote plugin does as well and even more. The cleanup will ease the port of the real wiimote feature into new wiimote plugin, which is still only offering emulated wiimote support. Billiard said he's now on it.:)

Wiimotes are now slighty more responsive and multiple wiimotes should harmonize now slighty better. This clean up was requested/inevitable and should have be done way more earlier. This "might" break osx/linux builds, so please test. If your aware of any "real wiimote" issues please post it in the comments as well(dont forget to state your OS).

Known wiimote issues:
1.) Possible wiimote disconnect on pressing the home button
2.) 1-2 Possible wiimote disconnects directly after starting a game
3.) Rumble causes lag. I don't think this is a wiimote plugin issue itself, I'm not sure tho. It would be interesting to know whether the lag still happens on emulated wiimotes as well, when the game tries to rumble.
4.) Connecting(pairing up and refreshing) a 2nd/3rd/4th real wiimote while having a game running/paused, might swap player slots and cause disconnects at that moment.
If u have more issues, feel free to post them, to have them all here collected once more to get a brief overview.
Apart from that, increase the wiimote read timeout @settings(20-200). If your  expecting frequent disconnects, restart dolphin, and don't open the wiimote gui before playing instead directly start games.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5788 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
snzgoo 2010-06-26 02:08:30 +00:00
parent 434e6b1198
commit f6d844dac1
37 changed files with 72 additions and 4503 deletions

View File

@ -611,18 +611,11 @@ WIIUSE_EXPORT extern void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes);
WIIUSE_EXPORT extern void wiiuse_rumble(struct wiimote_t* wm, int status);
WIIUSE_EXPORT extern void wiiuse_toggle_rumble(struct wiimote_t* wm);
WIIUSE_EXPORT extern void wiiuse_set_leds(struct wiimote_t* wm, int leds);
WIIUSE_EXPORT extern void wiiuse_motion_sensing(struct wiimote_t* wm, int status);
WIIUSE_EXPORT extern int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int offset, unsigned short len);
WIIUSE_EXPORT extern int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len);
WIIUSE_EXPORT extern void wiiuse_status(struct wiimote_t* wm);
WIIUSE_EXPORT extern struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid);
WIIUSE_EXPORT extern int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable);
WIIUSE_EXPORT extern float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha);
WIIUSE_EXPORT extern void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type);
WIIUSE_EXPORT extern void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold);
WIIUSE_EXPORT extern void wiiuse_resync(struct wiimote_t* wm);
WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout);
WIIUSE_EXPORT extern void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold);
/* connect.c */
WIIUSE_EXPORT extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout);
@ -633,20 +626,11 @@ WIIUSE_EXPORT extern int wiiuse_check_system_notification(unsigned int nMsg, WPA
WIIUSE_EXPORT extern int wiiuse_register_system_notification(HWND hwnd);
#endif
/* events.c */
WIIUSE_EXPORT extern int wiiuse_poll(struct wiimote_t** wm, int wiimotes);
/* ir.c */
WIIUSE_EXPORT extern void wiiuse_set_ir(struct wiimote_t* wm, int status);
WIIUSE_EXPORT extern void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y);
WIIUSE_EXPORT extern void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos);
WIIUSE_EXPORT extern void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect);
WIIUSE_EXPORT extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level);
/* nunchuk.c */
WIIUSE_EXPORT extern void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold);
WIIUSE_EXPORT extern void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold);
/* io.c */
WIIUSE_EXPORT extern int wiiuse_io_read(struct wiimote_t* wm);
WIIUSE_EXPORT extern int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -48,14 +48,9 @@ INCLUDES = -I.
# Generate a list of object files
#
OBJS = \
$(OBJ_DIR)/classic.o \
$(OBJ_DIR)/dynamics.o \
$(OBJ_DIR)/events.o \
$(OBJ_DIR)/io.o \
$(OBJ_DIR)/io_nix.o \
$(OBJ_DIR)/ir.o \
$(OBJ_DIR)/nunchuk.o \
$(OBJ_DIR)/guitar_hero_3.o \
$(OBJ_DIR)/wiiuse.o
###############################

View File

@ -8,14 +8,8 @@ if (env['HAVE_BLUEZ'] != 1 and sys.platform != 'darwin'):
Return()
files = [
"classic.c",
"dynamics.c",
"events.c",
"io.c",
"ir.c",
"nunchuk.c",
"guitar_hero_3.c",
"wiiboard.c",
"wiiuse.c",
]

View File

@ -1,188 +0,0 @@
/*
* 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$
*
*/
/**
* @file
* @brief Classic controller expansion device.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef WIN32
#include <Winsock2.h>
#endif
#include "definitions.h"
#include "wiiuse_internal.h"
#include "dynamics.h"
#include "events.h"
#include "classic.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, byte* data, unsigned short len) {
int i;
int offset = 0;
cc->btns = 0;
cc->btns_held = 0;
cc->btns_released = 0;
cc->r_shoulder = 0;
cc->l_shoulder = 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 */
byte* handshake_buf = (byte *)malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
WIIUSE_DEBUG("Classic controller handshake appears invalid, trying again.");
wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
return 0;
} else
offset += 16;
}
/* joystick stuff */
cc->ljs.max.x = data[0 + offset] / 4;
cc->ljs.min.x = data[1 + offset] / 4;
cc->ljs.center.x = data[2 + offset] / 4;
cc->ljs.max.y = data[3 + offset] / 4;
cc->ljs.min.y = data[4 + offset] / 4;
cc->ljs.center.y = data[5 + offset] / 4;
cc->rjs.max.x = data[6 + offset] / 8;
cc->rjs.min.x = data[7 + offset] / 8;
cc->rjs.center.x = data[8 + offset] / 8;
cc->rjs.max.y = data[9 + offset] / 8;
cc->rjs.min.y = data[10 + offset] / 8;
cc->rjs.center.y = data[11 + offset] / 8;
/* handshake done */
wm->expansion.type = EXP_CLASSIC;
wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
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, byte* 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.
*/
cc->r_shoulder = ((float)cc->rs_raw / 0x1F);
cc->l_shoulder = ((float)cc->ls_raw / 0x1F);
/* 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);
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);
}
/**
* @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;
/* 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;
}

View File

@ -1,53 +0,0 @@
/*
* 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$
*
*/
/**
* @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, byte* data, unsigned short len);
void classic_ctrl_disconnected(struct classic_ctrl_t* cc);
void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg);
#ifdef __cplusplus
}
#endif
#endif // CLASSIC_H_INCLUDED

View File

@ -1,276 +0,0 @@
/*
* 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$
*
*/
/**
* @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 vec3b_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 vec3b_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) {
/* roll */
x = RAD_TO_DEGREE(atan2f(x, z));
orient->roll = x;
orient->a_roll = x;
}
if (abs(accel->y - ac->cal_zero.y) <= ac->cal_g.y) {
/* pitch */
y = RAD_TO_DEGREE(atan2f(y, z));
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 vec3b_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 vec3b_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;
}
}
}
void calc_balanceboard_state(struct wii_board_t *wb)
{
/*
Interpolate values
Calculations borrowed from wiili.org - No names to mention sadly :( http://www.wiili.org/index.php/Wii_Balance_Board_PC_Drivers
*/
if(wb->rtr<wb->ctr[1])
{
wb->tr = 17.0f*(float)(wb->rtr-wb->ctr[0])/(float)(wb->ctr[1]-wb->ctr[0]);
}
else
{
wb->tr = 17.0f*(float)(wb->rtr-wb->ctr[1])/(float)(wb->ctr[2]-wb->ctr[1]) + 17.0f;
}
if(wb->rtl<wb->ctl[1])
{
wb->tl = 17.0f*(float)(wb->rtl-wb->ctl[0])/(float)(wb->ctl[1]-wb->ctl[0]);
}
else
{
wb->tl = 17.0f*(float)(wb->rtl-wb->ctl[1])/(float)(wb->ctl[2]-wb->ctl[1]) + 17.0f;
}
if(wb->rbr<wb->cbr[1])
{
wb->br = 17.0f*(float)(wb->rbr-wb->cbr[0])/(float)(wb->cbr[1]-wb->cbr[0]);
}
else
{
wb->br = 17.0f*(float)(wb->rbr-wb->cbr[1])/(float)(wb->cbr[2]-wb->cbr[1]) + 17.0f;
}
if(wb->rbl<wb->cbl[1])
{
wb->bl = 17.0f*(float)(wb->rbl-wb->cbl[0])/(float)(wb->cbl[1]-wb->cbl[0]);
}
else
{
wb->bl = 17.0f*(float)(wb->rbl-wb->cbl[1])/(float)(wb->cbl[2]-wb->cbl[1]) + 17.0f;
}
wb->x = (wb->tr+wb->br) - (wb->tl+wb->bl)/2.0f;
wb->y = (wb->bl+wb->br) - (wb->tl+wb->tr)/2.0f;
}

View File

@ -1,57 +0,0 @@
/*
* 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$
*
*/
/**
* @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 vec3b_t* accel, struct orient_t* orient, int smooth);
void calculate_gforce(struct accel_t* ac, struct vec3b_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);
void calc_balanceboard_state(struct wii_board_t *wb);
#ifdef __cplusplus
}
#endif
#endif // DYNAMICS_H_INCLUDED

View File

@ -1,810 +0,0 @@
/*
* 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$
*
*/
/**
* @file
* @brief Handles wiimote events.
*
* The file includes functions that handle the events
* that are sent from the wiimote to us.
*/
#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 "definitions.h"
#include "io.h"
#include "wiiuse_internal.h"
#include "dynamics.h"
#include "ir.h"
#include "nunchuk.h"
#include "classic.h"
#include "guitar_hero_3.h"
#include "wiiboard.h"
#include "events.h"
static void idle_cycle(struct wiimote_t* wm);
static void clear_dirty_reads(struct wiimote_t* wm);
static void propagate_event(struct wiimote_t* wm, byte event, byte* msg);
static void event_data_read(struct wiimote_t* wm, byte* msg);
static void event_status(struct wiimote_t* wm, byte* msg);
static void handle_expansion(struct wiimote_t* wm, byte* msg);
static void save_state(struct wiimote_t* wm);
static int state_changed(struct wiimote_t* wm);
/**
* @brief Poll the wiimotes for any events.
*
* @param wm An array of pointers to wiimote_t structures.
* @param wiimotes The number of wiimote_t structures in the \a wm array.
*
* @return Returns number of wiimotes that an event has occured on.
*
* It is necessary to poll the wiimote devices for events
* that occur. If an event occurs on a particular wiimote,
* the event variable will be set.
*/
int wiiuse_poll(struct wiimote_t** wm, int wiimotes) {
int evnt = 0;
/*
* Windows, Unix and Apple
*/
int i;
if (!wm) return 0;
for (i = 0; i < wiimotes; ++i) {
wm[i]->event = WIIUSE_NONE;
if (wiiuse_io_read(wm[i])) {
/* propagate the event */
propagate_event(wm[i], wm[i]->event_buf[1], wm[i]->event_buf+2);
evnt += (wm[i]->event != WIIUSE_NONE);
/* clear out the event buffer */
memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf));
} else {
idle_cycle(wm[i]);
}
}
return evnt;
}
/**
* @brief Called on a cycle where no significant change occurs.
*
* @param wm Pointer to a wiimote_t structure.
*/
static 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.
*/
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);
}
/* clear out any old read requests */
clear_dirty_reads(wm);
}
/**
* @brief Clear out all old 'dirty' read requests.
*
* @param wm Pointer to a wiimote_t structure.
*/
static void clear_dirty_reads(struct wiimote_t* wm) {
struct read_req_t* req = wm->read_req;
while (req && req->dirty) {
WIIUSE_DEBUG("Cleared old read request for address: %x", req->addr);
wm->read_req = req->next;
free(req);
req = wm->read_req;
}
}
/**
* @brief Analyze the event that occured on a wiimote.
*
* @param wm An array of pointers to wiimote_t structures.
* @param event The event that occured.
* @param msg The message specified in the event packet.
*
* Pass the event to the registered event callback.
*/
static void propagate_event(struct wiimote_t* wm, byte event, byte* msg) {
save_state(wm);
switch (event) {
case WM_RPT_BTN:
{
/* button */
wiiuse_pressed_buttons(wm, msg);
break;
}
case WM_RPT_BTN_ACC:
{
/* button - motion */
wiiuse_pressed_buttons(wm, msg);
wm->accel.x = msg[2];
wm->accel.y = msg[3];
wm->accel.z = msg[4];
/* 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);
break;
}
case WM_RPT_READ:
{
/* data read */
event_data_read(wm, msg);
/* yeah buttons may be pressed, but this wasn't an "event" */
return;
}
case WM_RPT_CTRL_STATUS:
{
/* controller status */
event_status(wm, msg);
/* don't execute the event callback */
return;
}
case WM_RPT_BTN_EXP:
{
/* button - expansion */
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];
wm->accel.y = msg[3];
wm->accel.z = msg[4];
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);
handle_expansion(wm, msg+5);
break;
}
case WM_RPT_BTN_ACC_IR:
{
/* button - motion - ir */
wiiuse_pressed_buttons(wm, msg);
wm->accel.x = msg[2];
wm->accel.y = msg[3];
wm->accel.z = msg[4];
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);
/* ir */
calculate_extended_ir(wm, msg+5);
break;
}
case WM_RPT_BTN_IR_EXP:
{
/* button - ir - expansion */
wiiuse_pressed_buttons(wm, msg);
handle_expansion(wm, msg+12);
/* ir */
calculate_basic_ir(wm, msg+2);
break;
}
case WM_RPT_BTN_ACC_IR_EXP:
{
/* button - motion - ir - expansion */
wiiuse_pressed_buttons(wm, msg);
wm->accel.x = msg[2];
wm->accel.y = msg[3];
wm->accel.z = msg[4];
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);
handle_expansion(wm, msg+15);
/* ir */
calculate_basic_ir(wm, msg+5);
break;
}
case WM_RPT_WRITE:
{
/* write feedback - safe to skip */
break;
}
default:
{
WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event);
return;
}
}
/* was there an event? */
if (state_changed(wm))
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, byte* msg) {
short now;
/* convert to big endian */
now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL;
/* 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;
}
/**
* @brief Received a data packet from a read request.
*
* @param wm Pointer to a wiimote_t structure.
* @param msg The message specified in the event packet.
*
* Data from the wiimote comes in packets. If the requested
* data segment size is bigger than one packet can hold then
* several packets will be received. These packets are first
* reassembled into one, then the registered callback function
* that handles data reads is invoked.
*/
static void event_data_read(struct wiimote_t* wm, byte* msg) {
/* we must always assume the packet received is from the most recent request */
byte err;
byte len;
unsigned short offset;
struct read_req_t* req = wm->read_req;
wiiuse_pressed_buttons(wm, msg);
/* find the next non-dirty request */
while (req && req->dirty)
req = req->next;
/* if we don't have a request out then we didn't ask for this packet */
if (!req) {
WIIUSE_WARNING("Received data packet when no request was made.");
return;
}
err = msg[2] & 0x0F;
if (err == 0x08)
WIIUSE_WARNING("Unable to read data - address does not exist.");
else if (err == 0x07)
WIIUSE_WARNING("Unable to read data - address is for write-only registers.");
else if (err)
WIIUSE_WARNING("Unable to read data - unknown error code %x.", err);
if (err) {
/* this request errored out, so skip it and go to the next one */
/* delete this request */
wm->read_req = req->next;
free(req);
/* if another request exists send it to the wiimote */
if (wm->read_req)
wiiuse_send_next_pending_read_request(wm);
return;
}
len = ((msg[2] & 0xF0) >> 4) + 1;
offset = BIG_ENDIAN_SHORT(*(unsigned short*)(msg + 3));
req->addr = (req->addr & 0xFFFF);
req->wait -= len;
if (req->wait >= req->size)
/* this should never happen */
req->wait = 0;
WIIUSE_DEBUG("Received read packet:");
WIIUSE_DEBUG(" Packet read offset: %i bytes", offset);
WIIUSE_DEBUG(" Request read offset: %i bytes", req->addr);
WIIUSE_DEBUG(" Read offset into buf: %i bytes", offset - req->addr);
WIIUSE_DEBUG(" Read data size: %i bytes", len);
WIIUSE_DEBUG(" Still need: %i bytes", req->wait);
/* reconstruct this part of the data */
memcpy((req->buf + offset - req->addr), (msg + 5), len);
#ifdef WITH_WIIUSE_DEBUG
{
int i = 0;
printf("Read: ");
for (; i < req->size - req->wait; ++i)
printf("%x ", req->buf[i]);
printf("\n");
}
#endif
/* if all data has been received, execute the read event callback or generate event */
if (!req->wait) {
if (req->cb) {
/* this was a callback, so invoke it now */
req->cb(wm, req->buf, req->size);
/* delete this request */
wm->read_req = req->next;
free(req);
} else {
/*
* This should generate an event.
* We need to leave the event in the array so the client
* can access it still. We'll flag is as being 'dirty'
* and give the client one cycle to use it. Next event
* we will remove it from the list.
*/
wm->event = WIIUSE_READ_DATA;
req->dirty = 1;
}
/* if another request exists send it to the wiimote */
if (wm->read_req)
wiiuse_send_next_pending_read_request(wm);
}
}
/**
* @brief Read the controller status.
*
* @param wm Pointer to a wiimote_t structure.
* @param msg The message specified in the event packet.
*
* Read the controller status and execute the registered status callback.
*/
static void event_status(struct wiimote_t* wm, byte* msg) {
int led[4] = {0};
int attachment = 0;
int ir = 0;
int exp_changed = 0;
/*
* An event occured.
* This event can be overwritten by a more specific
* event type during a handshake or expansion removal.
*/
wm->event = WIIUSE_STATUS;
wiiuse_pressed_buttons(wm, msg);
/* find what LEDs are lit */
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;
/* is an attachment connected to the expansion port? */
if ((msg[2] & WM_CTRL_STATUS_BYTE1_ATTACHMENT) == WM_CTRL_STATUS_BYTE1_ATTACHMENT)
attachment = 1;
/* is the speaker enabled? */
if ((msg[2] & WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED) == WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED)
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_SPEAKER);
/* is IR sensing enabled? */
if ((msg[2] & WM_CTRL_STATUS_BYTE1_IR_ENABLED) == WM_CTRL_STATUS_BYTE1_IR_ENABLED)
ir = 1;
/* find the battery level and normalize between 0 and 1 */
wm->battery_level = (msg[5] / (float)WM_MAX_BATTERY_CODE);
/* expansion port */
if (attachment && !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
/* send the initialization code for the attachment */
handshake_expansion(wm, NULL, 0);
exp_changed = 1;
} else if (!attachment && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
/* attachment removed */
disable_expansion(wm);
exp_changed = 1;
}
if (!attachment) {
WIIUSE_DEBUG("Setting timeout to normal %i ms.", wm->normal_timeout);
wm->timeout = wm->normal_timeout;
}
/*
* From now on the remote will only send status packets.
* We need to send a WIIMOTE_CMD_REPORT_TYPE packet to
* reenable other incoming reports.
*/
if (exp_changed && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
/*
* Since the expansion status changed IR needs to
* be reset for the new IR report mode.
*/
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
wiiuse_set_ir(wm, 1);
} else
wiiuse_set_report_type(wm);
}
/**
* @brief Handle data from the expansion.
*
* @param wm A pointer to a wiimote_t structure.
* @param msg The message specified in the event packet for the expansion.
*/
static void handle_expansion(struct wiimote_t* wm, byte* msg) {
switch (wm->expansion.type) {
case EXP_NUNCHUK:
nunchuk_event(&wm->expansion.nunchuk, msg);
break;
case EXP_CLASSIC:
classic_ctrl_event(&wm->expansion.classic, msg);
break;
case EXP_GUITAR_HERO_3:
guitar_hero_3_event(&wm->expansion.gh3, msg);
break;
case EXP_WII_BOARD:
wii_board_event(&wm->expansion.wb, msg);
break;
default:
break;
}
}
/**
* @brief Handle the handshake data from the expansion device.
*
* @param wm A pointer to a wiimote_t structure.
* @param data The data read in from the device.
* @param len The length of the data block, in bytes.
*
* Tries to determine what kind of expansion was attached
* and invoke the correct handshake function.
*
* If the data is NULL then this function will try to start
* a handshake with the expansion.
*/
void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len) {
int wid;
if (!data) {
byte* handshake_buf;
byte buf = 0x00;
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
disable_expansion(wm);
/* increase the timeout until the handshake completes */
WIIUSE_DEBUG("Setting timeout to expansion %i ms.", wm->exp_timeout);
wm->timeout = wm->exp_timeout;
wiiuse_write_data(wm, WM_EXP_MEM_ENABLE, &buf, 1);
/* get the calibration data */
handshake_buf = (byte *)malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
/* tell the wiimote to send expansion data */
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP);
return;
}
wid = BIG_ENDIAN_LONG(*(int*)(data + 220));
/* call the corresponding handshake function for this expansion */
switch (wid) {
case EXP_ID_CODE_NUNCHUK:
{
if (nunchuk_handshake(wm, &wm->expansion.nunchuk, data, len))
wm->event = WIIUSE_NUNCHUK_INSERTED;
break;
}
case EXP_ID_CODE_CLASSIC_CONTROLLER:
{
if (classic_ctrl_handshake(wm, &wm->expansion.classic, data, len))
wm->event = WIIUSE_CLASSIC_CTRL_INSERTED;
break;
}
case EXP_ID_CODE_GUITAR:
{
if (guitar_hero_3_handshake(wm, &wm->expansion.gh3, data, len))
wm->event = WIIUSE_GUITAR_HERO_3_CTRL_INSERTED;
break;
}
case EXP_ID_CODE_WII_BOARD:
{
if (wii_board_handshake(wm, &wm->expansion.wb, data, len))
wm->event = WIIUSE_WII_BOARD_CTRL_INSERTED;
break;
}
default:
{
WIIUSE_WARNING("Unknown expansion type. Code: 0x%x", wid);
break;
}
}
free(data);
}
/**
* @brief Disable the expansion device if it was enabled.
*
* @param wm A pointer to a wiimote_t structure.
* @param data The data read in from the device.
* @param len The length of the data block, in bytes.
*
* If the data is NULL then this function will try to start
* a handshake with the expansion.
*/
void disable_expansion(struct wiimote_t* wm) {
if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
return;
/* tell the assoicated module the expansion was removed */
switch (wm->expansion.type) {
case EXP_NUNCHUK:
nunchuk_disconnected(&wm->expansion.nunchuk);
wm->event = WIIUSE_NUNCHUK_REMOVED;
break;
case EXP_CLASSIC:
classic_ctrl_disconnected(&wm->expansion.classic);
wm->event = WIIUSE_CLASSIC_CTRL_REMOVED;
break;
case EXP_GUITAR_HERO_3:
guitar_hero_3_disconnected(&wm->expansion.gh3);
wm->event = WIIUSE_GUITAR_HERO_3_CTRL_REMOVED;
break;
case EXP_WII_BOARD:
wii_board_disconnected(&wm->expansion.wb);
wm->event = WIIUSE_WII_BOARD_CTRL_REMOVED;
break;
default:
break;
}
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
wm->expansion.type = EXP_NONE;
}
/**
* @brief Save important state data.
* @param wm A pointer to a wiimote_t structure.
*/
static void save_state(struct wiimote_t* wm) {
/* wiimote */
wm->lstate.btns = wm->btns;
wm->lstate.accel = wm->accel;
/* ir */
if (WIIUSE_USING_IR(wm)) {
wm->lstate.ir_ax = wm->ir.ax;
wm->lstate.ir_ay = wm->ir.ay;
wm->lstate.ir_distance = wm->ir.distance;
}
/* expansion */
switch (wm->expansion.type) {
case EXP_NUNCHUK:
wm->lstate.exp_ljs_ang = wm->expansion.nunchuk.js.ang;
wm->lstate.exp_ljs_mag = wm->expansion.nunchuk.js.mag;
wm->lstate.exp_btns = wm->expansion.nunchuk.btns;
wm->lstate.exp_accel = wm->expansion.nunchuk.accel;
break;
case EXP_CLASSIC:
wm->lstate.exp_ljs_ang = wm->expansion.classic.ljs.ang;
wm->lstate.exp_ljs_mag = wm->expansion.classic.ljs.mag;
wm->lstate.exp_rjs_ang = wm->expansion.classic.rjs.ang;
wm->lstate.exp_rjs_mag = wm->expansion.classic.rjs.mag;
wm->lstate.exp_r_shoulder = wm->expansion.classic.r_shoulder;
wm->lstate.exp_l_shoulder = wm->expansion.classic.l_shoulder;
wm->lstate.exp_btns = wm->expansion.classic.btns;
break;
case EXP_GUITAR_HERO_3:
wm->lstate.exp_ljs_ang = wm->expansion.gh3.js.ang;
wm->lstate.exp_ljs_mag = wm->expansion.gh3.js.mag;
wm->lstate.exp_r_shoulder = wm->expansion.gh3.whammy_bar;
wm->lstate.exp_btns = wm->expansion.gh3.btns;
break;
case EXP_NONE:
break;
}
}
/**
* @brief Determine if the current state differs significantly from the previous.
* @param wm A pointer to a wiimote_t structure.
* @return 1 if a significant change occured, 0 if not.
*/
static int state_changed(struct wiimote_t* wm) {
#define STATE_CHANGED(a, b) if (a != b) return 1
#define CROSS_THRESH(last, now, thresh) \
do { \
if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) { \
if ((diff_f(last.roll, now.roll) >= thresh) || \
(diff_f(last.pitch, now.pitch) >= thresh) || \
(diff_f(last.yaw, now.yaw) >= thresh)) \
{ \
last = now; \
return 1; \
} \
} else { \
if (last.roll != now.roll) return 1; \
if (last.pitch != now.pitch) return 1; \
if (last.yaw != now.yaw) return 1; \
} \
} while (0)
#define CROSS_THRESH_XYZ(last, now, thresh) \
do { \
if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) { \
if ((diff_f(last.x, now.x) >= thresh) || \
(diff_f(last.y, now.y) >= thresh) || \
(diff_f(last.z, now.z) >= thresh)) \
{ \
last = now; \
return 1; \
} \
} else { \
if (last.x != now.x) return 1; \
if (last.y != now.y) return 1; \
if (last.z != now.z) return 1; \
} \
} while (0)
/* ir */
if (WIIUSE_USING_IR(wm)) {
STATE_CHANGED(wm->lstate.ir_ax, wm->ir.ax);
STATE_CHANGED(wm->lstate.ir_ay, wm->ir.ay);
STATE_CHANGED(wm->lstate.ir_distance, wm->ir.distance);
}
/* accelerometer */
if (WIIUSE_USING_ACC(wm)) {
/* raw accelerometer */
CROSS_THRESH_XYZ(wm->lstate.accel, wm->accel, wm->accel_threshold);
/* orientation */
CROSS_THRESH(wm->lstate.orient, wm->orient, wm->orient_threshold);
}
/* expansion */
switch (wm->expansion.type) {
case EXP_NUNCHUK:
{
STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->expansion.nunchuk.js.ang);
STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->expansion.nunchuk.js.mag);
STATE_CHANGED(wm->lstate.exp_btns, wm->expansion.nunchuk.btns);
CROSS_THRESH(wm->lstate.exp_orient, wm->expansion.nunchuk.orient, wm->expansion.nunchuk.orient_threshold);
CROSS_THRESH_XYZ(wm->lstate.exp_accel, wm->expansion.nunchuk.accel, wm->expansion.nunchuk.accel_threshold);
break;
}
case EXP_CLASSIC:
{
STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->expansion.classic.ljs.ang);
STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->expansion.classic.ljs.mag);
STATE_CHANGED(wm->lstate.exp_rjs_ang, wm->expansion.classic.rjs.ang);
STATE_CHANGED(wm->lstate.exp_rjs_mag, wm->expansion.classic.rjs.mag);
STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->expansion.classic.r_shoulder);
STATE_CHANGED(wm->lstate.exp_l_shoulder, wm->expansion.classic.l_shoulder);
STATE_CHANGED(wm->lstate.exp_btns, wm->expansion.classic.btns);
break;
}
case EXP_GUITAR_HERO_3:
{
STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->expansion.gh3.js.ang);
STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->expansion.gh3.js.mag);
STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->expansion.gh3.whammy_bar);
STATE_CHANGED(wm->lstate.exp_btns, wm->expansion.gh3.btns);
break;
}
case EXP_WII_BOARD:
{
STATE_CHANGED(wm->expansion.wb.ltr,wm->expansion.wb.tr);
STATE_CHANGED(wm->expansion.wb.ltl,wm->expansion.wb.tl);
STATE_CHANGED(wm->expansion.wb.lbr,wm->expansion.wb.br);
STATE_CHANGED(wm->expansion.wb.lbl,wm->expansion.wb.bl);
break;
}
case EXP_NONE:
{
break;
}
}
STATE_CHANGED(wm->lstate.btns, wm->btns);
return 0;
}

View File

@ -1,54 +0,0 @@
/*
* 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$
*
*/
/**
* @file
* @brief Handles wiimote events.
*
* The file includes functions that handle the events
* that are sent from the wiimote to us.
*/
#ifndef EVENTS_H_INCLUDED
#define EVENTS_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg);
void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len);
void disable_expansion(struct wiimote_t* wm);
#ifdef __cplusplus
}
#endif
#endif // EVENTS_H_INCLUDED

View File

@ -1,177 +0,0 @@
/*
* 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$
*
*/
/**
* @file
* @brief Guitar Hero 3 expansion device.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef WIN32
#include <Winsock2.h>
#endif
#include "definitions.h"
#include "wiiuse_internal.h"
#include "dynamics.h"
#include "events.h"
#include "guitar_hero_3.h"
static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now);
/**
* @brief Handle the handshake data from the guitar.
*
* @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 guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len) {
/*
* The good fellows that made the Guitar Hero 3 controller
* failed to factory calibrate the devices. There is no
* calibration data on the device.
*/
gh3->btns = 0;
gh3->btns_held = 0;
gh3->btns_released = 0;
gh3->wb_raw = 0;
gh3->whammy_bar = 0.0f;
gh3->tb_raw = 0;
gh3->touch_bar = -1;
/* joystick stuff */
gh3->js.max.x = GUITAR_HERO_3_JS_MAX_X;
gh3->js.min.x = GUITAR_HERO_3_JS_MIN_X;
gh3->js.center.x = GUITAR_HERO_3_JS_CENTER_X;
gh3->js.max.y = GUITAR_HERO_3_JS_MAX_Y;
gh3->js.min.y = GUITAR_HERO_3_JS_MIN_Y;
gh3->js.center.y = GUITAR_HERO_3_JS_CENTER_Y;
/* handshake done */
wm->event = WIIUSE_GUITAR_HERO_3_CTRL_INSERTED;
wm->expansion.type = EXP_GUITAR_HERO_3;
wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
return 1;
}
/**
* @brief The guitar disconnected.
*
* @param cc A pointer to a classic_ctrl_t structure.
*/
void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3) {
memset(gh3, 0, sizeof(struct guitar_hero_3_t));
}
/**
* @brief Handle guitar event.
*
* @param cc A pointer to a classic_ctrl_t structure.
* @param msg The message specified in the event packet.
*/
void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg) {
int i;
/* decrypt data */
for (i = 0; i < 6; ++i)
msg[i] = (msg[i] ^ 0x17) + 0x17;
guitar_hero_3_pressed_buttons(gh3, BIG_ENDIAN_SHORT(*(short*)(msg + 4)));
gh3->js.pos.x = (msg[0] & GUITAR_HERO_3_JS_MASK);
gh3->js.pos.y = (msg[1] & GUITAR_HERO_3_JS_MASK);
gh3->tb_raw = (msg[2] & GUITAR_HERO_3_TOUCH_MASK);
gh3->wb_raw = (msg[3] & GUITAR_HERO_3_WHAMMY_MASK);
/* touch bar */
gh3->touch_bar = 0;
if (gh3->tb_raw > 0x1B)
gh3->touch_bar = GUITAR_HERO_3_TOUCH_ORANGE;
else if (gh3->tb_raw > 0x18)
gh3->touch_bar = GUITAR_HERO_3_TOUCH_ORANGE | GUITAR_HERO_3_TOUCH_BLUE;
else if (gh3->tb_raw > 0x15)
gh3->touch_bar = GUITAR_HERO_3_TOUCH_BLUE;
else if (gh3->tb_raw > 0x13)
gh3->touch_bar = GUITAR_HERO_3_TOUCH_BLUE | GUITAR_HERO_3_TOUCH_YELLOW;
else if (gh3->tb_raw > 0x10)
gh3->touch_bar = GUITAR_HERO_3_TOUCH_YELLOW;
else if (gh3->tb_raw > 0x0D)
gh3->touch_bar = GUITAR_HERO_3_TOUCH_AVAILABLE;
else if (gh3->tb_raw > 0x0B)
gh3->touch_bar = GUITAR_HERO_3_TOUCH_YELLOW | GUITAR_HERO_3_TOUCH_RED;
else if (gh3->tb_raw > 0x08)
gh3->touch_bar = GUITAR_HERO_3_TOUCH_RED;
else if (gh3->tb_raw > 0x05)
gh3->touch_bar = GUITAR_HERO_3_TOUCH_RED | GUITAR_HERO_3_TOUCH_GREEN;
else if (gh3->tb_raw > 0x02)
gh3->touch_bar = GUITAR_HERO_3_TOUCH_GREEN;
/* whammy bar */
gh3->whammy_bar = (msg[3] - GUITAR_HERO_3_WHAMMY_BAR_MIN) / (float)(GUITAR_HERO_3_WHAMMY_BAR_MAX - GUITAR_HERO_3_WHAMMY_BAR_MIN);
/* joy stick */
calc_joystick_state(&gh3->js, gh3->js.pos.x, gh3->js.pos.y);
}
/**
* @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 guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now) {
/* message is inverted (0 is active, 1 is inactive) */
now = ~now & GUITAR_HERO_3_BUTTON_ALL;
/* preserve old btns pressed */
gh3->btns_last = gh3->btns;
/* pressed now & were pressed, then held */
gh3->btns_held = (now & gh3->btns);
/* were pressed or were held & not pressed now, then released */
gh3->btns_released = ((gh3->btns | gh3->btns_held) & ~now);
/* buttons pressed now */
gh3->btns = now;
}

View File

@ -1,66 +0,0 @@
/*
* 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$
*
*/
/**
* @file
* @brief Guitar Hero 3 expansion device.
*/
#ifndef GUITAR_HERO_3_H_INCLUDED
#define GUITAR_HERO_3_H_INCLUDED
#include "wiiuse_internal.h"
#define GUITAR_HERO_3_JS_MASK 0x3F
#define GUITAR_HERO_3_TOUCH_MASK 0x1F
#define GUITAR_HERO_3_WHAMMY_MASK 0x1F
#define GUITAR_HERO_3_JS_MIN_X 0x05
#define GUITAR_HERO_3_JS_MAX_X 0x3C
#define GUITAR_HERO_3_JS_CENTER_X 0x20
#define GUITAR_HERO_3_JS_MIN_Y 0x05
#define GUITAR_HERO_3_JS_MAX_Y 0x3A
#define GUITAR_HERO_3_JS_CENTER_Y 0x20
#define GUITAR_HERO_3_WHAMMY_BAR_MIN 0x0F
#define GUITAR_HERO_3_WHAMMY_BAR_MAX 0x1A
#ifdef __cplusplus
extern "C" {
#endif
int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len);
void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3);
void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg);
#ifdef __cplusplus
}
#endif
#endif // GUITAR_HERO_3_H_INCLUDED

View File

@ -95,20 +95,10 @@ void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len) {
accel->cal_g.x, accel->cal_g.y, accel->cal_g.z);
/* request the status of the wiimote to see if there is an expansion */
wiiuse_status(wm);
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
wm->handshake_state++;
/* now enable IR if it was set before the handshake completed */
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
WIIUSE_DEBUG("Handshake finished, enabling IR.");
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
wiiuse_set_ir(wm, 1);
}
break;
}
default:

View File

@ -120,7 +120,7 @@ int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) {
continue;
}
/* do the handshake */
/* do the handshake * shouldn't be needed as well, I'm gonna leave first it tho*/
wiiuse_handshake(wm[found], NULL, 0);
WIIUSE_INFO("Connected to wiimote [id %i].", wm[found]->unid);

View File

@ -40,111 +40,8 @@
#include "definitions.h"
#include "wiiuse_internal.h"
#include "ir.h"
static int get_ir_sens(struct wiimote_t* wm, const char** block1, const char** block2);
static void interpret_ir_data(struct wiimote_t* wm);
static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang);
static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y);
static void reorder_ir_dots(struct ir_dot_t* dot);
static float ir_distance(struct ir_dot_t* dot);
static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y);
static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, unsigned int vx, unsigned int vy);
/**
* @brief Set if the wiimote should track IR targets.
*
* @param wm Pointer to a wiimote_t structure.
* @param status 1 to enable, 0 to disable.
*/
void wiiuse_set_ir(struct wiimote_t* wm, int status) {
byte buf;
const char* block1 = NULL;
const char* block2 = NULL;
int ir_level;
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.");
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
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))
return;
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
} else {
/* if already disabled then stop */
if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
return;
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
}
/* set camera 1 and 2 */
buf = (status ? 0x04 : 0x00);
wiiuse_send(wm, WM_CMD_IR, &buf, 1);
wiiuse_send(wm, WM_CMD_IR_2, &buf, 1);
if (!status) {
WIIUSE_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid);
wiiuse_set_report_type(wm);
return;
}
/* enable IR, set sensitivity */
buf = 0x08;
wiiuse_write_data(wm, WM_REG_IR, &buf, 1);
/* wait for the wiimote to catch up */
#ifndef WIN32
usleep(50000);
#else
Sleep(50);
#endif
/* write sensitivity blocks */
wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9);
wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2);
/* set the IR mode */
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);
#ifndef WIN32
usleep(50000);
#else
Sleep(50);
#endif
/* set the wiimote report type */
wiiuse_set_report_type(wm);
WIIUSE_DEBUG("Enabled IR camera for wiimote id %i (sensitivity level %i).", wm->unid, ir_level);
}
/**
* @brief Get the IR sensitivity settings.
@ -184,19 +81,6 @@ static int get_ir_sens(struct wiimote_t* wm, const char** block1, const char** b
}
/**
* @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.
@ -312,437 +196,3 @@ void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) {
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, byte* 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) {
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 */
}
}
interpret_ir_data(wm);
}
/**
* @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, byte* 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] & 0x0F;
/* if in range set to visible */
if (dot[i].ry == 1023)
dot[i].visible = 0;
else
dot[i].visible = 1;
}
interpret_ir_data(wm);
}
/**
* @brief Interpret IR data into more user friendly variables.
*
* @param wm Pointer to a wiimote_t structure.
*/
static void interpret_ir_data(struct wiimote_t* wm) {
struct ir_dot_t* dot = wm->ir.dot;
int i;
float roll = 0.0f;
int last_num_dots = wm->ir.num_dots;
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC))
roll = wm->orient.roll;
/* count visible dots */
wm->ir.num_dots = 0;
for (i = 0; i < 4; ++i) {
if (dot[i].visible)
wm->ir.num_dots++;
}
switch (wm->ir.num_dots) {
case 0:
{
wm->ir.state = 0;
/* reset the dot ordering */
for (i = 0; i < 4; ++i)
dot[i].order = 0;
wm->ir.x = 0;
wm->ir.y = 0;
wm->ir.z = 0.0f;
return;
}
case 1:
{
fix_rotated_ir_dots(wm->ir.dot, roll);
if (wm->ir.state < 2) {
/*
* Only 1 known dot, so use just that.
*/
for (i = 0; i < 4; ++i) {
if (dot[i].visible) {
wm->ir.x = dot[i].x;
wm->ir.y = dot[i].y;
wm->ir.ax = wm->ir.x;
wm->ir.ay = wm->ir.y;
/* can't calculate yaw because we don't have the distance */
//wm->orient.yaw = calc_yaw(&wm->ir);
ir_convert_to_vres(&wm->ir.x, &wm->ir.y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
break;
}
}
} else {
/*
* Only see 1 dot but know theres 2.
* Try to estimate where the other one
* should be and use that.
*/
for (i = 0; i < 4; ++i) {
if (dot[i].visible) {
int ox = 0;
int x, y;
if (dot[i].order == 1)
/* visible is the left dot - estimate where the right is */
ox = dot[i].x + wm->ir.distance;
else if (dot[i].order == 2)
/* visible is the right dot - estimate where the left is */
ox = dot[i].x - wm->ir.distance;
x = ((signed int)dot[i].x + ox) / 2;
y = dot[i].y;
wm->ir.ax = x;
wm->ir.ay = y;
wm->orient.yaw = calc_yaw(&wm->ir);
if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
wm->ir.x = x;
wm->ir.y = y;
}
break;
}
}
}
break;
}
case 2:
case 3:
case 4:
{
/*
* Two (or more) dots known and seen.
* Average them together to estimate the true location.
*/
int x, y;
wm->ir.state = 2;
fix_rotated_ir_dots(wm->ir.dot, roll);
/* if there is at least 1 new dot, reorder them all */
if (wm->ir.num_dots > last_num_dots) {
reorder_ir_dots(dot);
wm->ir.x = 0;
wm->ir.y = 0;
}
wm->ir.distance = ir_distance(dot);
wm->ir.z = 1023 - wm->ir.distance;
get_ir_dot_avg(wm->ir.dot, &x, &y);
wm->ir.ax = x;
wm->ir.ay = y;
wm->orient.yaw = calc_yaw(&wm->ir);
if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
wm->ir.x = x;
wm->ir.y = y;
}
break;
}
default:
{
break;
}
}
#ifdef WITH_WIIUSE_DEBUG
{
int ir_level;
WIIUSE_GET_IR_SENSITIVITY(wm, &ir_level);
WIIUSE_DEBUG("IR sensitivity: %i", ir_level);
WIIUSE_DEBUG("IR visible dots: %i", wm->ir.num_dots);
for (i = 0; i < 4; ++i)
if (dot[i].visible)
WIIUSE_DEBUG("IR[%i][order %i] (%.3i, %.3i) -> (%.3i, %.3i)", i, dot[i].order, dot[i].rx, dot[i].ry, dot[i].x, dot[i].y);
WIIUSE_DEBUG("IR[absolute]: (%i, %i)", wm->ir.x, wm->ir.y);
}
#endif
}
/**
* @brief Fix the rotation of the IR dots.
*
* @param dot An array of 4 ir_dot_t objects.
* @param ang The roll angle to correct by (-180, 180)
*
* If there is roll then the dots are rotated
* around the origin and give a false cursor
* position. Correct for the roll.
*
* If the accelerometer is off then obviously
* this will not do anything and the cursor
* position may be inaccurate.
*/
static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang) {
float s, c;
int x, y;
int i;
if (!ang) {
for (i = 0; i < 4; ++i) {
dot[i].x = dot[i].rx;
dot[i].y = dot[i].ry;
}
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 < 4; ++i) {
if (!dot[i].visible)
continue;
x = dot[i].rx - (1024/2);
y = dot[i].ry - (768/2);
dot[i].x = (c * x) + (-s * y);
dot[i].y = (s * x) + (c * y);
dot[i].x += (1024/2);
dot[i].y += (768/2);
}
}
/**
* @brief Average IR dots.
*
* @param dot An array of 4 ir_dot_t objects.
* @param x [out] Average X
* @param y [out] Average Y
*/
static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y) {
int vis = 0, i = 0;
*x = 0;
*y = 0;
for (; i < 4; ++i) {
if (dot[i].visible) {
*x += dot[i].x;
*y += dot[i].y;
++vis;
}
}
*x /= vis;
*y /= vis;
}
/**
* @brief Reorder the IR dots.
*
* @param dot An array of 4 ir_dot_t objects.
*/
static void reorder_ir_dots(struct ir_dot_t* dot) {
int i, j, order;
/* reset the dot ordering */
for (i = 0; i < 4; ++i)
dot[i].order = 0;
for (order = 1; order < 5; ++order) {
i = 0;
for (; !dot[i].visible || dot[i].order; ++i)
if (i == 4)
return;
for (j = 0; j < 4; ++j) {
if (dot[j].visible && !dot[j].order && (dot[j].x < dot[i].x))
i = j;
}
dot[i].order = order;
}
}
/**
* @brief Calculate the distance between the first 2 visible IR dots.
*
* @param dot An array of 4 ir_dot_t objects.
*/
static float ir_distance(struct ir_dot_t* dot) {
int i1, i2;
int xd, yd;
for (i1 = 0; i1 < 4; ++i1)
if (dot[i1].visible)
break;
if (i1 == 4)
return 0.0f;
for (i2 = i1+1; i2 < 4; ++i2)
if (dot[i2].visible)
break;
if (i2 == 4)
return 0.0f;
xd = dot[i2].x - dot[i1].x;
yd = dot[i2].y - dot[i1].y;
return sqrt(xd*xd + yd*yd);
}
/**
* @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(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y) {
int xzero, yzero;
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;
}
xzero = ((1024 - xs) / 2) + offset_x;
yzero = ((768 - ys) / 2) + offset_y;
if ((*x >= xzero)
&& (*x <= (xzero + xs))
&& (*y >= yzero)
&& (*y <= (yzero + 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(int* x, int* 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;
}
/**
* @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 = x * (ir->z / 1024.0f);
return RAD_TO_DEGREE( atanf(x / ir->z) );
}

View File

@ -1,56 +0,0 @@
/*
* 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$
*
*/
/**
* @file
* @brief Handles IR data.
*/
#ifndef IR_H_INCLUDED
#define IR_H_INCLUDED
#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, byte* data);
void calculate_extended_ir(struct wiimote_t* wm, byte* data);
float calc_yaw(struct ir_t* ir);
#ifdef __cplusplus
}
#endif
#endif // IR_H_INCLUDED

View File

@ -1,231 +0,0 @@
/*
* 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$
*
*/
/**
* @file
* @brief Nunchuk expansion device.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "definitions.h"
#include "wiiuse_internal.h"
#include "dynamics.h"
#include "events.h"
#include "nunchuk.h"
static void nunchuk_pressed_buttons(struct nunchuk_t* nc, byte now);
/**
* @brief Handle the handshake data from the nunchuk.
*
* @param nc A pointer to a nunchuk_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 nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len) {
int i;
int offset = 0;
nc->btns = 0;
nc->btns_held = 0;
nc->btns_released = 0;
/* set the smoothing to the same as the wiimote */
nc->flags = &wm->flags;
nc->accel_calib.st_alpha = wm->accel_calib.st_alpha;
/* 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 */
byte* handshake_buf = (byte *)malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
WIIUSE_DEBUG("Nunchuk handshake appears invalid, trying again.");
wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
return 0;
} else
offset += 16;
}
nc->accel_calib.cal_zero.x = data[offset + 0];
nc->accel_calib.cal_zero.y = data[offset + 1];
nc->accel_calib.cal_zero.z = data[offset + 2];
nc->accel_calib.cal_g.x = data[offset + 4];
nc->accel_calib.cal_g.y = data[offset + 5];
nc->accel_calib.cal_g.z = data[offset + 6];
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];
/* default the thresholds to the same as the wiimote */
nc->orient_threshold = wm->orient_threshold;
nc->accel_threshold = wm->accel_threshold;
/* handshake done */
wm->expansion.type = EXP_NUNCHUK;
/* if min and max are reported as 0, initialize them to usable values based on center, and fine tune in nunchuck_event() */
if (nc->js.center.x) {
if (nc->js.min.x == 0) nc->js.min.x = nc->js.center.x - 80;
if (nc->js.max.x == 0) nc->js.max.x = nc->js.center.x + 80;
}
if (nc->js.center.y) {
if (nc->js.min.y == 0) nc->js.min.y = nc->js.center.y - 80;
if (nc->js.max.y == 0) nc->js.max.y = nc->js.center.y + 80;
}
wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
return 1;
}
/**
* @brief The nunchuk disconnected.
*
* @param nc A pointer to a nunchuk_t structure.
*/
void nunchuk_disconnected(struct nunchuk_t* nc) {
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, byte* 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;
}
/* calculate joystick state */
calc_joystick_state(&nc->js, nc->js.pos.x, nc->js.pos.y);
/* calculate orientation */
nc->accel.x = msg[2];
nc->accel.y = msg[3];
nc->accel.z = msg[4];
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);
}
/**
* @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, byte now) {
/* message is inverted (0 is active, 1 is inactive) */
now = ~now & NUNCHUK_BUTTON_ALL;
/* 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;
}
/**
* @brief Set the orientation event threshold for the nunchuk.
*
* @param wm Pointer to a wiimote_t structure with a nunchuk attached.
* @param threshold The decimal place that should be considered a significant change.
*
* See wiiuse_set_orient_threshold() for details.
*/
void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold) {
if (!wm) return;
wm->expansion.nunchuk.orient_threshold = threshold;
}
/**
* @brief Set the accelerometer event threshold for the nunchuk.
*
* @param wm Pointer to a wiimote_t structure with a nunchuk attached.
* @param threshold The decimal place that should be considered a significant change.
*
* See wiiuse_set_orient_threshold() for details.
*/
void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold) {
if (!wm) return;
wm->expansion.nunchuk.accel_threshold = threshold;
}

View File

@ -1,53 +0,0 @@
/*
* 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$
*
*/
/**
* @file
* @brief Nunchuk expansion device.
*/
#ifndef NUNCHUK_H_INCLUDED
#define NUNCHUK_H_INCLUDED
#include "wiiuse_internal.h"
#ifdef __cplusplus
extern "C" {
#endif
int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len);
void nunchuk_disconnected(struct nunchuk_t* nc);
void nunchuk_event(struct nunchuk_t* nc, byte* msg);
#ifdef __cplusplus
}
#endif
#endif // NUNCHUK_H_INCLUDED

View File

@ -1,114 +0,0 @@
/*
* 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$
*
*/
/**
* @file
* @brief Wiiboard expansion device.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef WIN32
#include <Winsock2.h>
#endif
#include "definitions.h"
#include "wiiuse_internal.h"
#include "dynamics.h"
#include "events.h"
#include "wiiboard.h"
/**
* @brief Handle the handshake data from the guitar.
*
* @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 wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, byte* data, unsigned short len) {
int offset = 0;
if (data[offset]==0xff) {
if (data[offset+16]==0xff) {
WIIUSE_DEBUG("Wii Balance Board handshake appears invalid, trying again.");
wiiuse_read_data(wm, data, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
return 0;
}
offset += 16;
}
wb->ctr[0] = (data[offset+4]<<8)|data[offset+5];
wb->cbr[0] = (data[offset+6]<<8)|data[offset+7];
wb->ctl[0] = (data[offset+8]<<8)|data[offset+9];
wb->cbl[0] = (data[offset+10]<<8)|data[offset+11];
wb->ctr[1] = (data[offset+12]<<8)|data[offset+13];
wb->cbr[1] = (data[offset+14]<<8)|data[offset+15];
wb->ctl[1] = (data[offset+16]<<8)|data[offset+17];
wb->cbl[1] = (data[offset+18]<<8)|data[offset+19];
wb->ctr[2] = (data[offset+20]<<8)|data[offset+21];
wb->cbr[2] = (data[offset+22]<<8)|data[offset+23];
wb->ctl[2] = (data[offset+24]<<8)|data[offset+25];
wb->cbl[2] = (data[offset+26]<<8)|data[offset+27];
/* handshake done */
wm->event = WIIUSE_WII_BOARD_CTRL_INSERTED;
wm->expansion.type = EXP_WII_BOARD;
return 1;
}
/**
* @brief The wii board disconnected.
*
* @param cc A pointer to a wii_board_t structure.
*/
void wii_board_disconnected(struct wii_board_t* wb) {
memset(wb, 0, sizeof(struct wii_board_t));
}
/**
* @brief Handle guitar event.
*
* @param cc A pointer to a classic_ctrl_t structure.
* @param msg The message specified in the event packet.
*/
void wii_board_event(struct wii_board_t* wb, byte* msg) {
wb->rtr = (msg[0]<<8)|msg[1];
wb->rbr = (msg[2]<<8)|msg[3];
wb->rtl = (msg[4]<<8)|msg[5];
wb->rbl = (msg[6]<<8)|msg[7];
calc_balanceboard_state(wb);
}

View File

@ -1,53 +0,0 @@
/*
* 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$
*
*/
/**
* @file
* @brief Guitar Hero 3 expansion device.
*/
#ifndef WII_BOARD_H_INCLUDED
#define WII_BOARD_H_INCLUDED
#include "wiiuse_internal.h"
#ifdef __cplusplus
extern "C" {
#endif
int wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, byte* data, unsigned short len);
void wii_board_disconnected(struct wii_board_t* wb);
void wii_board_event(struct wii_board_t* wb, byte* msg);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -46,7 +46,6 @@
#include "definitions.h"
#include "wiiuse_internal.h"
#include "events.h"
#include "io.h"
static int g_banner = 1;
@ -222,19 +221,6 @@ void wiiuse_rumble(struct wiimote_t* wm, int status) {
wiiuse_send(wm, WM_CMD_RUMBLE, &buf, 1);
}
/**
* @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;
wiiuse_rumble(wm, !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE));
}
/**
* @brief Set the enabled LEDs.
*
@ -262,26 +248,6 @@ void wiiuse_set_leds(struct wiimote_t* wm, int leds) {
}
/**
* @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)
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC);
else
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC);
wiiuse_set_report_type(wm);
}
/**
* @brief Set the report type based on the current wiimote state.
*
@ -387,60 +353,6 @@ int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buff
}
/**
* @brief Read data from the wiimote (event version).
*
* @param wm Pointer to a wiimote_t structure.
* @param buffer An allocated buffer to store the data as it arrives from the wiimote.
* Must be persistent in memory and large enough to hold the data.
* @param addr The address of wiimote memory to read from.
* @param len The length of the block to be read.
*
* The library can only handle one data read request at a time
* because it must keep track of the buffer and other
* events that are specific to that request. So if a request
* has already been made, subsequent requests will be added
* to a pending list and be sent out when the previous
* finishes.
*/
int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int addr, unsigned short len) {
struct read_req_t* req;
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
return 0;
if (!buffer || !len)
return 0;
/* make this request structure */
req = (struct read_req_t*)malloc(sizeof(struct read_req_t));
req->cb = NULL;
req->buf = buffer;
req->addr = addr;
req->size = len;
req->wait = len;
req->dirty = 0;
req->next = NULL;
/* add this to the request list */
if (!wm->read_req) {
/* root node */
wm->read_req = req;
WIIUSE_DEBUG("Data read request can be sent out immediately.");
/* send the request out immediately */
wiiuse_send_next_pending_read_request(wm);
} else {
struct read_req_t* nptr = wm->read_req;
for (; nptr->next; nptr = nptr->next);
nptr->next = req;
WIIUSE_DEBUG("Added pending data read request.");
}
return 1;
}
/**
* @brief Send the next pending data read request to the wiimote.
@ -477,46 +389,6 @@ void wiiuse_send_next_pending_read_request(struct wiimote_t* wm) {
}
/**
* @brief Request the wiimote controller status.
*
* @param wm Pointer to a wiimote_t structure.
*
* Controller status includes: battery level, LED status, expansions
*/
void wiiuse_status(struct wiimote_t* wm) {
byte buf = 0;
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
return;
WIIUSE_DEBUG("Requested wiimote status.");
wiiuse_send(wm, WM_CMD_CTRL_STATUS, &buf, 1);
}
/**
* @brief Find a wiimote_t structure by its unique identifier.
*
* @param wm Pointer to a wiimote_t structure.
* @param wiimotes The number of wiimote_t structures in \a wm.
* @param unid The unique identifier to search for.
*
* @return Pointer to a wiimote_t structure, or NULL if not found.
*/
struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid) {
int i = 0;
for (; i < wiimotes; ++i) {
if (wm[i]->unid == unid)
return wm[i];
}
return NULL;
}
/**
* @brief Write data to the wiimote.
*
@ -612,60 +484,6 @@ int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len) {
}
/**
* @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 the wiimote smoothing alpha value.
*
* @param wm Pointer to a wiimote_t structure.
* @param alpha The alpha value to set. Between 0 and 1.
*
* @return Returns the old alpha value.
*
* The alpha value is between 0 and 1 and is used in an exponential
* smoothing algorithm.
*
* Smoothing is only performed if the WIIMOTE_USE_SMOOTHING is set.
*/
float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha) {
float old;
if (!wm) return 0.0f;
old = wm->accel_calib.st_alpha;
wm->accel_calib.st_alpha = alpha;
/* if there is a nunchuk set that too */
if (wm->expansion.type == EXP_NUNCHUK)
wm->expansion.nunchuk.accel_calib.st_alpha = alpha;
return old;
}
/**
@ -686,50 +504,6 @@ void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt
#endif
}
/**
* @brief Set the orientation event threshold.
*
* @param wm Pointer to a wiimote_t structure.
* @param threshold The decimal place that should be considered a significant change.
*
* If threshold is 0.01, and any angle changes by 0.01 then a significant change
* has occured and the event callback will be invoked. If threshold is 1 then
* the angle has to change by a full degree to generate an event.
*/
void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold) {
if (!wm) return;
wm->orient_threshold = threshold;
}
/**
* @brief Set the accelerometer event threshold.
*
* @param wm Pointer to a wiimote_t structure.
* @param threshold The decimal place that should be considered a significant change.
*/
void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold) {
if (!wm) return;
wm->accel_threshold = threshold;
}
/**
* @brief Try to resync with the wiimote by starting a new handshake.
*
* @param wm Pointer to a wiimote_t structure.
*/
void wiiuse_resync(struct wiimote_t* wm) {
if (!wm) return;
wm->handshake_state = 0;
wiiuse_handshake(wm, NULL, 0);
}
/**
* @brief Set the normal and expansion handshake timeouts.
*

View File

@ -140,6 +140,8 @@
#define EXP_CLASSIC 2
#define EXP_GUITAR_HERO_3 3
#define EXP_WII_BOARD 4
#define EXP_WII_MOTION_PLUS 5
#define EXP_WII_MOTION_PLUS_NUNCHUK 6
/* IR correction types */
typedef enum ir_position_t {
@ -276,6 +278,13 @@ typedef struct vec3b_t {
byte x, y, z;
} vec3b_t;
/**
* @struct vec3f_t
* @brief unsigned orientation short struct.
*/
typedef struct vec3s_t {
unsigned pitch, roll, yaw;
} vec3s_t;
/**
* @struct vec3f_t
@ -493,6 +502,24 @@ typedef struct wii_board_t {
float y;
} wii_board_t;
/**
* @struct motionplus_t
* @brief Motion Plus expansion device.
*/
typedef struct motionplus_t {
struct vec3s_t calib_zero; /* motion plus gyroscope calibration */
struct vec3s_t calib_min;
struct vec3s_t calib_max;
byte pitchfs; /* fast/slow motion */
byte rollfs;
byte yawfs;
unsigned short pitch; /* current orientation on each axis */
unsigned short roll;
unsigned short yaw;
} motionplus_t;
/**
* @struct expansion_t
* @brief Generic expansion device plugged into wiimote.
@ -567,7 +594,9 @@ typedef enum WIIUSE_EVENT_TYPE {
WIIUSE_GUITAR_HERO_3_CTRL_INSERTED,
WIIUSE_GUITAR_HERO_3_CTRL_REMOVED,
WIIUSE_WII_BOARD_CTRL_INSERTED,
WIIUSE_WII_BOARD_CTRL_REMOVED
WIIUSE_WII_BOARD_CTRL_REMOVED,
WIIUSE_MOTION_PLUS_INSERTED,
WIIUSE_MOTION_PLUS_REMOVED
} WIIUSE_EVENT_TYPE;
/**
@ -658,50 +687,29 @@ WIIUSE_EXPORT extern struct wiimote_t** wiiuse_init(int wiimotes);
WIIUSE_EXPORT extern void wiiuse_disconnected(struct wiimote_t* wm);
WIIUSE_EXPORT extern void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes);
WIIUSE_EXPORT extern void wiiuse_rumble(struct wiimote_t* wm, int status);
WIIUSE_EXPORT extern void wiiuse_toggle_rumble(struct wiimote_t* wm);
WIIUSE_EXPORT extern void wiiuse_set_leds(struct wiimote_t* wm, int leds);
WIIUSE_EXPORT extern void wiiuse_motion_sensing(struct wiimote_t* wm, int status);
WIIUSE_EXPORT extern int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int offset, unsigned short len);
WIIUSE_EXPORT extern int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len);
WIIUSE_EXPORT extern void wiiuse_status(struct wiimote_t* wm);
WIIUSE_EXPORT extern struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid);
WIIUSE_EXPORT extern int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable);
WIIUSE_EXPORT extern float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha);
WIIUSE_EXPORT extern void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type);
WIIUSE_EXPORT extern void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold);
WIIUSE_EXPORT extern void wiiuse_resync(struct wiimote_t* wm);
WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout);
WIIUSE_EXPORT extern void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold);
/* connect.c / io_win.c */
WIIUSE_EXPORT extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout);
WIIUSE_EXPORT extern int wiiuse_connect(struct wiimote_t** wm, int wiimotes);
WIIUSE_EXPORT extern void wiiuse_disconnect(struct wiimote_t* wm);
WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout);
#ifdef WIN32
WIIUSE_EXPORT extern int wiiuse_check_system_notification(unsigned int nMsg, WPARAM wParam, LPARAM lParam);
WIIUSE_EXPORT extern int wiiuse_register_system_notification(HWND hwnd);
#endif
/* events.c */
WIIUSE_EXPORT extern int wiiuse_poll(struct wiimote_t** wm, int wiimotes);
/* ir.c */
WIIUSE_EXPORT extern void wiiuse_set_ir(struct wiimote_t* wm, int status);
WIIUSE_EXPORT extern void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y);
WIIUSE_EXPORT extern void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos);
WIIUSE_EXPORT extern void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect);
WIIUSE_EXPORT extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level);
/* nunchuk.c */
WIIUSE_EXPORT extern void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold);
WIIUSE_EXPORT extern void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold);
/* io.c */
WIIUSE_EXPORT extern int wiiuse_io_read(struct wiimote_t* wm);
WIIUSE_EXPORT extern int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len);
/* Balance Board */
WIIUSE_EXPORT extern void wiiuse_set_wii_board_calib(struct wiimote_t *wm);
#ifdef __cplusplus
}

View File

@ -109,12 +109,19 @@
#define WM_EXP_MEM_BASE 0x04A40000
#define WM_EXP_MEM_ENABLE 0x04A40040
#define WM_EXP_MEM_CALIBR 0x04A40020
#define WM_EXP_MEM_ENABLE1 0x04A400F0
#define WM_EXP_MEM_ENABLE2 0x04A400FB
#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_EXT_MP_MEM_BASE 0x04A60000
#define WM_EXT_MP_MEM_ENABLE1 0x04A600F0
#define WM_EXT_MP_MEM_ENABLE2 0x04A600FE
#define WM_EXT_MP_MEM_ENABLE3 0x04A400FB
/* ir block data */
#define WM_IR_BLOCK1_LEVEL1 "\x02\x00\x00\x71\x01\x00\x64\x00\xfe"
#define WM_IR_BLOCK2_LEVEL1 "\xfd\x05"
@ -153,10 +160,16 @@
*/
/* encrypted expansion id codes (located at 0x04A400FC) */
#define EXP_ID_CODE_NUNCHUK 0x9A1EFEFE
#define EXP_ID_CODE_WII_BOARD 0xa4200402 //Find the encrypted epansion id code
/*#define EXP_ID_CODE_NUNCHUK 0x9A1EFEFE
#define EXP_ID_CODE_CLASSIC_CONTROLLER 0x9A1EFDFD
#define EXP_ID_CODE_GUITAR 0x9A1EFDFB
*/
#define EXP_ID_CODE_NUNCHUK 0xa4200000
#define EXP_ID_CODE_CLASSIC_CONTROLLER 0xa4200101
#define EXP_ID_CODE_GUITAR 0xa4200103 // 4 bytes are not unique enough
#define EXP_ID_CODE_WII_BOARD 0xa4200402
#define EXP_ID_CODE_MOTIONPLUS 0xa4200405
#define EXP_ID_CODE_MOTIONPLUS_EXT 0xa4200505
#define EXP_HANDSHAKE_LEN 224

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Version="9,00"
Name="wiiuse"
ProjectGUID="{944EF6DE-471D-447E-A2FD-D37D58805169}"
RootNamespace="wiiuse"
@ -408,42 +408,6 @@
<References>
</References>
<Files>
<Filter
Name="Expansion Devices"
>
<File
RelativePath=".\Src\classic.c"
>
</File>
<File
RelativePath=".\Src\classic.h"
>
</File>
<File
RelativePath=".\Src\guitar_hero_3.c"
>
</File>
<File
RelativePath=".\Src\guitar_hero_3.h"
>
</File>
<File
RelativePath=".\Src\nunchuk.c"
>
</File>
<File
RelativePath=".\Src\nunchuk.h"
>
</File>
<File
RelativePath=".\Src\wiiboard.c"
>
</File>
<File
RelativePath=".\Src\wiiboard.h"
>
</File>
</Filter>
<Filter
Name="I/O"
>
@ -471,30 +435,10 @@
<Filter
Name="Wiimote Data"
>
<File
RelativePath=".\Src\dynamics.c"
>
</File>
<File
RelativePath=".\Src\dynamics.h"
>
</File>
<File
RelativePath=".\Src\events.c"
>
</File>
<File
RelativePath=".\Src\events.h"
>
</File>
<File
RelativePath=".\Src\ir.c"
>
</File>
<File
RelativePath=".\Src\ir.h"
>
</File>
</Filter>
<Filter
Name="Common"

View File

@ -596,10 +596,6 @@
<Filter
Name="Real Wiimote"
>
<File
RelativePath=".\Src\ReadWiimote.cpp"
>
</File>
<File
RelativePath=".\Src\wiimote_real.cpp"
>
@ -640,18 +636,6 @@
RelativePath=".\Src\ConfigPadDlg.h"
>
</File>
<File
RelativePath=".\Src\ConfigRecording.cpp"
>
</File>
<File
RelativePath=".\Src\ConfigRecordingDlg.cpp"
>
</File>
<File
RelativePath=".\Src\ConfigRecordingDlg.h"
>
</File>
</Filter>
<Filter
Name="UDP Wiimote"

View File

@ -20,7 +20,6 @@
#include "main.h"
#include "ConfigBasicDlg.h"
#include "ConfigPadDlg.h"
#include "ConfigRecordingDlg.h"
#include "Config.h"
#include "EmuMain.h" // for SetDefaultExtensionRegistry
#include "EmuSubroutines.h" // for WmRequestStatus
@ -112,12 +111,6 @@ void WiimoteBasicConfigDialog::ButtonClick(wxCommandEvent& event)
m_Notebook->ChangeSelection(g_Config.CurrentPage);
UpdateGUI();
break;
case ID_BUTTONRECORDING:
m_RecordingConfigFrame = new WiimoteRecordingConfigDialog(this);
m_RecordingConfigFrame->ShowModal();
m_RecordingConfigFrame->Destroy();
m_RecordingConfigFrame = NULL;
break;
#ifdef _WIN32
case IDB_PAIRUP_REAL:
if (g_EmulatorState != PLUGIN_EMUSTATE_PLAY)
@ -327,7 +320,6 @@ void WiimoteBasicConfigDialog::CreateGUIControls()
}
m_ButtonMapping = new wxButton(this, ID_BUTTONMAPPING, wxT("Button Mapping"));
m_Recording = new wxButton(this, ID_BUTTONRECORDING, wxT("Recording"));
m_OK = new wxButton(this, wxID_OK, wxT("OK"));
m_OK->SetToolTip(wxT("Save changes and close"));
@ -336,7 +328,6 @@ void WiimoteBasicConfigDialog::CreateGUIControls()
wxBoxSizer* sButtons = new wxBoxSizer(wxHORIZONTAL);
sButtons->Add(m_ButtonMapping, 0, (wxALL), 0);
sButtons->Add(m_Recording, 0, (wxALL), 0);
sButtons->AddStretchSpacer();
sButtons->Add(m_OK, 0, (wxALL), 0);
sButtons->Add(m_Cancel, 0, (wxLEFT), 5);

View File

@ -1,541 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "IniFile.h"
#include "Timer.h"
#include "wiimote_real.h" // Local
#include "wiimote_hid.h"
#include "main.h"
#include "ConfigRecordingDlg.h"
#include "ConfigBasicDlg.h"
#include "Config.h"
#include "EmuMain.h" // for LoadRecordedMovements()
#include "EmuSubroutines.h" // for WmRequestStatus
void WiimoteRecordingConfigDialog::LoadFile()
{
DEBUG_LOG(WIIMOTE, "LoadFile()");
IniFile file;
file.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "WiimoteMovement.ini").c_str());
for (int i = 1; i < (RECORDING_ROWS + 1); i++)
{
// Temporary storage
int iTmp;
std::string STmp;
// Get row name
std::string SaveName = StringFromFormat("Recording%i", i);
// HotKey
file.Get(SaveName.c_str(), "HotKeySwitch", &iTmp, 3); m_RecordHotKeySwitch[i]->SetSelection(iTmp);
file.Get(SaveName.c_str(), "HotKeyWiimote", &iTmp, 10); m_RecordHotKeyWiimote[i]->SetSelection(iTmp);
file.Get(SaveName.c_str(), "HotKeyNunchuck", &iTmp, 10); m_RecordHotKeyNunchuck[i]->SetSelection(iTmp);
file.Get(SaveName.c_str(), "HotKeyIR", &iTmp, 10); m_RecordHotKeyIR[i]->SetSelection(iTmp);
// Movement name
file.Get(SaveName.c_str(), "MovementName", &STmp, ""); m_RecordText[i]->SetValue(wxString::FromAscii(STmp.c_str()));
// Game name
file.Get(SaveName.c_str(), "GameName", &STmp, ""); m_RecordGameText[i]->SetValue(wxString::FromAscii(STmp.c_str()));
// IR Bytes
file.Get(SaveName.c_str(), "IRBytes", &STmp, ""); m_RecordIRBytesText[i]->SetValue(wxString::FromAscii(STmp.c_str()));
// Recording speed
file.Get(SaveName.c_str(), "RecordingSpeed", &iTmp, -1);
if(iTmp != -1)
m_RecordSpeed[i]->SetValue(wxString::Format(wxT("%i"), iTmp));
else
m_RecordSpeed[i]->SetValue(wxT(""));
// Playback speed (currently always saved directly after a recording)
file.Get(SaveName.c_str(), "PlaybackSpeed", &iTmp, -1); m_RecordPlayBackSpeed[i]->SetSelection(iTmp);
}
}
void WiimoteRecordingConfigDialog::SaveFile()
{
DEBUG_LOG(WIIMOTE, "SaveFile");
IniFile file;
file.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "WiimoteMovement.ini").c_str());
for(int i = 1; i < (RECORDING_ROWS + 1); i++)
{
// Get row name
std::string SaveName = StringFromFormat("Recording%i", i);
// HotKey
file.Set(SaveName.c_str(), "HotKeySwitch", m_RecordHotKeySwitch[i]->GetSelection());
file.Set(SaveName.c_str(), "HotKeyWiimote", m_RecordHotKeyWiimote[i]->GetSelection());
file.Set(SaveName.c_str(), "HotKeyNunchuck", m_RecordHotKeyNunchuck[i]->GetSelection());
file.Set(SaveName.c_str(), "HotKeyIR", m_RecordHotKeyIR[i]->GetSelection());
// Movement name
file.Set(SaveName.c_str(), "MovementName", (const char*)m_RecordText[i]->GetValue().mb_str(wxConvUTF8));
// Game name
file.Set(SaveName.c_str(), "GameName", (const char*)m_RecordGameText[i]->GetValue().mb_str(wxConvUTF8));
// Recording speed (currently always saved directly after a recording)
/*
wxString TmpRecordSpeed = m_RecordSpeed[i]->GetValue();
if(TmpRecordSpeed.length() > 0)
int TmpRecordSpeed; file.Set(SaveName.c_str(), "RecordingSpeed", TmpRecordSpeed);
else
int TmpRecordSpeed; file.Set(SaveName.c_str(), "RecordingSpeed", "-1");
*/
// Playback speed (currently always saved directly after a recording)
file.Set(SaveName.c_str(), "PlaybackSpeed", m_RecordPlayBackSpeed[i]->GetSelection());
}
file.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "WiimoteMovement.ini").c_str());
DEBUG_LOG(WIIMOTE, "SaveFile()");
}
void WiimoteRecordingConfigDialog::CreateGUIControlsRecording()
{
m_PageRecording = new wxPanel(this, ID_RECORDINGPAGE, wxDefaultPosition, wxDefaultSize);
m_TextUpdateRate = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Update rate: 000 times/s"));
m_UpdateMeters = new wxCheckBox(m_PageRecording, ID_UPDATE_REAL, wxT("Update gauges"));
m_UpdateMeters->SetValue(g_Config.bUpdateRealWiimote);
m_UpdateMeters->SetToolTip(
wxT("You can turn this off when a game is running to avoid a potential slowdown that may come from redrawing the\n")
wxT("configuration screen. Remember that you also need to press '+' on your Wiimote before you can record movements."));
// Width and height of the gauges
static const int Gw = 35, Gh = 110; //ugly
m_GaugeBattery = new wxGauge( m_PageRecording, wxID_ANY, 100, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeRoll[0] = new wxGauge( m_PageRecording, wxID_ANY, 360, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeRoll[1] = new wxGauge( m_PageRecording, wxID_ANY, 360, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeGForce[0] = new wxGauge( m_PageRecording, wxID_ANY, 600, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeGForce[1] = new wxGauge( m_PageRecording, wxID_ANY, 600, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeGForce[2] = new wxGauge( m_PageRecording, wxID_ANY, 600, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeAccel[0] = new wxGauge( m_PageRecording, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeAccel[1] = new wxGauge( m_PageRecording, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeAccel[2] = new wxGauge( m_PageRecording, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeAccelNunchuk[0] = new wxGauge( m_PageRecording, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeAccelNunchuk[1] = new wxGauge( m_PageRecording, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeAccelNunchuk[2] = new wxGauge( m_PageRecording, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeGForceNunchuk[0] = new wxGauge( m_PageRecording, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeGForceNunchuk[1] = new wxGauge( m_PageRecording, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeGForceNunchuk[2] = new wxGauge( m_PageRecording, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
// The text controls
m_TextIR = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Cursor: 000 000\nDistance: 0000"));
wxBoxSizer * sBoxBattery = new wxBoxSizer(wxVERTICAL);
wxBoxSizer * sBoxRoll[2];
sBoxRoll[0] = new wxBoxSizer(wxVERTICAL);
sBoxRoll[1] = new wxBoxSizer(wxVERTICAL);
wxBoxSizer * sBoxGForce[3];
sBoxGForce[0] = new wxBoxSizer(wxVERTICAL);
sBoxGForce[1] = new wxBoxSizer(wxVERTICAL);
sBoxGForce[2] = new wxBoxSizer(wxVERTICAL);
wxBoxSizer * sBoxAccel[3];
sBoxAccel[0] = new wxBoxSizer(wxVERTICAL);
sBoxAccel[1] = new wxBoxSizer(wxVERTICAL);
sBoxAccel[2] = new wxBoxSizer(wxVERTICAL);
wxBoxSizer * sBoxAccelNunchuk[3];
sBoxAccelNunchuk[0] = new wxBoxSizer(wxVERTICAL);
sBoxAccelNunchuk[1] = new wxBoxSizer(wxVERTICAL);
sBoxAccelNunchuk[2] = new wxBoxSizer(wxVERTICAL);
wxBoxSizer * sBoxGForceNunchuk[3];
sBoxGForceNunchuk[0] = new wxBoxSizer(wxVERTICAL);
sBoxGForceNunchuk[1] = new wxBoxSizer(wxVERTICAL);
sBoxGForceNunchuk[2] = new wxBoxSizer(wxVERTICAL);
wxStaticText * m_TextBattery = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Batt."), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
wxStaticText * m_TextRoll = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Roll"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
wxStaticText * m_TextPitch = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Pitch"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
wxStaticText *m_TextX[4], *m_TextY[4], *m_TextZ[4];
m_TextX[0] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("X"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextX[1] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("X"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextX[2] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("X"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextX[3] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("X"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
m_TextY[0] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Y"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextY[1] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Y"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextY[2] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Y"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextY[3] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Y"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
m_TextZ[0] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Z"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextZ[1] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Z"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextZ[2] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Z"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextZ[3] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Z"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
sBoxBattery->Add(m_GaugeBattery, 0, wxEXPAND | (wxALL), 0); sBoxBattery->Add(m_TextBattery, 0, wxEXPAND | (wxUP), 5);
sBoxRoll[0]->Add(m_GaugeRoll[0], 0, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 0); sBoxRoll[0]->Add(m_TextRoll, 0, wxEXPAND | (wxUP), 5);
sBoxRoll[1]->Add(m_GaugeRoll[1], 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 0); sBoxRoll[1]->Add(m_TextPitch, 0, wxEXPAND | (wxUP), 5);
sBoxGForce[0]->Add(m_GaugeGForce[0], 0, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 0); sBoxGForce[0]->Add(m_TextX[0], 0, wxEXPAND | (wxUP), 5);
sBoxGForce[1]->Add(m_GaugeGForce[1], 0, wxEXPAND | (wxUP | wxDOWN), 0); sBoxGForce[1]->Add(m_TextY[0], 0, wxEXPAND | (wxUP), 5);
sBoxGForce[2]->Add(m_GaugeGForce[2], 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 0); sBoxGForce[2]->Add(m_TextZ[0], 0, wxEXPAND | (wxUP), 5);
sBoxAccel[0]->Add(m_GaugeAccel[0], 0, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 0); sBoxAccel[0]->Add(m_TextX[1], 0, wxEXPAND | (wxUP), 5);
sBoxAccel[1]->Add(m_GaugeAccel[1], 0, wxEXPAND | (wxUP | wxDOWN), 0); sBoxAccel[1]->Add(m_TextY[1], 0, wxEXPAND | (wxUP), 5);
sBoxAccel[2]->Add(m_GaugeAccel[2], 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 0); sBoxAccel[2]->Add(m_TextZ[1], 0, wxEXPAND | (wxUP), 5);
sBoxGForceNunchuk[0]->Add(m_GaugeGForceNunchuk[0], 0, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 0); sBoxGForceNunchuk[0]->Add(m_TextX[2], 0, wxEXPAND | (wxUP), 5);
sBoxGForceNunchuk[1]->Add(m_GaugeGForceNunchuk[1], 0, wxEXPAND | (wxUP | wxDOWN), 0); sBoxGForceNunchuk[1]->Add(m_TextY[2], 0, wxEXPAND | (wxUP), 5);
sBoxGForceNunchuk[2]->Add(m_GaugeGForceNunchuk[2], 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 0); sBoxGForceNunchuk[2]->Add(m_TextZ[2], 0, wxEXPAND | (wxUP), 5);
sBoxAccelNunchuk[0]->Add(m_GaugeAccelNunchuk[0], 0, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 0); sBoxAccelNunchuk[0]->Add(m_TextX[3], 0, wxEXPAND | (wxUP), 5);
sBoxAccelNunchuk[1]->Add(m_GaugeAccelNunchuk[1], 0, wxEXPAND | (wxUP | wxDOWN), 0); sBoxAccelNunchuk[1]->Add(m_TextY[3], 0, wxEXPAND | (wxUP), 5);
sBoxAccelNunchuk[2]->Add(m_GaugeAccelNunchuk[2], 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 0); sBoxAccelNunchuk[2]->Add(m_TextZ[3], 0, wxEXPAND | (wxUP), 5);
wxStaticBoxSizer * sbRealStatus = new wxStaticBoxSizer(wxVERTICAL, m_PageRecording, wxT("Status"));
wxStaticBoxSizer * sbRealIR = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("IR"));
wxStaticBoxSizer * sbRealBattery = new wxStaticBoxSizer(wxVERTICAL, m_PageRecording, wxT("Battery"));
wxStaticBoxSizer * sbRealRoll = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("Roll and Pitch"));
wxStaticBoxSizer * sbRealGForce = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("G-Force"));
wxStaticBoxSizer * sbRealAccel = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("Accelerometer"));
wxStaticBoxSizer * sbRealGForceNunchuk = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("G-Force NC"));
wxStaticBoxSizer * sbRealAccelNunchuk = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("Accelerometer NC"));
// Status
sbRealStatus->Add(m_TextUpdateRate, 0, wxEXPAND | (wxALL), 5);
sbRealStatus->Add(m_UpdateMeters, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
sbRealIR->Add(m_TextIR, 0, wxEXPAND | (wxALL), 5);
sbRealBattery->Add(sBoxBattery, 0, wxEXPAND | (wxALL), 5);
sbRealRoll->Add(sBoxRoll[0], 0, wxEXPAND | (wxALL), 5); sbRealRoll->Add(sBoxRoll[1], 0, wxEXPAND | (wxALL), 5);
sbRealGForce->Add(sBoxGForce[0], 0, wxEXPAND | (wxALL), 5); sbRealGForce->Add(sBoxGForce[1], 0, wxEXPAND | (wxALL), 5); sbRealGForce->Add(sBoxGForce[2], 0, wxEXPAND | (wxALL), 5);
sbRealAccel->Add(sBoxAccel[0], 0, wxEXPAND | (wxALL), 5); sbRealAccel->Add(sBoxAccel[1], 0, wxEXPAND | (wxALL), 5); sbRealAccel->Add(sBoxAccel[2], 0, wxEXPAND | (wxALL), 5);
sbRealAccelNunchuk->Add(sBoxAccelNunchuk[0], 0, wxEXPAND | (wxALL), 5); sbRealAccelNunchuk->Add(sBoxAccelNunchuk[1], 0, wxEXPAND | (wxALL), 5); sbRealAccelNunchuk->Add(sBoxAccelNunchuk[2], 0, wxEXPAND | (wxALL), 5);
sbRealGForceNunchuk->Add(sBoxGForceNunchuk[0], 0, wxEXPAND | (wxALL), 5); sbRealGForceNunchuk->Add(sBoxGForceNunchuk[1], 0, wxEXPAND | (wxALL), 5); sbRealGForceNunchuk->Add(sBoxGForceNunchuk[2], 0, wxEXPAND | (wxALL), 5);
// Vertical leftmost status
wxBoxSizer * sbStatusLeft = new wxBoxSizer(wxVERTICAL);
sbStatusLeft->Add(sbRealStatus, 0, wxEXPAND | (wxLEFT), 0);
sbStatusLeft->Add(sbRealIR, 0, wxEXPAND | (wxLEFT), 0);
wxBoxSizer * sbRealWiimoteStatus = new wxBoxSizer(wxHORIZONTAL);
sbRealWiimoteStatus->Add(sbStatusLeft, 0, wxEXPAND | (wxLEFT), 0);
sbRealWiimoteStatus->Add(sbRealBattery, 0, wxEXPAND | (wxLEFT), 5);
sbRealWiimoteStatus->Add(sbRealRoll, 0, wxEXPAND | (wxLEFT), 5);
sbRealWiimoteStatus->Add(sbRealGForce, 0, wxEXPAND | (wxLEFT), 5);
sbRealWiimoteStatus->Add(sbRealAccel, 0, wxEXPAND | (wxLEFT), 5);
sbRealWiimoteStatus->Add(sbRealAccelNunchuk, 0, wxEXPAND | (wxLEFT), 5);
sbRealWiimoteStatus->Add(sbRealGForceNunchuk, 0, wxEXPAND | (wxLEFT), 5);
m_GaugeBattery->SetToolTip(wxT("Press '+' to show the current status. Press '-' to stop recording the status."));
wxStaticBoxSizer * sbRealRecord = new wxStaticBoxSizer(wxVERTICAL, m_PageRecording, wxT("Record movements"));
wxArrayString StrHotKeySwitch;
StrHotKeySwitch.Add(wxT("Shift"));
StrHotKeySwitch.Add(wxT("Ctrl"));
StrHotKeySwitch.Add(wxT("Alt"));
StrHotKeySwitch.Add(wxT(" "));
wxArrayString StrHotKey;
for(int i = 0; i < 10; i++) StrHotKey.Add(wxString::Format(wxT("%i"), i));
StrHotKey.Add(wxT(" "));
wxArrayString StrPlayBackSpeed;
for(int i = 1; i <= 20; i++) StrPlayBackSpeed.Add(wxString::Format(wxT("%i"), i*25));
wxBoxSizer * sRealRecord[RECORDING_ROWS + 1];
wxStaticText * m_TextRec = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Rec."), wxDefaultPosition, wxSize(80, -1), wxALIGN_CENTRE);
wxStaticText * m_TextHotKeyWm = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Wiim."), wxDefaultPosition, wxSize(32, -1), wxALIGN_CENTRE);
wxStaticText * m_TextHotKeyNc = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Nunc."), wxDefaultPosition, wxSize(32, -1), wxALIGN_CENTRE);
wxStaticText * m_TextHotKeyIR = new wxStaticText(m_PageRecording, wxID_ANY, wxT("IR"), wxDefaultPosition, wxSize(32, -1), wxALIGN_CENTRE);
wxStaticText * m_TextMovement = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Movement name"), wxDefaultPosition, wxSize(200, -1), wxALIGN_CENTRE);
wxStaticText * m_TextGame = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Game name"), wxDefaultPosition, wxSize(200, -1), wxALIGN_CENTRE);
wxStaticText * m_TextIRBytes = new wxStaticText(m_PageRecording, wxID_ANY, wxT("IR"), wxDefaultPosition, wxSize(20, -1), wxALIGN_CENTRE);
wxStaticText * m_TextRecSpeed = new wxStaticText(m_PageRecording, wxID_ANY, wxT("R. s."), wxDefaultPosition, wxSize(33, -1), wxALIGN_CENTRE);
wxStaticText * m_TextPlaySpeed = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Pl. s."), wxDefaultPosition, wxSize(40, -1), wxALIGN_CENTRE);
// Tool tips
m_TextRec->SetToolTip(
wxT("To record a movement first press this button, then start the recording by pressing 'A' on the Wiimote and stop the recording\n")
wxT("by letting go of 'A'"));
m_TextHotKeyWm->SetToolTip(
wxT("Select a hotkey for playback of Wiimote movements. You can combine it with an")
wxT(" optional Shift, Ctrl, or Alt switch."));
m_TextHotKeyNc->SetToolTip(wxT(
"Select a hotkey for playback of Nunchuck movements"));
m_TextHotKeyIR->SetToolTip(wxT(
"Select a hotkey for playback of Nunchuck movements"));
m_TextRecSpeed->SetToolTip(wxT(
"Recording speed in average measurements per second"));
m_TextPlaySpeed->SetToolTip(
wxT("Playback speed: A playback speed of 100 means that the playback occurs at the same rate as it was recorded. (You can see the\n")
wxT("current update rate in the Status window above when a game is running.) However, if your framerate is only at 50% of full speed\n")
wxT("you may want to select a playback rate of 50, because then the game might perceive the playback as a full speed playback. (This\n")
wxT("holds if Wiimote_Update() is tied to the framerate, I'm not sure that this is the case. It seemed to vary somewhat with different\n")
wxT("framerates but perhaps not enough to say that it was exactly tied to the framerate.) So until this is better understood you'll have\n")
wxT("to try different playback rates and see which one that works."));
sRealRecord[0] = new wxBoxSizer(wxHORIZONTAL);
sRealRecord[0]->Add(m_TextRec, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextHotKeyWm, 0, wxEXPAND | (wxLEFT), 62);
sRealRecord[0]->Add(m_TextHotKeyNc, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextHotKeyIR, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextMovement, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextGame, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextIRBytes, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextRecSpeed, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextPlaySpeed, 0, wxEXPAND | (wxLEFT), 5);
sbRealRecord->Add(sRealRecord[0], 0, wxEXPAND | (wxALL), 0);
for(int i = 1; i < (RECORDING_ROWS + 1); i++)
{
sRealRecord[i] = new wxBoxSizer(wxHORIZONTAL);
m_RecordButton[i] = new wxButton(m_PageRecording, IDB_RECORD + i, wxEmptyString, wxDefaultPosition, wxSize(80, 20), 0, wxDefaultValidator, wxEmptyString);
m_RecordHotKeySwitch[i] = new wxChoice(m_PageRecording, IDC_RECORD + i, wxDefaultPosition, wxDefaultSize, StrHotKeySwitch);
m_RecordHotKeyWiimote[i] = new wxChoice(m_PageRecording, IDC_RECORD + i, wxDefaultPosition, wxDefaultSize, StrHotKey);
m_RecordHotKeyNunchuck[i] = new wxChoice(m_PageRecording, IDC_RECORD + i, wxDefaultPosition, wxDefaultSize, StrHotKey);
m_RecordHotKeyIR[i] = new wxChoice(m_PageRecording, IDC_RECORD + i, wxDefaultPosition, wxDefaultSize, StrHotKey);
m_RecordText[i] = new wxTextCtrl(m_PageRecording, IDT_RECORD_TEXT, wxT(""), wxDefaultPosition, wxSize(200, 19));
m_RecordGameText[i] = new wxTextCtrl(m_PageRecording, IDT_RECORD_GAMETEXT, wxT(""), wxDefaultPosition, wxSize(200, 19));
m_RecordIRBytesText[i] = new wxTextCtrl(m_PageRecording, IDT_RECORD_IRBYTESTEXT, wxT(""), wxDefaultPosition, wxSize(25, 19));
m_RecordSpeed[i] = new wxTextCtrl(m_PageRecording, IDT_RECORD_SPEED, wxT(""), wxDefaultPosition, wxSize(30, 19), wxTE_READONLY | wxTE_CENTRE);
m_RecordPlayBackSpeed[i] = new wxChoice(m_PageRecording, IDT_RECORD_PLAYSPEED, wxDefaultPosition, wxDefaultSize, StrPlayBackSpeed);
m_RecordText[i]->SetMaxLength(35);
m_RecordGameText[i]->SetMaxLength(35);
m_RecordIRBytesText[i]->Enable(false);
m_RecordSpeed[i]->Enable(false);
// Row 2 Sizers
sRealRecord[i]->Add(m_RecordButton[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordHotKeySwitch[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordHotKeyWiimote[i], 0, wxEXPAND | (wxLEFT), 2);
sRealRecord[i]->Add(m_RecordHotKeyNunchuck[i], 0, wxEXPAND | (wxLEFT), 2);
sRealRecord[i]->Add(m_RecordHotKeyIR[i], 0, wxEXPAND | (wxLEFT), 2);
sRealRecord[i]->Add(m_RecordText[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordGameText[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordIRBytesText[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordSpeed[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordPlayBackSpeed[i], 0, wxEXPAND | (wxLEFT), 5);
sbRealRecord->Add(sRealRecord[i], 0, wxEXPAND | (wxTOP), 2);
}
m_sRecordingMain = new wxBoxSizer(wxVERTICAL);
m_sRecordingMain->Add(sbRealWiimoteStatus, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxUP), 5);
m_sRecordingMain->Add(sbRealRecord, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
m_PageRecording->SetSizer(m_sRecordingMain);
m_Apply = new wxButton(this, wxID_APPLY, wxT("Apply"));
m_Close = new wxButton(this, wxID_CLOSE, wxT("Close"));
m_Close->SetToolTip(wxT("Apply and Close"));
wxBoxSizer* sButtons = new wxBoxSizer(wxHORIZONTAL);
sButtons->AddStretchSpacer();
sButtons->Add(m_Apply, 0, (wxALL), 0);
sButtons->Add(m_Close, 0, (wxLEFT), 5);
m_MainSizer = new wxBoxSizer(wxVERTICAL);
m_MainSizer->Add(m_PageRecording, 1, wxEXPAND | wxALL, 5);
m_MainSizer->Add(sButtons, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
this->SetSizer(m_MainSizer);
this->Layout();
Fit();
// Center the window if there is room for it
#ifdef _WIN32
if (GetSystemMetrics(SM_CYFULLSCREEN) > 800)
Center();
#endif
ControlsCreated = true;
}
void WiimoteRecordingConfigDialog::ConvertToString()
{
IniFile file;
file.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "WiimoteMovement.ini").c_str());
std::string TmpStr = "", TmpIR = "", TmpTime = "";
for (int i = 0; i < (int)m_vRecording.size(); i++)
{
// Write the movement data
TmpStr += StringFromFormat("%s", m_vRecording.at(i).x >= 0 ? StringFromFormat("+%03i", m_vRecording.at(i).x).c_str() : StringFromFormat("%04i", m_vRecording.at(i).x).c_str());
TmpStr += StringFromFormat("%s", m_vRecording.at(i).y >= 0 ? StringFromFormat("+%03i", m_vRecording.at(i).y).c_str() : StringFromFormat("%04i", m_vRecording.at(i).y).c_str());
TmpStr += StringFromFormat("%s", m_vRecording.at(i).z >= 0 ? StringFromFormat("+%03i", m_vRecording.at(i).z).c_str() : StringFromFormat("%04i", m_vRecording.at(i).z).c_str());
if (i < ((int)m_vRecording.size() - 1)) TmpStr += ",";
DEBUG_LOG(WIIMOTE, "%s", TmpStr.c_str());
// Write the IR data
TmpIR += ArrayToString(m_vRecording.at(i).IR, IRBytes, 0, 30, false);
if (i < ((int)m_vRecording.size() - 1)) TmpIR += ",";
// Write the timestamps. The upper limit is 99 seconds.
int Time = (int)((m_vRecording.at(i).Time - m_vRecording.at(0).Time) * 1000);
TmpTime += StringFromFormat("%05i", Time);
if (i < ((int)m_vRecording.size() - 1)) TmpTime += ",";
/* Break just short of the IniFile.cpp byte limit so that we don't
crash file.Load() the next time. This limit should never be hit
because of the recording limit below. I keep it here just in
case. */
if(TmpStr.length() > (1024*10 - 10) || TmpIR.length() > (1024*10 - 10) || TmpTime.length() > (1024*10 - 10))
{
break;
PanicAlert("Your recording was to long, the entire recording was not saved.");
}
// Debug
DEBUG_LOG(WIIMOTE, "Saved: [%i / %i] %03i %03i %03i", i, m_vRecording.size(), m_vRecording.at(i).x, m_vRecording.at(i).y, m_vRecording.at(i).z);
}
// Recordings per second
double Recordings = (double)m_vRecording.size();
double Time = m_vRecording.at(m_vRecording.size() - 1).Time - m_vRecording.at(0).Time;
int Rate = (int)(Recordings / Time);
// If time or the number of recordings are zero we set the Rate to zero
if (Time == 0 || m_vRecording.size() == 0) Rate = 0;
// Update GUI
m_RecordIRBytesText[m_iRecordTo]->SetValue(wxString::Format(wxT("%i"), IRBytes));
m_RecordSpeed[m_iRecordTo]->SetValue(wxString::Format(wxT("%i"), Rate));
// Save file
std::string SaveName = StringFromFormat("Recording%i", m_iRecordTo);
file.Set(SaveName.c_str(), "Movement", TmpStr.c_str());
file.Set(SaveName.c_str(), "IR", TmpIR.c_str());
file.Set(SaveName.c_str(), "Time", TmpTime.c_str());
file.Set(SaveName.c_str(), "IRBytes", IRBytes);
file.Set(SaveName.c_str(), "RecordingSpeed", Rate);
// Set a default playback speed if none is set already
int TmpPlaySpeed; file.Get(SaveName.c_str(), "PlaybackSpeed", &TmpPlaySpeed, -1);
if (TmpPlaySpeed == -1)
{
file.Set(SaveName.c_str(), "PlaybackSpeed", 3);
m_RecordPlayBackSpeed[m_iRecordTo]->SetSelection(3);
}
file.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "WiimoteMovement.ini").c_str());
DEBUG_LOG(WIIMOTE, "Save recording to WiimoteMovement.ini");
}
// Timeout the recording
void WiimoteRecordingConfigDialog::Update(wxTimerEvent& WXUNUSED(event))
{
m_bWaitForRecording = false;
m_bRecording = false;
m_RecordButton[m_iRecordTo]->SetLabel(wxT(""));
UpdateRecordingGUI();
}
void WiimoteRecordingConfigDialog::RecordMovement(wxCommandEvent& event)
{
m_iRecordTo = event.GetId() - 2000;
if(WiiMoteReal::g_MotionSensing)
{
// Check if there already is a recording here
if(m_RecordSpeed[m_iRecordTo]->GetLineLength(0) > 0)
{
if(!AskYesNo("Do you want to replace the current recording?")) return;
}
m_RecordButton[m_iRecordTo]->SetLabel(wxT("Hold A"));
}
else
{
m_RecordButton[m_iRecordTo]->SetLabel(wxT("Press +"));
return;
}
m_bWaitForRecording = true;
m_bRecording = false;
UpdateRecordingGUI();
m_TimeoutTimer->Start(5000, true);
}
void WiimoteRecordingConfigDialog::DoRecordA(bool Pressed)
{
// Return if we are not waiting or recording
if (! (m_bWaitForRecording || m_bRecording)) return;
// Return if we are waiting but have not pressed A
if (m_bWaitForRecording && !Pressed) return;
// Return if we are recording but are still pressing A
if (m_bRecording && Pressed) return;
//m_bAllowA = false;
m_bRecording = Pressed;
// Start recording, only run this once
if(m_bRecording && m_bWaitForRecording)
{
m_RecordButton[m_iRecordTo]->SetLabel(wxT("Recording..."));
m_vRecording.clear(); // Clear the list
m_TimeoutTimer->Stop();
m_bWaitForRecording = false;
}
// The recording is done
else
{
m_RecordButton[m_iRecordTo]->SetLabel(wxT("Done"));
DEBUG_LOG(WIIMOTE, "Done: %i %i", m_bWaitForRecording, m_bRecording);
//m_bAllowA = true;
ConvertToString();
}
UpdateRecordingGUI();
}
void WiimoteRecordingConfigDialog::DoRecordMovement(int _x, int _y, int _z, const u8 *_IR, int _IRBytes)
{
//std::string Tmp1 = ArrayToString(_IR, 20, 0, 30);
//DEBUG_LOG(WIIMOTE, "DoRecordMovement: %s", Tmp1.c_str());
if (!m_bRecording) return;
//DEBUG_LOG(WIIMOTE, "DoRecordMovement: %03i %03i %03i", _x, _y, _z);
SRecording Tmp;
Tmp.x = _x;
Tmp.y = _y;
Tmp.z = _z;
Tmp.Time = Common::Timer::GetDoubleTime();
memcpy(Tmp.IR, _IR, _IRBytes);
m_vRecording.push_back(Tmp);
// Save the number of IR bytes
IRBytes = _IRBytes;
// The upper limit of a recording coincides with the IniFile.cpp limit, each list element
// is 7 bytes, therefore be divide by 7
if (m_vRecording.size() > (10*1024 / 7 - 2) )
{
m_bRecording = false;
m_RecordButton[m_iRecordTo]->SetLabel(wxT("Done"));
ConvertToString();
UpdateRecordingGUI();
}
}

View File

@ -1,147 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "wiimote_hid.h"
#include "main.h"
#include "ConfigRecordingDlg.h"
#include "ConfigBasicDlg.h"
#include "Config.h"
#include "EmuMain.h" // for LoadRecordedMovements()
#include "wiimote_real.h"
BEGIN_EVENT_TABLE(WiimoteRecordingConfigDialog,wxDialog)
EVT_CLOSE(WiimoteRecordingConfigDialog::OnClose)
EVT_BUTTON(wxID_CLOSE, WiimoteRecordingConfigDialog::CloseClick)
EVT_BUTTON(wxID_APPLY, WiimoteRecordingConfigDialog::CloseClick)
EVT_CHOICE(IDC_RECORD + 1, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 2, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 3, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 4, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 5, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 6, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 7, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 8, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 9, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 10, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 11, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 12, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 13, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 14, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_CHOICE(IDC_RECORD + 15, WiimoteRecordingConfigDialog::RecordingChanged)
EVT_BUTTON(IDB_RECORD + 1, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 2, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 3, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 4, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 5, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 6, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 7, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 8, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 9, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 10, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 11, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 12, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 13, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 14, WiimoteRecordingConfigDialog::RecordMovement)
EVT_BUTTON(IDB_RECORD + 15, WiimoteRecordingConfigDialog::RecordMovement)
EVT_TIMER(IDTM_UPDATE, WiimoteRecordingConfigDialog::Update)
END_EVENT_TABLE()
WiimoteRecordingConfigDialog::WiimoteRecordingConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title,
const wxPoint &position, const wxSize& size, long style)
: wxDialog(parent, id, title, position, size, style)
{
#if wxUSE_TIMER
m_TimeoutTimer = new wxTimer(this, IDTM_UPDATE);
#endif
m_bWaitForRecording = false;
m_bRecording = false;
m_vRecording.resize(RECORDING_ROWS + 1);
g_Config.Load();
CreateGUIControlsRecording();
SetBackgroundColour(m_PageRecording->GetBackgroundColour());
LoadFile();
// Set control values
UpdateRecordingGUI();
}
void WiimoteRecordingConfigDialog::OnClose(wxCloseEvent& event)
{
SaveFile();
EndModal(wxID_CLOSE);
}
void WiimoteRecordingConfigDialog::CloseClick(wxCommandEvent& event)
{
switch(event.GetId())
{
case wxID_CLOSE:
#if HAVE_WIIUSE
if (!WiiMoteReal::SafeClose())
#endif
Close();
break;
case wxID_APPLY:
SaveFile();
WiiMoteEmu::LoadRecordedMovements();
break;
}
}
void WiimoteRecordingConfigDialog::RecordingChanged(wxCommandEvent& event)
{
switch (event.GetId())
{
case ID_UPDATE_REAL:
g_Config.bUpdateRealWiimote = m_UpdateMeters->IsChecked();
break;
default:
// Check if any of the other choice boxes has the same hotkey
for (int i = 1; i < (RECORDING_ROWS + 1); i++)
{
int CurrentChoiceBox = (event.GetId() - IDC_RECORD);
if (i == CurrentChoiceBox) continue;
if (m_RecordHotKeyWiimote[i]->GetSelection() == m_RecordHotKeyWiimote[CurrentChoiceBox]->GetSelection()) m_RecordHotKeyWiimote[i]->SetSelection(10);
if (m_RecordHotKeyNunchuck[i]->GetSelection() == m_RecordHotKeyNunchuck[CurrentChoiceBox]->GetSelection()) m_RecordHotKeyNunchuck[i]->SetSelection(10);
if (m_RecordHotKeyIR[i]->GetSelection() == m_RecordHotKeyIR[CurrentChoiceBox]->GetSelection()) m_RecordHotKeyIR[i]->SetSelection(10);
//DEBUG_LOG(WIIMOTE, "HotKey: %i %i",
// m_RecordHotKey[i]->GetSelection(), m_RecordHotKey[CurrentChoiceBox]->GetSelection());
}
break;
}
g_Config.Save();
UpdateRecordingGUI();
}
void WiimoteRecordingConfigDialog::UpdateRecordingGUI(int Slot)
{
// Disable all recording buttons
#ifdef _WIN32
bool ActiveRecording = !(m_bWaitForRecording || m_bRecording);
for(int i = IDB_RECORD + 1; i < (IDB_RECORD + RECORDING_ROWS + 1); i++)
if(ControlsCreated) m_PageRecording->FindItem(i)->Enable(ActiveRecording);
#endif
}

View File

@ -1,129 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef __CONFIGDIALOG_h__
#define __CONFIGDIALOG_h__
#include <iostream>
#include <vector>
#include <wx/wx.h>
#include <wx/textctrl.h>
#include <wx/button.h>
#include <wx/stattext.h>
#include <wx/combobox.h>
#include <wx/checkbox.h>
#include <wx/panel.h>
#include "Thread.h"
class WiimoteRecordingConfigDialog : public wxDialog
{
public:
WiimoteRecordingConfigDialog(wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxString &title = wxT("Wii Remote Plugin Configuration"),
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_DIALOG_STYLE | wxWANTS_CHARS);
virtual ~WiimoteRecordingConfigDialog(){;}
void UpdateRecordingGUI(int Slot = 0);
void LoadFile();
void SaveFile();
void DoRecordMovement(int _x, int _y, int _z, const u8 *_IR, int IRBytes);
void DoRecordA(bool Pressed);
void ConvertToString();
void CloseClick(wxCommandEvent& event);
void RecordMovement(wxCommandEvent& event);
void Update(wxTimerEvent& WXUNUSED(event));
bool m_bWaitForRecording,
m_bRecording;
int m_iRecordTo;
wxTimer *m_TimeoutTimer;
// General status
wxStaticText * m_TextUpdateRate,
*m_TextIR;
// Wiimote status
wxGauge *m_GaugeBattery,
*m_GaugeRoll[2],
*m_GaugeGForce[3],
*m_GaugeAccel[3],
*m_GaugeAccelNunchuk[3],
*m_GaugeGForceNunchuk[3];
private:
DECLARE_EVENT_TABLE();
bool ControlsCreated;
THREAD_RETURN SafeCloseReadWiimote_ThreadFunc2(void* arg);
Common::Thread* g_pReadThread2;
wxPanel *m_PageRecording;
wxButton *m_Close,
*m_Apply;
wxBoxSizer *m_MainSizer,
*m_sRecordingMain;
wxCheckBox *m_UpdateMeters;
wxButton * m_RecordButton[RECORDING_ROWS + 1];
wxChoice * m_RecordHotKeySwitch[RECORDING_ROWS + 1];
wxChoice * m_RecordHotKeyWiimote[RECORDING_ROWS + 1];
wxChoice * m_RecordHotKeyNunchuck[RECORDING_ROWS + 1];
wxChoice * m_RecordHotKeyIR[RECORDING_ROWS + 1];
wxTextCtrl * m_RecordText[RECORDING_ROWS + 1];
wxTextCtrl * m_RecordGameText[RECORDING_ROWS + 1];
wxTextCtrl * m_RecordIRBytesText[RECORDING_ROWS + 1];
wxTextCtrl * m_RecordSpeed[RECORDING_ROWS + 1];
wxChoice * m_RecordPlayBackSpeed[RECORDING_ROWS + 1];
std::vector<SRecording> m_vRecording;
int IRBytes;
enum
{
ID_RECORDINGPAGE = 1000,
IDTM_UPDATE,
// Real
ID_UPDATE_REAL,
IDB_RECORD = 2000,
IDC_RECORD = 3000,
IDC_PLAY_WIIMOTE,
IDC_PLAY_NUNCHUCK,
IDC_PLAY_IR,
IDT_RECORD_TEXT,
IDT_RECORD_GAMETEXT,
IDT_RECORD_IRBYTESTEXT,
IDT_RECORD_SPEED,
IDT_RECORD_PLAYSPEED
};
void OnClose(wxCloseEvent& event);
void CreateGUIControlsRecording();
void RecordingChanged(wxCommandEvent& event);
};
extern WiimoteRecordingConfigDialog *m_RecordingConfigFrame;
#endif

View File

@ -1,417 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <iostream> // System
#include "wiiuse.h" // Externals
#include "StringUtil.h"
#include "Timer.h"
#include "pluginspecs_wiimote.h"
#include "wiimote_real.h" // Local
#include "wiimote_hid.h"
#include "EmuDefinitions.h"
#include "EmuMain.h"
#include "main.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigBasicDlg.h"
#include "ConfigRecordingDlg.h"
#include "ConfigPadDlg.h"
#endif
#include "Config.h"
namespace WiiMoteReal
{
int GetIRDataSize(struct wiimote_t* wm)
{
if (WIIUSE_USING_EXP(wm))
return 10;
else
return 12;
}
void handle_ctrl_status(struct wiimote_t* wm)
{
DEBUG_LOG(WIIMOTE, "--- CONTROLLER STATUS [wiimote id %i] ---", wm->unid);
DEBUG_LOG(WIIMOTE, "attachment: %i", wm->expansion.type);
DEBUG_LOG(WIIMOTE, "speaker: %i", WIIUSE_USING_SPEAKER(wm));
DEBUG_LOG(WIIMOTE, "ir: %i", WIIUSE_USING_IR(wm));
DEBUG_LOG(WIIMOTE, "leds: %i %i %i %i", WIIUSE_IS_LED_SET(wm, 1), WIIUSE_IS_LED_SET(wm, 2), WIIUSE_IS_LED_SET(wm, 3), WIIUSE_IS_LED_SET(wm, 4));
DEBUG_LOG(WIIMOTE, "battery: %f %%", wm->battery_level);
}
bool IRDataOK(struct wiimote_t* wm)
{
// This check is valid because 0 should only be returned if the data
// hasn't been filled in by wiiuse
int IRDataSize = GetIRDataSize(wm);
for (int i = 7; i < IRDataSize; i++)
if (wm->event_buf[i] == 0)
return false;
return true;
}
void handle_event(struct wiimote_t* wm)
{
//DEBUG_LOG(WIIMOTE, "--- EVENT [id %i] ---", wm->unid);
// if a button is pressed, report it
if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) DEBUG_LOG(WIIMOTE, "A pressed");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_B)) DEBUG_LOG(WIIMOTE, "B pressed");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_UP)) DEBUG_LOG(WIIMOTE, "UP pressed");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN)) DEBUG_LOG(WIIMOTE, "DOWN pressed");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_LEFT)) DEBUG_LOG(WIIMOTE, "LEFT pressed");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_RIGHT)) DEBUG_LOG(WIIMOTE, "RIGHT pressed");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_MINUS)) DEBUG_LOG(WIIMOTE, "MINUS pressed");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_PLUS)) DEBUG_LOG(WIIMOTE, "PLUS pressed");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_ONE)) DEBUG_LOG(WIIMOTE, "ONE pressed");
//if (IS_PRESSED(wm, WIIMOTE_BUTTON_ONE)) g_Run = false;
if (IS_PRESSED(wm, WIIMOTE_BUTTON_TWO)) DEBUG_LOG(WIIMOTE, "TWO pressed");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_HOME)) DEBUG_LOG(WIIMOTE, "HOME pressed");
// Create shortcut to the nunchuck
struct nunchuk_t* nc = NULL;
if (wm->expansion.type == EXP_NUNCHUK) {
nc = (nunchuk_t*)&wm->expansion.nunchuk;
if (IS_PRESSED(nc, NUNCHUK_BUTTON_C))
DEBUG_LOG(WIIMOTE, "C pressed");
if (IS_PRESSED(nc, NUNCHUK_BUTTON_Z))
DEBUG_LOG(WIIMOTE, "Z pressed");
}
// Pressing minus will tell the wiimote we are no longer interested in movement.
// This is useful because it saves battery power.
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS))
{
wiiuse_motion_sensing(wm, 0);
wiiuse_set_ir(wm, 0);
g_MotionSensing = false;
}
// Turn aceelerometer and IR reporting on, there is some kind of bug that prevents us from turing these on
// directly after each other, so we have to wait for another wiiuse_poll() this way
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS))
{
wiiuse_motion_sensing(wm, 1);
g_MotionSensing = true;
}
// Turn IR reporting on
if (g_MotionSensing && !WIIUSE_USING_IR(wm))
wiiuse_set_ir(wm, 1);
#if defined(HAVE_WX) && HAVE_WX
if (!m_RecordingConfigFrame) return;
// Print battery status
if(m_RecordingConfigFrame && g_Config.bUpdateRealWiimote)
m_RecordingConfigFrame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5));
#endif
// If the accelerometer is turned on then print angles
if (WIIUSE_USING_ACC(wm) && WIIUSE_USING_IR(wm))
{
/*
std::string Tmp;
Tmp += StringFromFormat("Roll: %2.1f ", wm->orient.roll);
Tmp += StringFromFormat("Pitch: %2.1f ", wm->orient.pitch);
Tmp += StringFromFormat("Battery: %1.2f\n", wm->battery_level);
Tmp += StringFromFormat("G-Force x, y, z: %1.2f %1.2f %1.2f\n", wm->gforce.x, wm->gforce.y, wm->gforce.z);
Tmp += StringFromFormat("Accel x, y, z: %03i %03i %03i\n", wm->accel.x, wm->accel.y, wm->accel.z); */
// wm->event_buf is cleared at the end of all wiiuse_poll(), so wm->event_buf will always be zero
// after that. To get the raw IR data we need to read the wiimote again. This seems to work most of the time,
// it seems to fails with a regular interval about each tenth read.
if (wiiuse_io_read(wm))
if (IRDataOK(wm))
memcpy(g_EventBuffer, wm->event_buf, GetIRDataSize(wm));
/*
// Go through each of the 4 possible IR sources
for (int i = 0; i < 4; ++i)
{
// Check if the source is visible
if (wm->ir.dot[i].visible)
Tmp += StringFromFormat("IR source %i: (%u, %u)\n", i, wm->ir.dot[i].x, wm->ir.dot[i].y);
}
Tmp += "\n";
Tmp += StringFromFormat("IR cursor: (%u, %u)\n", wm->ir.x, wm->ir.y);
Tmp += StringFromFormat("IR z distance: %f\n", wm->ir.z);
if(wm->expansion.type == EXP_NUNCHUK)
{
Tmp += "\n";
Tmp += StringFromFormat("Nunchuck accel x, y, z: %03i %03i %03i\n", nc->accel.x, nc->accel.y, nc->accel.z);
} */
//Tmp += "\n";
//std::string TmpData = ArrayToString(g_EventBuffer, ReportSize, 0, 30);
//Tmp += "Data: " + TmpData;
//DEBUG_LOG(WIIMOTE, "%s", Tmp.c_str());
#if defined(HAVE_WX) && HAVE_WX
if(m_RecordingConfigFrame && g_Config.bUpdateRealWiimote)
{
// Produce adjusted accelerometer values
float _Gx = (float)(wm->accel.x - wm->accel_calib.cal_zero.x) / (float)wm->accel_calib.cal_g.x;
float _Gy = (float)(wm->accel.y - wm->accel_calib.cal_zero.y) / (float)wm->accel_calib.cal_g.y;
float _Gz = (float)(wm->accel.z - wm->accel_calib.cal_zero.z) / (float)wm->accel_calib.cal_g.z;
// Conver the data to integers
int Gx = (int)(_Gx * 100);
int Gy = (int)(_Gy * 100);
int Gz = (int)(_Gz * 100);
{ //Updating Wiimote Gauges.
m_RecordingConfigFrame->m_GaugeRoll[0]->SetValue(wm->orient.roll + 180);
m_RecordingConfigFrame->m_GaugeRoll[1]->SetValue(wm->orient.pitch + 180);
// Show g. forces between -3 and 3
m_RecordingConfigFrame->m_GaugeGForce[0]->SetValue((int)floor((wm->gforce.x * 100) + 300.5));
m_RecordingConfigFrame->m_GaugeGForce[1]->SetValue((int)floor((wm->gforce.y * 100) + 300.5));
m_RecordingConfigFrame->m_GaugeGForce[2]->SetValue((int)floor((wm->gforce.z * 100) + 300.5));
m_RecordingConfigFrame->m_GaugeAccel[0]->SetValue(wm->accel.x);
m_RecordingConfigFrame->m_GaugeAccel[1]->SetValue(wm->accel.y);
m_RecordingConfigFrame->m_GaugeAccel[2]->SetValue(wm->accel.z);
int GNCx, GNCy, GNCz;
if(wm->expansion.type == EXP_NUNCHUK) // Updating Nunchuck Gauges
{
m_RecordingConfigFrame->m_GaugeGForceNunchuk[0]->SetValue((int)floor((nc->gforce.x * 300) + 100.5));
m_RecordingConfigFrame->m_GaugeGForceNunchuk[1]->SetValue((int)floor((nc->gforce.y * 300) + 100.5));
m_RecordingConfigFrame->m_GaugeGForceNunchuk[2]->SetValue((int)floor((nc->gforce.z * 300) + 100.5));
m_RecordingConfigFrame->m_GaugeAccelNunchuk[0]->SetValue(nc->accel.x);
m_RecordingConfigFrame->m_GaugeAccelNunchuk[1]->SetValue(nc->accel.y);
m_RecordingConfigFrame->m_GaugeAccelNunchuk[2]->SetValue(nc->accel.z);
//Produce valid data for recording
float _GNCx = (float)(nc->accel.x - nc->accel_calib.cal_zero.x) / (float)nc->accel_calib.cal_g.x;
float _GNCy = (float)(nc->accel.y - nc->accel_calib.cal_zero.y) / (float)nc->accel_calib.cal_g.y;
float _GNCz = (float)(nc->accel.z - nc->accel_calib.cal_zero.z) / (float)nc->accel_calib.cal_g.z;
// Conver the data to integers
GNCx = (int)(_GNCx * 100);
GNCy = (int)(_GNCy * 100);
GNCz = (int)(_GNCz * 100);
}
m_RecordingConfigFrame->m_TextIR->SetLabel(wxString::Format(
wxT("Cursor: %03u %03u\nDistance:%4.0f"), wm->ir.x, wm->ir.y, wm->ir.z));
//m_RecordingConfigFrame->m_TextAccNeutralCurrent->SetLabel(wxString::Format(
// wxT("Current: %03u %03u %03u"), Gx, Gy, Gz));
if(m_RecordingConfigFrame->m_bRecording) {
if(wm->expansion.type != EXP_NUNCHUK) {
DEBUG_LOG(WIIMOTE, "Wiiuse Recorded accel x, y, z: %03i %03i %03i", Gx, Gy, Gz);
}
else {
DEBUG_LOG(WIIMOTE, "Wiiuse Recorded accel x, y, z: %03i %03i %03i; NCx, NCy, NCz: %03i %03i %03i",Gx,Gy,Gz, GNCx, GNCy, GNCz);
}
}
}
// Send the data to be saved //todo: passing nunchuck x,y,z vars as well
m_RecordingConfigFrame->DoRecordMovement(Gx, Gy, Gz, g_EventBuffer + 6, GetIRDataSize(wm));
// Turn recording on and off
if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) m_RecordingConfigFrame->DoRecordA(true);
else m_RecordingConfigFrame->DoRecordA(false);
// ------------------------------------
// Show roll and pitch in the status box
// --------------
if(!g_DebugData)
{
DEBUG_LOG(WIIMOTE, "Roll:%03i Pitch:%03i", (int)wm->orient.roll, (int)wm->orient.pitch);
}
if(m_PadConfigFrame)
{
// Convert Roll and Pitch from 180 to 0x8000
int Roll = (int)wm->orient.roll * (0x8000 / 180);
int Pitch = (int)wm->orient.pitch * (0x8000 / 180);
// Convert it to the box
m_PadConfigFrame->Convert2Box(Roll);
m_PadConfigFrame->Convert2Box(Pitch);
// Show roll and pitch in the axis boxes
m_PadConfigFrame->m_bmpDotRightOut[0]->SetPosition(wxPoint(Roll, Pitch));
}
}
#endif
}
// Otherwise remove the values
else
{
#if defined(HAVE_WX) && HAVE_WX
if (m_RecordingConfigFrame)
{
NOTICE_LOG(BOOT, "readwiimote, reset bars to zero");
m_RecordingConfigFrame->m_GaugeRoll[0]->SetValue(0);
m_RecordingConfigFrame->m_GaugeRoll[1]->SetValue(0);
m_RecordingConfigFrame->m_GaugeGForce[0]->SetValue(0);
m_RecordingConfigFrame->m_GaugeGForce[1]->SetValue(0);
m_RecordingConfigFrame->m_GaugeGForce[2]->SetValue(0);
m_RecordingConfigFrame->m_GaugeAccel[0]->SetValue(0);
m_RecordingConfigFrame->m_GaugeAccel[1]->SetValue(0);
m_RecordingConfigFrame->m_GaugeAccel[2]->SetValue(0);
m_RecordingConfigFrame->m_GaugeAccelNunchuk[0]->SetValue(0);
m_RecordingConfigFrame->m_GaugeAccelNunchuk[1]->SetValue(0);
m_RecordingConfigFrame->m_GaugeAccelNunchuk[2]->SetValue(0);
m_RecordingConfigFrame->m_GaugeGForceNunchuk[0]->SetValue(0);
m_RecordingConfigFrame->m_GaugeGForceNunchuk[1]->SetValue(0);
m_RecordingConfigFrame->m_GaugeGForceNunchuk[2]->SetValue(0);
m_RecordingConfigFrame->m_TextIR->SetLabel(wxT("Cursor:\nDistance:"));
}
#endif
}
}
void ReadWiimote()
{
/* I place this outside wiiuse_poll() to produce a continous recording regardless of the status
change of the Wiimote, wiiuse_poll() is only true if the status has changed. However, this the
timing functions for recording playback that checks the time of the recording this should not
be needed. But I still use it becase it seemed like state_changed() or the threshold values or
something else might fail so that only huge status changed were reported. */
for (int i = 0; i < g_NumberOfWiiMotes; i++)
{
handle_event(g_WiiMotesFromWiiUse[i]);
}
// Declaration
std::string Temp;
/* Timeout for data reading. This is used in Initialize() to read the Eeprom, if we have not gotten
what we wanted in the WIIUSE_READ_DATA case we stop this loop and enable the regular
wiiuse_io_read() and wiiuse_io_write() loop again. */
if (g_RunTemporary)
{
// The SecondsToWait holds if the update rate of wiiuse_poll() is kept at the default value of 10 ms
static const int SecondsToWait = 2;
g_RunTemporaryCountdown++;
if(g_RunTemporaryCountdown > (SecondsToWait * 100))
{
g_RunTemporaryCountdown = 0;
g_RunTemporary = false;
}
}
// Read formatted Wiimote data
if (wiiuse_poll(g_WiiMotesFromWiiUse, MAX_WIIMOTES))
{
/*
* This happens if something happened on any wiimote.
* So go through each one and check if anything happened.
*/
int i = 0;
for (; i < MAX_WIIMOTES; ++i)
{
switch (g_WiiMotesFromWiiUse[i]->event)
{
case WIIUSE_EVENT:
/* a generic event occured */
//handle_event(g_WiiMotesFromWiiUse[i]);
break;
case WIIUSE_STATUS:
/* a status event occured */
//handle_ctrl_status(g_WiiMotesFromWiiUse[i]);
break;
case WIIUSE_DISCONNECT:
case WIIUSE_UNEXPECTED_DISCONNECT:
/* the wiimote disconnected */
//handle_disconnect(wiimotes[i]);
break;
case WIIUSE_READ_DATA:
/*
* Data we requested to read was returned.
* Take a look at wiimotes[i]->read_req
* for the data.
*/
if(g_WiiMotesFromWiiUse[i]->read_req->size == sizeof(WiiMoteEmu::EepromData_0)
&& g_WiiMotesFromWiiUse[i]->read_req->addr == 0)
{
Temp = ArrayToString(g_WiiMotesFromWiiUse[i]->read_req->buf, sizeof(WiiMoteEmu::EepromData_0), 0, 30);
//memcpy(WiiMoteEmu::g_Eeprom[i], g_WiiMotesFromWiiUse[i]->read_req->buf, sizeof(WiiMoteEmu::EepromData_0));
DEBUG_LOG(WIIMOTE, "EEPROM: %s", Temp.c_str());
g_RunTemporary = false;
}
break;
case WIIUSE_NUNCHUK_INSERTED:
/*
* a nunchuk was inserted
* This is a good place to set any nunchuk specific
* threshold values. By default they are the same
* as the wiimote.
*/
//wiiuse_set_nunchuk_orient_threshold(g_WiiMotesFromWiiUse[i], 90.0f);
//wiiuse_set_nunchuk_accel_threshold(g_WiiMotesFromWiiUse[i], 100);
break;
case WIIUSE_CLASSIC_CTRL_INSERTED:
DEBUG_LOG(WIIMOTE, "Classic controller inserted.");
break;
case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
// some expansion was inserted
//handle_ctrl_status(wiimotes[i]);
DEBUG_LOG(WIIMOTE, "Guitar Hero 3 controller inserted.");
break;
case WIIUSE_NUNCHUK_REMOVED:
DEBUG_LOG(WIIMOTE, "Nunchuck was removed.");
break;
case WIIUSE_CLASSIC_CTRL_REMOVED:
case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
// some expansion was removed
//handle_ctrl_status(wiimotes[i]);
DEBUG_LOG(WIIMOTE, "An expansion was removed.");
break;
default:
break;
}
}
}
}
}; // end of namespace

View File

@ -27,11 +27,9 @@
#include "main.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigPadDlg.h"
#include "ConfigRecordingDlg.h"
#include "ConfigBasicDlg.h"
WiimotePadConfigDialog *m_PadConfigFrame = NULL;
WiimoteRecordingConfigDialog *m_RecordingConfigFrame = NULL;
WiimoteBasicConfigDialog *m_BasicConfigFrame = NULL;
#endif
#include "Config.h"
@ -358,20 +356,6 @@ void Wiimote_ControlChannel(int _number, u16 _channelID, const void* _pData, u32
// This sends a Data Report from the Wiimote. See SystemTimers.cpp for the documentation of this update.
void Wiimote_Update(int _number)
{
// Tell us about the update rate, but only about once every second to avoid a major slowdown
#if defined(HAVE_WX) && HAVE_WX
if (m_RecordingConfigFrame)
{
GetUpdateRate();
if (g_UpdateWriteScreen > g_UpdateRate)
{
m_RecordingConfigFrame->m_TextUpdateRate->SetLabel(wxString::Format(wxT("Update rate: %03i times/s"), g_UpdateRate));
g_UpdateWriteScreen = 0;
}
g_UpdateWriteScreen++;
}
#endif
// This functions will send:
// Emulated Wiimote: Only data reports 0x30-0x37
// Real Wiimote: Both data reports 0x30-0x37 and all other read reports
@ -437,40 +421,3 @@ bool IsFocus()
of the form seconds.milleseconds for example 1234.123. The leding seconds have no particular meaning
but are just there to enable use to tell if we have entered a new second or now. */
// -----------------
/* Calculate the current update frequency. Calculate the time between ten updates, and average
five such rates. If we assume there are 60 updates per second if the game is running at full
speed then we get this measure on average once every second. The reason to have a few updates
between each measurement is becase the milliseconds may not be perfectly accurate and may return
the same time even when a milliseconds has actually passed, for example.*/
int GetUpdateRate()
{
#if defined(HAVE_WX) && HAVE_WX
if(g_UpdateCounter == 10)
{
// Erase the old ones
if(g_UpdateTimeList.size() == 5) g_UpdateTimeList.erase(g_UpdateTimeList.begin() + 0);
// Calculate the time and save it
int Time = (int)(10 / (Common::Timer::GetDoubleTime() - g_UpdateTime));
g_UpdateTimeList.push_back(Time);
//DEBUG_LOG(WIIMOTE, "Time: %i %f", Time, Common::Timer::GetDoubleTime());
int TotalTime = 0;
for (int i = 0; i < (int)g_UpdateTimeList.size(); i++)
TotalTime += g_UpdateTimeList.at(i);
g_UpdateRate = TotalTime / 5;
// Write the new update time
g_UpdateTime = Common::Timer::GetDoubleTime();
g_UpdateCounter = 0;
}
g_UpdateCounter++;
return g_UpdateRate;
#else
return 0;
#endif
}

View File

@ -32,7 +32,6 @@
#endif
// Definitions and declarations
bool IsFocus();
int GetUpdateRate();
//void InterruptDebugging(bool Emu, const void* _pData);
//void ReadDebugging(bool Emu, const void* _pData, int Size);

View File

@ -35,7 +35,6 @@
#define EXCLUDE_H // Avoid certain declarations in wiimote_real.h
#include "wiimote_real.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigRecordingDlg.h"
#include "ConfigBasicDlg.h"
#endif
@ -64,16 +63,6 @@ Common::Thread* g_pReadThread = NULL;
int g_NumberOfWiiMotes;
CWiiMote* g_WiiMotes[MAX_WIIMOTES];
volatile bool g_Shutdown = false;
Common::Event g_StartThread;
Common::Event g_StopThreadTemporary;
bool g_LocalThread = true;
bool g_IRSensing = false;
bool g_MotionSensing = false;
u64 g_UpdateTime = 0;
int g_UpdateCounter = 0;
bool g_RunTemporary = false;
int g_RunTemporaryCountdown = 0;
u8 g_EventBuffer[32];
bool g_WiimoteInUse[MAX_WIIMOTES];
Common::Event NeedsConnect;
Common::Event Connected;
@ -94,7 +83,6 @@ THREAD_RETURN RunInvisibleMessageWindow_ThreadFunc(void* arg);
#endif
THREAD_RETURN ReadWiimote_ThreadFunc(void* arg);
THREAD_RETURN SafeCloseReadWiimote_ThreadFunc(void* arg);
// Probably this class should be in its own file
@ -377,6 +365,13 @@ int Initialize()
DEBUG_LOG(WIIMOTE, "Found No of Wiimotes: %i", g_NumberOfWiiMotes);
if (g_NumberOfWiiMotes > 0)
{
/*
//TODO: We need here to re-order the wiimote structure, after we shutdown() and re-init().
// If we don't do this Wiimotes will change slots on addition of a new real wiimote during a game,
// causing a disconnect as well.
if (g_EmulatorState == PLUGIN_EMUSTATE_PAUSE)
SortWiimotes();
*/
g_RealWiiMotePresent = true;
// Create a new thread for listening for Wiimote data
// and also connecting in Linux/OSX.
@ -384,6 +379,8 @@ int Initialize()
g_pReadThread = new Common::Thread(ReadWiimote_ThreadFunc, NULL);
// Don't run the Wiimote thread if no wiimotes were found
g_Shutdown = false;
//Hack for OSX
NeedsConnect.Set();
Connected.Wait();
}
@ -391,10 +388,7 @@ int Initialize()
return 0;
for (i = 0; i < g_NumberOfWiiMotes; i++)
{
// Remove the wiiuse_poll() threshold
wiiuse_set_accel_threshold(g_WiiMotesFromWiiUse[i], 0);
{
// Set the ir sensor sensitivity.
if (g_Config.iIRLevel) {
wiiuse_set_ir_sensitivity(g_WiiMotesFromWiiUse[i], g_Config.iIRLevel);
@ -402,33 +396,13 @@ int Initialize()
// Set the sensor bar position, this should only affect the internal wiiuse api functions
wiiuse_set_ir_position(g_WiiMotesFromWiiUse[i], WIIUSE_IR_ABOVE);
// Set flags
//wiiuse_set_flags(g_WiiMotesFromWiiUse[i], NULL, WIIUSE_SMOOTHING);
}
// psyjoe reports this allows majority of lost packets to be transferred.
// Will test soon
if (g_Config.bWiiReadTimeout != 10)
if (g_Config.bWiiReadTimeout != 10)
wiiuse_set_timeout(g_WiiMotesFromWiiUse, g_NumberOfWiiMotes, g_Config.bWiiReadTimeout, g_Config.bWiiReadTimeout);
// If we are connecting from the config window without a game running we set the LEDs
if (g_EmulatorState != PLUGIN_EMUSTATE_PLAY && g_RealWiiMotePresent)
FlashLights(true);
/* Allocate memory and copy the Wiimote eeprom accelerometer neutral values
to g_Eeprom. Unlike with and extension we have to do this here, because
this data is only read once when the Wiimote is connected. Also, we
can't change the neutral values the wiimote will report, I think, unless
we update its eeprom? In any case it's probably better to let the
current calibration be where it is and adjust the global values after
that to avoid overwriting critical data on any Wiimote. */
for (i = 0; i < g_NumberOfWiiMotes; i++)
{
byte *data = (byte*)malloc(sizeof(byte) * sizeof(WiiMoteEmu::EepromData_0));
wiiuse_read_data(g_WiiMotesFromWiiUse[i], data, 0, sizeof(WiiMoteEmu::EepromData_0));
}
// Initialized, even if we didn't find a Wiimote
g_RealWiiMoteInitialized = true;
@ -508,10 +482,6 @@ void Allocate()
DEBUG_LOG(WIIMOTE, "Using %i Real Wiimote(s) and %i Emu Wiimote(s)", g_Config.bNumberRealWiimotes, g_Config.bNumberEmuWiimotes);
// If we are not using any emulated wiimotes we can run the thread temporary until the data has beeen copied
if (g_Config.bNumberEmuWiimotes == 0)
g_RunTemporary = true;
g_RealWiiMoteAllocated = true;
}
@ -546,6 +516,11 @@ void Shutdown(void)
if (g_EmulatorState != PLUGIN_EMUSTATE_PLAY && g_RealWiiMotePresent)
FlashLights(false);
// TODOE: Save Wiimote-order here to restore it after an Init()
// we should best use the btaddress for this purpose, unfortunately it is a bit of a work to make wiiuse_find()
// get the btaddress of a bt device on windows with only a createfile() handle etc., but it wiiuse_find() is already doing that on linux
// Clean up wiiuse
wiiuse_cleanup(g_WiiMotesFromWiiUse, g_NumberOfWiiMotes);
@ -580,8 +555,6 @@ void Update(int _WiimoteNumber)
time to avoid a potential collision. */
THREAD_RETURN ReadWiimote_ThreadFunc(void* arg)
{
g_StopThreadTemporary.Init();
g_StartThread.Init();
NeedsConnect.Wait();
#ifndef _WIN32
int Connect;
@ -594,58 +567,18 @@ THREAD_RETURN ReadWiimote_ThreadFunc(void* arg)
while (!g_Shutdown)
{
// There is at least one Real Wiimote in use
if (g_Config.bNumberRealWiimotes > 0 && !g_RunTemporary)
// Usually, there is at least one Real Wiimote in use,
// except a wiimote gets disconnected unexpectly ingame or wiimote input type gets changed from real to none
if (g_Config.bNumberRealWiimotes > 0)
{
for (int i = 0; i < MAX_WIIMOTES; i++)
if (g_WiimoteInUse[i])
g_WiiMotes[i]->ReadData();
}
else {
if (!g_StopThreadTemporary.Wait(0))
{
// Event object was signaled, exiting thread to close ConfigRecordingDlg
new Common::Thread(SafeCloseReadWiimote_ThreadFunc, NULL);
g_StartThread.Set(); //tell the new thread to get going
return 0;
}
else
ReadWiimote();
}
}
//else { idle }
}
return 0;
}
// Returns whether SafeClose_ThreadFunc will take over closing of Recording dialog.
// FIXME: this whole threading stuff is bad, and should be removed.
// OSX is having problems with the threading anyways, since WiiUse is used
// from multiple threads, and not just the one where it was created on.
bool SafeClose()
{
if (!g_RealWiiMoteInitialized)
return false;
g_StopThreadTemporary.Set();
return true;
}
// Thread to avoid racing conditions by directly closing of ReadWiimote_ThreadFunc() resp. ReadWiimote()
// shutting down the Dlg while still beeing @ReadWiimote will result in a crash;
THREAD_RETURN SafeCloseReadWiimote_ThreadFunc(void* arg)
{
g_Shutdown = true;
g_StartThread.Wait(); //Ready to start cleaning
if (g_RealWiiMoteInitialized)
Shutdown();
#if defined(HAVE_WX) && HAVE_WX
m_RecordingConfigFrame->Close(true);
#endif
if (!g_RealWiiMoteInitialized)
Initialize();
return 0;
}

View File

@ -44,28 +44,13 @@ void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32
void Update(int _WiimoteNumber);
void SendAcc(u8 _ReportID);
void SetDataReportingMode(u8 ReportingMode = 0);
void ClearEvents();
bool SafeClose();
// The alternative Wiimote loop
void ReadWiimote();
bool IRDataOK(struct wiimote_t* wm);
#ifndef EXCLUDE_H
extern wiimote_t** g_WiiMotesFromWiiUse;
extern bool g_Shutdown;
extern Common::Event g_StartThread;
extern Common::Event g_StopThreadTemporary;
extern int g_NumberOfWiiMotes;
extern bool g_MotionSensing;
extern bool g_IRSensing;
extern u64 g_UpdateTime;
extern int g_UpdateCounter;
extern bool g_RunTemporary;
extern int g_RunTemporaryCountdown;
extern u8 g_EventBuffer[32];
#ifdef _WIN32
extern Common::Thread* g_AutoPairUpInvisibleWindow;
extern Common::Thread* g_AutoPairUpMonitoring;