diff options
-rw-r--r-- | tracker-wii/CMakeLists.txt | 7 | ||||
-rw-r--r-- | tracker-wii/lang/nl_NL.ts | 7 | ||||
-rw-r--r-- | tracker-wii/lang/ru_RU.ts | 7 | ||||
-rw-r--r-- | tracker-wii/lang/stub.ts | 7 | ||||
-rw-r--r-- | tracker-wii/lang/zh_CN.ts | 7 | ||||
-rw-r--r-- | tracker-wii/wii_camera.cpp | 105 | ||||
-rw-r--r-- | tracker-wii/wii_camera.h | 33 | ||||
-rw-r--r-- | tracker-wii/wii_frame.cpp | 34 | ||||
-rw-r--r-- | tracker-wii/wii_frame.hpp | 16 | ||||
-rw-r--r-- | tracker-wii/wii_module.cpp | 33 | ||||
-rw-r--r-- | tracker-wii/wii_point_extractor.cpp | 52 | ||||
-rw-r--r-- | tracker-wii/wii_point_extractor.h | 14 | ||||
-rw-r--r-- | tracker-wii/wiiyourself/CMakeLists.txt | 8 | ||||
-rw-r--r-- | tracker-wii/wiiyourself/warns-begin.hpp | 24 | ||||
-rw-r--r-- | tracker-wii/wiiyourself/warns-end.hpp | 7 | ||||
-rw-r--r-- | tracker-wii/wiiyourself/wiimote.cpp | 2925 | ||||
-rw-r--r-- | tracker-wii/wiiyourself/wiimote.h | 15 | ||||
-rw-r--r-- | tracker-wii/wiiyourself/wiimote_common.h | 2 |
18 files changed, 1607 insertions, 1696 deletions
diff --git a/tracker-wii/CMakeLists.txt b/tracker-wii/CMakeLists.txt index f43dca55..76a43a77 100644 --- a/tracker-wii/CMakeLists.txt +++ b/tracker-wii/CMakeLists.txt @@ -1,10 +1,9 @@ if(WIN32) - find_package(OpenCV QUIET) + find_package(OpenCV 3.0 QUIET) if(OpenCV_FOUND) add_subdirectory(wiiyourself) otr_module(tracker-wii) - target_link_libraries(${self} opentrack-tracker-pt-base opentrack-wiiyourself bthprops) - target_include_directories(${self} PRIVATE SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/wiiyourself") - target_include_directories(${self} PRIVATE "${CMAKE_SOURCE_DIR}/tracker-pt") + target_link_libraries(opentrack-tracker-wii opentrack-tracker-pt-base opentrack-wiiyourself bthprops) + target_include_directories(opentrack-tracker-wii PRIVATE "${CMAKE_SOURCE_DIR}/tracker-pt") endif() endif() diff --git a/tracker-wii/lang/nl_NL.ts b/tracker-wii/lang/nl_NL.ts index 4c21a820..9e739505 100644 --- a/tracker-wii/lang/nl_NL.ts +++ b/tracker-wii/lang/nl_NL.ts @@ -1,11 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1" language="nl_NL"> -<context> - <name>wii_metadata_pt</name> - <message> - <source>WiiPointTracker 1.1</source> - <translation type="unfinished"></translation> - </message> -</context> </TS> diff --git a/tracker-wii/lang/ru_RU.ts b/tracker-wii/lang/ru_RU.ts index ff0e7092..f62cf2e1 100644 --- a/tracker-wii/lang/ru_RU.ts +++ b/tracker-wii/lang/ru_RU.ts @@ -1,11 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1" language="ru_RU"> -<context> - <name>wii_metadata_pt</name> - <message> - <source>WiiPointTracker 1.1</source> - <translation type="unfinished"></translation> - </message> -</context> </TS> diff --git a/tracker-wii/lang/stub.ts b/tracker-wii/lang/stub.ts index d67c57ad..6401616d 100644 --- a/tracker-wii/lang/stub.ts +++ b/tracker-wii/lang/stub.ts @@ -1,11 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1"> -<context> - <name>wii_metadata_pt</name> - <message> - <source>WiiPointTracker 1.1</source> - <translation type="unfinished"></translation> - </message> -</context> </TS> diff --git a/tracker-wii/lang/zh_CN.ts b/tracker-wii/lang/zh_CN.ts index d67c57ad..6401616d 100644 --- a/tracker-wii/lang/zh_CN.ts +++ b/tracker-wii/lang/zh_CN.ts @@ -1,11 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1"> -<context> - <name>wii_metadata_pt</name> - <message> - <source>WiiPointTracker 1.1</source> - <translation type="unfinished"></translation> - </message> -</context> </TS> diff --git a/tracker-wii/wii_camera.cpp b/tracker-wii/wii_camera.cpp index 25173bb7..af9a2d1f 100644 --- a/tracker-wii/wii_camera.cpp +++ b/tracker-wii/wii_camera.cpp @@ -7,19 +7,8 @@ */ // silence #pragma deprecated in bluetoothapis.h - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wreserved-id-macro" -#endif - #undef _WIN32_WINNT #define _WIN32_WINNT _WIN32_WINNT_VISTA - -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - #undef NTDDI_VERSION #define NTDDI_VERSION NTDDI_VISTASP1 @@ -32,17 +21,18 @@ #include <opencv2/imgproc.hpp> -#include <bthsdpdef.h> +#include "cv/video-property-page.hpp" + #include <bluetoothapis.h> -namespace pt_module { +using namespace pt_module; WIICamera::WIICamera(const QString& module_name) : s { module_name } { - cam_info.fps = 70; - cam_info.res_x = 1024; - cam_info.res_y = 768; - cam_info.fov = 42; + cam_info.fps = 70; + cam_info.res_x = 1024; + cam_info.res_y = 768; + cam_info.fov = 42.0f; cam_info.idx = 0; } @@ -53,12 +43,12 @@ WIICamera::~WIICamera() QString WIICamera::get_desired_name() const { - return {}; + return desired_name; } QString WIICamera::get_active_name() const { - return {}; + return active_name; } void WIICamera::show_camera_settings() @@ -69,8 +59,8 @@ void WIICamera::show_camera_settings() WIICamera::result WIICamera::get_info() const { if (cam_info.res_x == 0 || cam_info.res_y == 0) - return { false, {} }; - return { true, cam_info }; + return result(false, pt_camera_info()); + return result(true, cam_info); } WIICamera::result WIICamera::get_frame(pt_frame& frame_) @@ -78,7 +68,7 @@ WIICamera::result WIICamera::get_frame(pt_frame& frame_) cv::Mat& frame = frame_.as<WIIFrame>()->mat; struct wii_info& wii = frame_.as<WIIFrame>()->wii; - const wii_camera_status new_frame = get_frame_(frame); + const wii_camera_status new_frame = _get_frame(frame); //create a fake blank frame frame = cv::Mat(cam_info.res_x, cam_info.res_y, CV_8UC3, cv::Scalar(0, 0, 0)); wii.status = new_frame; @@ -86,43 +76,46 @@ WIICamera::result WIICamera::get_frame(pt_frame& frame_) switch (new_frame) { case wii_cam_data_change: - get_status(wii); - get_points(wii); + _get_status(wii); + _get_points(wii); break; case wii_cam_data_no_change: - return { false, cam_info }; - default: - break; + return result(false, cam_info); } - return { true, cam_info }; + return result(true, cam_info); } -bool WIICamera::start(int, int, int, int) +bool WIICamera::start(int idx, int fps, int res_x, int res_y) { m_pDev = std::make_unique<wiimote>(); m_pDev->ChangedCallback = on_state_change; - m_pDev->CallbackTriggerFlags = (state_change_flags)(CONNECTED|EXTENSION_CHANGED |MOTIONPLUS_CHANGED); + m_pDev->CallbackTriggerFlags = (state_change_flags)(CONNECTED | + EXTENSION_CHANGED | + MOTIONPLUS_CHANGED); return true; } void WIICamera::stop() { - m_pDev->ChangedCallback = nullptr; - m_pDev->Disconnect(); - Beep(1000, 200); - m_pDev = nullptr; + onExit = true; + m_pDev->ChangedCallback = NULL; + m_pDev->Disconnect(); + Beep(1000, 200); + if (m_pDev) { + m_pDev=nullptr; + m_pDev = NULL; + } - cam_info = {}; - cam_desired = {}; + desired_name = QString(); + active_name = QString(); + cam_info = pt_camera_info(); + cam_desired = pt_camera_info(); } -wii_camera_status WIICamera::pair() + +wii_camera_status WIICamera::_pair() { -#if defined __MINGW32__ - // missing prototypes and implib entries - return wii_cam_wait_for_connect; -#else wii_camera_status ret = wii_cam_wait_for_sync; HBLUETOOTH_RADIO_FIND hbt; BLUETOOTH_FIND_RADIO_PARAMS bt_param; @@ -150,7 +143,7 @@ wii_camera_status WIICamera::pair() if (ERROR_SUCCESS != BluetoothGetRadioInfo(hbtlist[i], &btinfo)) {break;} HBLUETOOTH_DEVICE_FIND hbtdevfd; - BLUETOOTH_DEVICE_SEARCH_PARAMS btdevparam {}; + BLUETOOTH_DEVICE_SEARCH_PARAMS btdevparam; BLUETOOTH_DEVICE_INFO btdevinfo; btdevinfo.dwSize = sizeof(btdevinfo); @@ -190,7 +183,7 @@ wii_camera_status WIICamera::pair() pwd[4] = btinfo.address.rgBytes[4]; pwd[5] = btinfo.address.rgBytes[5]; - if (ERROR_SUCCESS != BluetoothAuthenticateDevice(nullptr, hbtlist[i], &btdevinfo, pwd, 6)) { error = true; continue; } + if (ERROR_SUCCESS != BluetoothAuthenticateDevice(NULL, hbtlist[i], &btdevinfo, pwd, 6)) { error = true; continue; } DWORD servicecount = 32; GUID guids[32]; if (ERROR_SUCCESS != BluetoothEnumerateInstalledServices(hbtlist[i], &btdevinfo, &servicecount, guids)) { error = true; continue; } @@ -206,25 +199,21 @@ wii_camera_status WIICamera::pair() } if (wiifound) { ret = wii_cam_wait_for_connect; } return ret; -#endif } -wii_camera_status WIICamera::get_frame_(cv::Mat& frame) +wii_camera_status WIICamera::_get_frame(cv::Mat& frame) { - (void)frame; wii_camera_status ret = wii_cam_wait_for_connect; if (!m_pDev->IsConnected()) { qDebug() << "wii wait"; - ret = pair(); - switch (ret) { + ret = _pair(); + switch(ret){ case wii_cam_wait_for_sync: m_pDev->Disconnect(); goto goodbye; case wii_cam_wait_for_connect: break; - default: - break; } if (!m_pDev->Connect(wiimote::FIRST_AVAILABLE)) { Beep(500, 30); Sleep(1000); @@ -249,7 +238,7 @@ goodbye: return ret; } -bool WIICamera::get_points(struct wii_info& wii) +bool WIICamera::_get_points(struct wii_info& wii) { bool dot_sizes = (m_pDev->IR.Mode == wiimote_state::ir::EXTENDED); bool ret = false; @@ -280,21 +269,23 @@ bool WIICamera::get_points(struct wii_info& wii) return ret; } -void WIICamera::get_status(struct wii_info& wii) +void WIICamera::_get_status(struct wii_info& wii) { //draw battery status wii.BatteryPercent = m_pDev->BatteryPercent; wii.bBatteryDrained = m_pDev->bBatteryDrained; //draw horizon + static int p = 0; + static int r = 0; if (m_pDev->Nunchuk.Acceleration.Orientation.UpdateAge < 10) { - horizon.p = m_pDev->Acceleration.Orientation.Pitch; - horizon.r = m_pDev->Acceleration.Orientation.Roll; + p = m_pDev->Acceleration.Orientation.Pitch; + r = m_pDev->Acceleration.Orientation.Roll; } - wii.Pitch = horizon.p; - wii.Roll = horizon.r; + wii.Pitch = p; + wii.Roll = r; } void WIICamera::on_state_change(wiimote &remote, @@ -339,5 +330,3 @@ void WIICamera::on_state_change(wiimote &remote, remote.SetReportType(wiimote::IN_BUTTONS_ACCEL_IR); } } - -} // ns pt_module diff --git a/tracker-wii/wii_camera.h b/tracker-wii/wii_camera.h index e7d93b83..55def206 100644 --- a/tracker-wii/wii_camera.h +++ b/tracker-wii/wii_camera.h @@ -21,7 +21,7 @@ #include <QString> -#include <wiimote.h> +#include <wiiyourself/wiimote.h> #include "wii_frame.hpp" namespace pt_module { @@ -41,26 +41,33 @@ struct WIICamera final : pt_camera QString get_desired_name() const override; QString get_active_name() const override; - void set_fov(f value) override { (void)value; } + void set_fov(double value) override {} void show_camera_settings() override; private: - static void on_state_change(wiimote &remote, - state_change_flags changed, - const wiimote_state &new_state); - wii_camera_status pair(); - wii_camera_status get_frame_(cv::Mat& Frame); - bool get_points(struct wii_info& wii); - void get_status(struct wii_info& wii); - - std::unique_ptr<wiimote> m_pDev; + std::unique_ptr<wiimote> m_pDev; + static void on_state_change(wiimote &remote, + state_change_flags changed, + const wiimote_state &new_state); + bool onExit = false; + pt_frame internalframe; + + wii_camera_status _pair(); + wii_camera_status _get_frame(cv::Mat& Frame); + bool _get_points(struct wii_info&); + void _get_status(struct wii_info&); + + double dt_mean = 0; + + Timer t; pt_camera_info cam_info; pt_camera_info cam_desired; - - struct { float p = 0, r = 0; } horizon; + QString desired_name, active_name; pt_settings s; + + static constexpr inline double dt_eps = 1./384; }; } // ns pt_module diff --git a/tracker-wii/wii_frame.cpp b/tracker-wii/wii_frame.cpp index 4520fde4..9332a704 100644 --- a/tracker-wii/wii_frame.cpp +++ b/tracker-wii/wii_frame.cpp @@ -15,7 +15,7 @@ #include <opencv2/imgproc.hpp> -namespace pt_module { +using namespace pt_module; WIIPreview& WIIPreview::operator=(const pt_frame& frame_) { @@ -27,7 +27,7 @@ WIIPreview& WIIPreview::operator=(const pt_frame& frame_) if (frame.channels() != 3) { - eval_once(qDebug() << "tracker/pt: camera frame depth: 3 !=" << frame.channels()); + once_only(qDebug() << "tracker/pt: camera frame depth: 3 !=" << frame.channels()); return *this; } @@ -49,23 +49,19 @@ WIIPreview::WIIPreview(int w, int h) QImage WIIPreview::get_bitmap() { - switch (status) { - case wii_cam_wait_for_dongle: - return QImage(":/Resources/usb.png"); - case wii_cam_wait_for_sync: - return QImage(":/Resources/sync.png"); - case wii_cam_wait_for_connect: - return QImage(":/Resources/on.png"); - case wii_cam_data_change: - case wii_cam_data_no_change: - break; - } - + switch (status) { + case wii_cam_wait_for_dongle: + return QImage(":/Resources/usb.png"); + case wii_cam_wait_for_sync: + return QImage(":/Resources/sync.png"); + case wii_cam_wait_for_connect: + return QImage(":/Resources/on.png"); + } int stride = frame_out.step.p[0]; if (stride < 64 || stride < frame_out.cols * 4) { - eval_once(qDebug() << "bad stride" << stride + once_only(qDebug() << "bad stride" << stride << "for bitmap size" << frame_copy.cols << frame_copy.rows); return QImage(); } @@ -78,9 +74,11 @@ QImage WIIPreview::get_bitmap() QImage::Format_ARGB32); } -void WIIPreview::draw_head_center(f x, f y) +void WIIPreview::draw_head_center(double x, double y) { - auto [px_, py_] = to_pixel_pos(x, y, frame_copy.cols, frame_copy.rows); + double px_, py_; + + std::tie(px_, py_) = to_pixel_pos(x, y, frame_copy.cols, frame_copy.rows); int px = iround(px_), py = iround(py_); @@ -102,5 +100,3 @@ void WIIPreview::ensure_size(cv::Mat& frame, int w, int h, int type) if (frame.cols != w || frame.rows != h) frame = cv::Mat(h, w, type); } - -} // ns pt_module diff --git a/tracker-wii/wii_frame.hpp b/tracker-wii/wii_frame.hpp index 8c4508b2..31967d10 100644 --- a/tracker-wii/wii_frame.hpp +++ b/tracker-wii/wii_frame.hpp @@ -12,10 +12,7 @@ #include <opencv2/core.hpp> #include <QImage> -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wweak-vtables" -#endif + namespace pt_module { @@ -52,7 +49,7 @@ struct WIIPreview final : pt_preview WIIPreview& operator=(const pt_frame& frame) override; QImage get_bitmap() override; - void draw_head_center(f x, f y) override; + void draw_head_center(double x, double y) override; operator cv::Mat&() { return frame_copy; } operator cv::Mat const&() const { return frame_copy; } @@ -60,12 +57,9 @@ struct WIIPreview final : pt_preview private: static void ensure_size(cv::Mat& frame, int w, int h, int type); - cv::Mat frame_copy, frame_out; - wii_camera_status status = wii_cam_wait_for_dongle; + bool fresh = true; + cv::Mat frame_copy, frame_color, frame_resize, frame_out; + wii_camera_status status; }; } // ns pt_module - -#ifdef __clang__ -# pragma clang diagnostic pop -#endif diff --git a/tracker-wii/wii_module.cpp b/tracker-wii/wii_module.cpp index c4884f22..40131f69 100644 --- a/tracker-wii/wii_module.cpp +++ b/tracker-wii/wii_module.cpp @@ -6,12 +6,11 @@ * copyright notice and this permission notice appear in all copies. */ #include "ftnoir_tracker_pt.h" +#include "api/plugin-api.hpp" -#include "wii_module.hpp" #include "wii_camera.h" #include "wii_frame.hpp" #include "wii_point_extractor.h" -#include "wii_module.hpp" #include "ftnoir_tracker_pt_dialog.h" #include "pt-api.hpp" @@ -20,12 +19,7 @@ static const QString module_name = "tracker-wii-pt"; -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -namespace pt_module { +using namespace pt_module; struct wii_pt_module_traits final : pt_runtime_traits { @@ -68,27 +62,22 @@ struct wii_dialog_pt : TrackerDialog_PT wii_dialog_pt(); }; -} // ns pt_module - -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - -QString wii_metadata_pt::name() +class wii_metadata_pt : public Metadata { - return tr("WiiPointTracker 1.1"); -} + QString name() { return _("WiiPointTracker 1.1"); } + QIcon icon() { return QIcon(":/Resources/wii.png"); } +}; -QIcon wii_metadata_pt::icon() -{ - return QIcon(":/Resources/wii.png"); -} +// ns pt_module using namespace pt_module; + + wii_dialog_pt::wii_dialog_pt() : TrackerDialog_PT(module_name) { - ui.tabWidget->removeTab(0); + ui.camera_settings_groupbox->hide(); + ui.groupBox_2->hide(); } OPENTRACK_DECLARE_TRACKER(wii_tracker_pt, wii_dialog_pt, wii_metadata_pt) diff --git a/tracker-wii/wii_point_extractor.cpp b/tracker-wii/wii_point_extractor.cpp index a16cf233..215d50b8 100644 --- a/tracker-wii/wii_point_extractor.cpp +++ b/tracker-wii/wii_point_extractor.cpp @@ -30,9 +30,9 @@ #include <QDebug> -using namespace numeric_types; +using namespace types; +using namespace pt_module; -namespace pt_module { WIIPointExtractor::WIIPointExtractor(const QString& module_name) : s(module_name) { @@ -40,40 +40,40 @@ WIIPointExtractor::WIIPointExtractor(const QString& module_name) : s(module_name } //define a temp draw function -void WIIPointExtractor::draw_point(cv::Mat& preview_frame, const vec2& p, const cv::Scalar& color, int thickness) +void WIIPointExtractor::_draw_point(cv::Mat& preview_frame, const vec2& p, const cv::Scalar& color, int thinkness) { static constexpr int len = 9; - cv::Point p2(iround(p[0] * preview_frame.cols + preview_frame.cols / f{2}), - iround(-p[1] * preview_frame.cols + preview_frame.rows / f{2})); + cv::Point p2(iround(p[0] * preview_frame.cols + preview_frame.cols / 2), + iround(-p[1] * preview_frame.cols + preview_frame.rows / 2)); cv::line(preview_frame, cv::Point(p2.x - len, p2.y), cv::Point(p2.x + len, p2.y), color, - thickness); + thinkness); cv::line(preview_frame, cv::Point(p2.x, p2.y - len), cv::Point(p2.x, p2.y + len), color, - thickness); -} + thinkness); +}; -bool WIIPointExtractor::draw_points(cv::Mat& preview_frame, const struct wii_info& wii, std::vector<vec2>& points) +bool WIIPointExtractor::_draw_points(cv::Mat& preview_frame, const struct wii_info &wii, std::vector<vec2>& points) { - constexpr int W = 1024; - constexpr int H = 768; + const float W = 1024.0f; + const float H = 768.0f; points.reserve(4); points.clear(); - for (unsigned index = 0; index < 4; index++) // NOLINT(modernize-loop-convert) + for (unsigned index = 0; index < 4; index++) { const struct wii_info_points &dot = wii.Points[index]; if (dot.bvis) { //qDebug() << "wii:" << dot.RawX << "+" << dot.RawY; //anti-clockwise rotate the 2D point - const f RX = W - dot.ux; - const f RY = H - dot.uy; + const float RX = W - dot.ux; + const float RY = H - dot.uy; //vec2 dt((dot.RawX - W / 2.0f) / W, -(dot.RawY - H / 2.0f) / W); //vec2 dt((RX - W / 2.0f) / W, -(RY - H / 2.0f) / W); //vec2 dt((2.0f*RX - W) / W, -(2.0f*RY - H ) / W); @@ -81,7 +81,7 @@ bool WIIPointExtractor::draw_points(cv::Mat& preview_frame, const struct wii_inf std::tie(dt[0], dt[1]) = to_screen_pos(RX, RY, W, H); points.push_back(dt); - draw_point(preview_frame, dt, cv::Scalar(0, 255, 0), dot.isize); + _draw_point(preview_frame, dt, cv::Scalar(0, 255, 0), dot.isize); } } const bool success = points.size() >= PointModel::N_POINTS; @@ -89,7 +89,7 @@ bool WIIPointExtractor::draw_points(cv::Mat& preview_frame, const struct wii_inf return success; } -void WIIPointExtractor::draw_bg(cv::Mat& preview_frame, const struct wii_info& wii) +void WIIPointExtractor::_draw_bg(cv::Mat& preview_frame, const struct wii_info &wii) { //draw battery status cv::line(preview_frame, @@ -99,8 +99,8 @@ void WIIPointExtractor::draw_bg(cv::Mat& preview_frame, const struct wii_info& w 2); //draw horizon - int pdelta = iround((preview_frame.rows / f{4}) * tan(((double)wii.Pitch)* pi / f(180))); - int rdelta = iround((preview_frame.cols / f{4}) * tan(((double)wii.Roll)* pi / f(180))); + int pdelta = iround((preview_frame.rows / 4) * tan((wii.Pitch)* M_PI / 180.0f)); + int rdelta = iround((preview_frame.cols / 4) * tan((wii.Roll)* M_PI / 180.0f)); cv::line(preview_frame, cv::Point(0, preview_frame.rows / 2 + rdelta - pdelta), @@ -114,15 +114,11 @@ void WIIPointExtractor::extract_points(const pt_frame& frame_, pt_preview& previ const struct wii_info& wii = frame_.as_const<WIIFrame>()->wii; cv::Mat& preview_frame = *preview_frame_.as<WIIPreview>(); - switch (wii.status) - { - case wii_cam_data_change: - draw_bg(preview_frame, wii); - draw_points(preview_frame, wii, points); - break; - default: - break; - } + switch (wii.status) { + case wii_cam_data_change: + _draw_bg(preview_frame, wii); + _draw_points(preview_frame, wii, points); + break; + } } -} // ns pt_module diff --git a/tracker-wii/wii_point_extractor.h b/tracker-wii/wii_point_extractor.h index 661ce35f..be0e5f45 100644 --- a/tracker-wii/wii_point_extractor.h +++ b/tracker-wii/wii_point_extractor.h @@ -16,19 +16,23 @@ namespace pt_module { -using namespace numeric_types; +using namespace types; class WIIPointExtractor final : public pt_point_extractor { public: + // extracts points from frame and draws some processing info into frame, if draw_output is set + // dt: time since last call in seconds void extract_points(const pt_frame& frame, pt_preview& preview_frame, std::vector<vec2>& points) override; WIIPointExtractor(const QString& module_name); - private: + static constexpr int max_blobs = 16; + pt_settings s; - void draw_point(cv::Mat& preview_frame, const vec2& p, const cv::Scalar& color, int thickness = 1); - bool draw_points(cv::Mat& preview_frame, const struct wii_info& wii, std::vector<vec2>& points); - void draw_bg(cv::Mat& preview_frame, const struct wii_info& wii); + void _draw_point(cv::Mat& preview_frame, const vec2& p, const cv::Scalar& color, int thinkness = 1); + bool _draw_points(cv::Mat& preview_frame, const struct wii_info &wii, std::vector<vec2>& points); + void _draw_bg(cv::Mat& preview_frame, const struct wii_info &wii); }; } // ns impl + diff --git a/tracker-wii/wiiyourself/CMakeLists.txt b/tracker-wii/wiiyourself/CMakeLists.txt index 91fa245a..6a32fde4 100644 --- a/tracker-wii/wiiyourself/CMakeLists.txt +++ b/tracker-wii/wiiyourself/CMakeLists.txt @@ -1,7 +1 @@ -if(WIN32) - otr_module(wiiyourself STATIC NO-COMPAT NO-QT) - target_link_libraries(${self} setupapi hid winmm) - if(CMAKE_COMPILER_IS_CLANGXX OR CMAKE_COMPILER_IS_GNUCXX) - target_compile_options(${self} PRIVATE -Wno-error) - endif() -endif() +otr_module(wiiyourself STATIC) diff --git a/tracker-wii/wiiyourself/warns-begin.hpp b/tracker-wii/wiiyourself/warns-begin.hpp deleted file mode 100644 index 0d0365a9..00000000 --- a/tracker-wii/wiiyourself/warns-begin.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifdef __GNUG__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wswitch" -# pragma GCC diagnostic ignored "-Wreorder" -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wunused-parameter" -# pragma GCC diagnostic ignored "-Wcast-align" -# ifndef __clang__ -# pragma GCC diagnostic ignored "-Wunused-but-set-variable" -# pragma GCC diagnostic ignored "-Wcast-function-type" -# endif -#endif - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" -# pragma clang diagnostic ignored "-Wextra-semi" -# pragma clang diagnostic ignored "-Wshadow-field" -# pragma clang diagnostic ignored "-Wreserved-id-macro" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -# pragma clang diagnostic ignored "-Wunused-macros" -# pragma clang diagnostic ignored "-Wcast-qual" -#endif diff --git a/tracker-wii/wiiyourself/warns-end.hpp b/tracker-wii/wiiyourself/warns-end.hpp deleted file mode 100644 index 3de03ca5..00000000 --- a/tracker-wii/wiiyourself/warns-end.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#ifdef __GNUG__ -# pragma GCC diagnostic pop -#endif - -#ifdef __clang__ -# pragma clang diagnostic pop -#endif diff --git a/tracker-wii/wiiyourself/wiimote.cpp b/tracker-wii/wiiyourself/wiimote.cpp index f3fcd81f..e1e49101 100644 --- a/tracker-wii/wiiyourself/wiimote.cpp +++ b/tracker-wii/wiiyourself/wiimote.cpp @@ -8,22 +8,34 @@ // // wiimote.cpp (tab = 4 spaces) -#include "warns-begin.hpp" - -#include <cmath> -#include <new> -#include <cstring> -#include <cstdio> -#include <iterator> +// VC-specifics: +#ifdef _MSC_VER + // disable warning "C++ exception handler used, but unwind semantics are not enabled." + // in <xstring> (I don't use it - or just enable C++ exceptions) +# pragma warning(disable: 4530) +// auto-link with the necessary libs +# pragma comment(lib, "setupapi.lib") +# pragma comment(lib, "hid.lib") // for HID API (from DDK) +# pragma comment(lib, "winmm.lib") // for timeGetTime() +#endif // _MSC_VER #include "wiimote.h" #include <setupapi.h> -#include <hidsdi.h>// from WinDDK - +extern "C" { +# ifdef __MINGW32__ +# include <ddk/hidsdi.h>// from WinDDK +# else +# include <hidsdi.h> +# endif +} #include <sys/types.h> // for _stat #include <sys/stat.h> // " #include <process.h> // for _beginthreadex() -#include <math.h> // for orientation +#ifdef __BORLANDC__ +# include <cmath.h> // for orientation +#else +# include <math.h> // " +#endif #include <mmreg.h> // for WAVEFORMATEXTENSIBLE #include <mmsystem.h> // for timeGetTime() @@ -34,19 +46,24 @@ // ------------------------------------------------------------------------------------ // helpers // ------------------------------------------------------------------------------------ -template<class T> inline T sign(const T& val) { return (val < 0) ? T(-1) : T(1); } -template<class T> inline T square(const T& val) { return val * val; } +template<class T> inline T sign (const T& val) { return (val<0)? T(-1) : T(1); } +template<class T> inline T square(const T& val) { return val*val; } #define ARRAY_ENTRIES(array) (sizeof(array)/sizeof(array[0])) // ------------------------------------------------------------------------------------ // Tracing & Debugging // ------------------------------------------------------------------------------------ -#define PREFIX "WiiYourself: " +#define PREFIX _T("WiiYourself! : ") // comment these to auto-strip their code from the library: // (they currently use OutputDebugString() via _TRACE() - change to suit) -# define TRACE trace_ -# define WARN trace_ +#if (_MSC_VER >= 1400) // VC 2005+ (earlier versions don't support variable args) +# define TRACE(fmt, ...) _TRACE(PREFIX fmt _T("\n"), __VA_ARGS__) +# define WARN(fmt, ...) _TRACE(PREFIX _T("* ") fmt _T(" *") _T("\n"), __VA_ARGS__) +#elif defined(__MINGW32__) +# define TRACE(fmt, ...) _TRACE(PREFIX fmt _T("\n") , ##__VA_ARGS__) +# define WARN(fmt, ...) _TRACE(PREFIX _T("* ") fmt _T(" *") _T("\n") , ##__VA_ARGS__) +#endif // uncomment any of these for deeper debugging: //#define DEEP_TRACE(fmt, ...) _TRACE(PREFIX _T("|") fmt _T("\n"), __VA_ARGS__) // VC 2005+ //#define DEEP_TRACE(fmt, ...) _TRACE(PREFIX _T("|") fmt _T("\n") , ##__VA_ARGS__) // mingw @@ -57,112 +74,108 @@ template<class T> inline T square(const T& val) { return val * val; } // internals: auto-strip code from the macros if they weren't defined #ifndef TRACE -# define TRACE(...) (void)0 +# define TRACE #endif #ifndef DEEP_TRACE -# define DEEP_TRACE(...) (void)0 +# define DEEP_TRACE #endif #ifndef WARN -# define WARN(...) (void)0 +# define WARN #endif // ------------------------------------------------------------------------------------ -static void trace_(const char* fmt, ...) -{ - char buffer[256]; - - if (!fmt) - return; - - va_list ap; - va_start(ap, fmt); - vsnprintf(buffer, std::size(buffer), fmt, ap); - va_end(ap); - - if (IsDebuggerPresent()) - OutputDebugString(buffer); - else - { - fprintf(stderr, "%s\n", buffer); - fflush(stderr); - } -} +static void _cdecl _TRACE (const TCHAR* fmt, ...) + { + static TCHAR buffer[256]; + if (!fmt) return; + + va_list argptr; + va_start (argptr, fmt); +#if (_MSC_VER >= 1400) // VC 2005+ + _vsntprintf_s(buffer, ARRAY_ENTRIES(buffer), _TRUNCATE, fmt, argptr); +#else + _vsntprintf (buffer, ARRAY_ENTRIES(buffer), fmt, argptr); +#endif + va_end (argptr); + + OutputDebugString(buffer); + } // ------------------------------------------------------------------------------------ // wiimote // ------------------------------------------------------------------------------------ // class statics -HMODULE wiimote::HidDLL = NULL; -unsigned wiimote::_TotalCreated = 0; -unsigned wiimote::_TotalConnected = 0; +HMODULE wiimote::HidDLL = NULL; +unsigned wiimote::_TotalCreated = 0; +unsigned wiimote::_TotalConnected = 0; hidwrite_ptr wiimote::_HidD_SetOutputReport = NULL; // (keep in sync with 'speaker_freq'): -const unsigned wiimote::FreqLookup[TOTAL_FREQUENCIES] = -{ 0, 4200, 3920, 3640, 3360, - 3130, 2940, 2760, 2610, 2470 }; - -const TCHAR* const wiimote::ButtonNameFromBit[TOTAL_BUTTON_BITS] = -{ _T("Left") , _T("Right"), _T("Down"), _T("Up"), - _T("Plus") , _T("??") , _T("??") , _T("??") , - _T("Two") , _T("One") , _T("B") , _T("A") , - _T("Minus"), _T("??") , _T("??") , _T("Home") }; - -const TCHAR* const wiimote::ClassicButtonNameFromBit[TOTAL_BUTTON_BITS] = -{ _T("??") , _T("TrigR") , _T("Plus") , _T("Home"), - _T("Minus"), _T("TrigL") , _T("Down") , _T("Right") , - _T("Up") , _T("Left") , _T("ZR") , _T("X") , - _T("A") , _T("Y") , _T("B") , _T("ZL") }; +const unsigned wiimote::FreqLookup [TOTAL_FREQUENCIES] = + { 0, 4200, 3920, 3640, 3360, + 3130, 2940, 2760, 2610, 2470 }; + +const TCHAR* const wiimote::ButtonNameFromBit [TOTAL_BUTTON_BITS] = + { _T("Left") , _T("Right"), _T("Down"), _T("Up"), + _T("Plus") , _T("??") , _T("??") , _T("??") , + _T("Two") , _T("One") , _T("B") , _T("A") , + _T("Minus"), _T("??") , _T("??") , _T("Home") }; + +const TCHAR* const wiimote::ClassicButtonNameFromBit [TOTAL_BUTTON_BITS] = + { _T("??") , _T("TrigR") , _T("Plus") , _T("Home"), + _T("Minus"), _T("TrigL") , _T("Down") , _T("Right") , + _T("Up") , _T("Left") , _T("ZR") , _T("X") , + _T("A") , _T("Y") , _T("B") , _T("ZL") }; // ------------------------------------------------------------------------------------ -wiimote::wiimote() +wiimote::wiimote () : - DataRead(CreateEvent(NULL, FALSE, FALSE, NULL)), - Handle(INVALID_HANDLE_VALUE), - ReportType(IN_BUTTONS), - bStatusReceived(false), // for output method detection - bConnectInProgress(true), - bInitInProgress(false), - bEnablingMotionPlus(false), - bConnectionLost(false), // set if write fails after connection - bMotionPlusDetected(false), - bMotionPlusEnabled(false), - bMotionPlusExtension(false), - bCalibrateAtRest(false), - bUseHIDwrite(false), // if OS supports it - ChangedCallback(NULL), - CallbackTriggerFlags(CHANGED_ALL), - InternalChanged(NO_CHANGE), - CurrentSample(NULL), - HIDwriteThread(NULL), - ReadParseThread(NULL), - SampleThread(NULL), - AsyncRumbleThread(NULL), - AsyncRumbleTimeout(0), - UniqueID(0) // not _guaranteed_ unique, see comments in header + DataRead (CreateEvent(NULL, FALSE, FALSE, NULL)), + Handle (INVALID_HANDLE_VALUE), + ReportType (IN_BUTTONS), + bStatusReceived (false), // for output method detection + bConnectInProgress (true ), + bInitInProgress (false), + bEnablingMotionPlus (false), + bConnectionLost (false), // set if write fails after connection + bMotionPlusDetected (false), + bMotionPlusEnabled (false), + bMotionPlusExtension (false), + bCalibrateAtRest (false), + bUseHIDwrite (false), // if OS supports it + ChangedCallback (NULL), + CallbackTriggerFlags (CHANGED_ALL), + InternalChanged (NO_CHANGE), + CurrentSample (NULL), + HIDwriteThread (NULL), + ReadParseThread (NULL), + SampleThread (NULL), + AsyncRumbleThread (NULL), + AsyncRumbleTimeout (0), + UniqueID (0) // not _guaranteed_ unique, see comments in header #ifdef ID2_FROM_DEVICEPATH // (see comments in header) // UniqueID2 (0) #endif -{ + { _ASSERT(DataRead != INVALID_HANDLE_VALUE); - + // if this is the first wiimote object, detect & enable HID write support - if (++_TotalCreated == 1) - { + if(++_TotalCreated == 1) + { HidDLL = LoadLibrary(_T("hid.dll")); _ASSERT(HidDLL); - if (!HidDLL) + if(!HidDLL) WARN(_T("Couldn't load hid.dll - shouldn't happen!")); - else { + else{ _HidD_SetOutputReport = (hidwrite_ptr) - GetProcAddress(HidDLL, "HidD_SetOutputReport"); - if (_HidD_SetOutputReport) + GetProcAddress(HidDLL, "HidD_SetOutputReport"); + if(_HidD_SetOutputReport) TRACE(_T("OS supports HID writes.")); else TRACE(_T("OS doesn't support HID writes.")); + } } - } // clear our public and private state data completely (including deadzones) - Clear(true); + Clear (true); Internal.Clear(true); // and the state recording vars @@ -170,9 +183,9 @@ wiimote::wiimote() // for overlapped IO (Read/WriteFile) memset(&Overlapped, 0, sizeof(Overlapped)); - Overlapped.hEvent = DataRead; - Overlapped.Offset = - Overlapped.OffsetHigh = 0; + Overlapped.hEvent = DataRead; + Overlapped.Offset = + Overlapped.OffsetHigh = 0; // for async HID output method InitializeCriticalSection(&HIDwriteQueueLock); @@ -180,43 +193,43 @@ wiimote::wiimote() InitializeCriticalSection(&StateLock); // request millisecond timer accuracy - timeBeginPeriod(1); -} + timeBeginPeriod(1); + } // ------------------------------------------------------------------------------------ -wiimote::~wiimote() -{ +wiimote::~wiimote () + { Disconnect(); // events & critical sections are kept open for the lifetime of the object, // so tidy them up here: - if (DataRead != INVALID_HANDLE_VALUE) + if(DataRead != INVALID_HANDLE_VALUE) CloseHandle(DataRead); DeleteCriticalSection(&HIDwriteQueueLock); DeleteCriticalSection(&StateLock); // tidy up timer accuracy request - timeEndPeriod(1); + timeEndPeriod(1); // release HID DLL (for dynamic HID write method) - if ((--_TotalCreated == 0) && HidDLL) - { + if((--_TotalCreated == 0) && HidDLL) + { FreeLibrary(HidDLL); - HidDLL = NULL; + HidDLL = NULL; _HidD_SetOutputReport = NULL; + } } -} // ------------------------------------------------------------------------------------ -bool wiimote::Connect(unsigned wiimote_index, bool force_hidwrites) -{ - if (wiimote_index == FIRST_AVAILABLE) +bool wiimote::Connect (unsigned wiimote_index, bool force_hidwrites) + { + if(wiimote_index == FIRST_AVAILABLE) TRACE(_T("Connecting first available Wiimote:")); else TRACE(_T("Connecting Wiimote %u:"), wiimote_index); // auto-disconnect if user is being naughty - if (IsConnected()) + if(IsConnected()) Disconnect(); // get the GUID of the HID class @@ -227,68 +240,65 @@ bool wiimote::Connect(unsigned wiimote_index, bool force_hidwrites) // Brian: Fun fact: DIGCF_PRESENT worked on my machine just fine. I reinstalled // Vista, and now it no longer finds the Wiimote with that parameter enabled... HDEVINFO dev_info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE);// | DIGCF_PRESENT); - if (!dev_info) { + if(!dev_info) { WARN(_T("couldn't get device info")); return false; - } + } // enumerate the devices SP_DEVICE_INTERFACE_DATA didata; didata.cbSize = sizeof(didata); - - unsigned index = 0; + + unsigned index = 0; unsigned wiimotes_found = 0; - while (SetupDiEnumDeviceInterfaces(dev_info, NULL, &guid, index, &didata)) - { + while(SetupDiEnumDeviceInterfaces(dev_info, NULL, &guid, index, &didata)) + { // get the buffer size for this device detail instance DWORD req_size = 0; - if (!SetupDiGetDeviceInterfaceDetail(dev_info, &didata, NULL, 0, &req_size, NULL)) - { - WARN(_T("couldn't get devinterface info for %u"), index); - break; - } + SetupDiGetDeviceInterfaceDetail(dev_info, &didata, NULL, 0, &req_size, NULL); // (bizarre way of doing it) create a buffer large enough to hold the // fixed-size detail struct components, and the variable string size - using spdidd = SP_DEVICE_INTERFACE_DETAIL_DATA; - spdidd *didetail = (spdidd*)operator new(req_size, (std::align_val_t)alignof(spdidd)); + SP_DEVICE_INTERFACE_DETAIL_DATA *didetail = + (SP_DEVICE_INTERFACE_DETAIL_DATA*) new BYTE[req_size]; + _ASSERT(didetail); didetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // now actually get the detail struct - if (!SetupDiGetDeviceInterfaceDetail(dev_info, &didata, didetail, - req_size, &req_size, NULL)) { - WARN(_T("couldn't get devinterface info for %u #2"), index); + if(!SetupDiGetDeviceInterfaceDetail(dev_info, &didata, didetail, + req_size, &req_size, NULL)) { + WARN(_T("couldn't get devinterface info for %u"), index); break; - } + } // open a shared handle to the device to query it (this will succeed even // if the wiimote is already Connect()'ed) DEEP_TRACE(_T(".. querying device %s"), didetail->DevicePath); - Handle = CreateFile(didetail->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - if (Handle == INVALID_HANDLE_VALUE) { - DEEP_TRACE(_T(".... failed with err %x (probably harmless)."), - GetLastError()); + Handle = CreateFile(didetail->DevicePath, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if(Handle == INVALID_HANDLE_VALUE) { + DEEP_TRACE(_T(".... failed with err %x (probably harmless)."), + GetLastError()); goto skip; - } - + } + // get the device attributes HIDD_ATTRIBUTES attrib; attrib.Size = sizeof(attrib); - if (HidD_GetAttributes(Handle, &attrib)) - { + if(HidD_GetAttributes(Handle, &attrib)) + { // is this a wiimote? - if ((attrib.VendorID != VID) || (attrib.ProductID != PID)) + if((attrib.VendorID != VID) || (attrib.ProductID != PID)) goto skip; // yes, but is it the one we're interested in? ++wiimotes_found; - if ((wiimote_index != FIRST_AVAILABLE) && - (wiimote_index != wiimotes_found)) + if((wiimote_index != FIRST_AVAILABLE) && + (wiimote_index != wiimotes_found)) goto skip; // the wiimote is installed, but it may not be currently paired: - if (wiimote_index == FIRST_AVAILABLE) + if(wiimote_index == FIRST_AVAILABLE) TRACE(_T(".. opening Wiimote %u:"), wiimotes_found); else TRACE(_T(".. opening:")); @@ -298,7 +308,7 @@ bool wiimote::Connect(unsigned wiimote_index, bool force_hidwrites) // (that way subsequent calls can still _discover_ wiimotes above, but // will correctly fail here if they're already connected) CloseHandle(Handle); - + // note this also means that if another application has already opened // the device, the library can no longer connect it (this may happen // with software that enumerates all joysticks in the system, because @@ -309,21 +319,21 @@ bool wiimote::Connect(unsigned wiimote_index, bool force_hidwrites) // call below to open the device in full shared mode - but then the // library can no longer detect if you've already connected a device // and will allow you to connect it twice! So be careful ... - Handle = CreateFile(didetail->DevicePath, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, NULL); - if (Handle == INVALID_HANDLE_VALUE) { + Handle = CreateFile(didetail->DevicePath, GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ| FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, NULL); + if(Handle == INVALID_HANDLE_VALUE) { TRACE(_T(".... failed with err %x"), GetLastError()); goto skip; - } + } // clear the wiimote state & buffers - Clear(false); // preserves existing deadzones + Clear (false); // preserves existing deadzones Internal.Clear(false); // " InternalChanged = NO_CHANGE; - memset(ReadBuff, 0, sizeof(ReadBuff)); - bConnectionLost = false; + memset(ReadBuff , 0, sizeof(ReadBuff)); + bConnectionLost = false; bConnectInProgress = true; // don't parse extensions or request regular // updates until complete // enable async reading @@ -331,49 +341,49 @@ bool wiimote::Connect(unsigned wiimote_index, bool force_hidwrites) // autodetect which write method the Bluetooth stack supports, // by requesting the wiimote status report: - if (force_hidwrites && !_HidD_SetOutputReport) { + if(force_hidwrites && !_HidD_SetOutputReport) { TRACE(_T(".. can't force HID writes (not supported)")); force_hidwrites = false; - } + } - if (force_hidwrites) + if(force_hidwrites) TRACE(_T(".. (HID writes forced)")); - else { + else{ // - try WriteFile() first as it's the most efficient (it uses // harware interrupts where possible and is async-capable): bUseHIDwrite = false; RequestStatusReport(); // and wait for the report to arrive: DWORD last_time = timeGetTime(); - while (!bStatusReceived && ((timeGetTime() - last_time) < 500)) + while(!bStatusReceived && ((timeGetTime()-last_time) < 500)) Sleep(10); - TRACE(_T(".. WriteFile() %s."), bStatusReceived ? _T("succeeded") : - _T("failed")); - } + TRACE(_T(".. WriteFile() %s."), bStatusReceived? _T("succeeded") : + _T("failed")); + } // try HID write method (if supported) - if (!bStatusReceived && _HidD_SetOutputReport) - { + if(!bStatusReceived && _HidD_SetOutputReport) + { bUseHIDwrite = true; RequestStatusReport(); // wait for the report to arrive: DWORD last_time = timeGetTime(); - while (!bStatusReceived && ((timeGetTime() - last_time) < 500)) + while(!bStatusReceived && ((timeGetTime()-last_time) < 500)) Sleep(10); // did we get it? - TRACE(_T(".. HID write %s."), bStatusReceived ? _T("succeeded") : - _T("failed")); - } + TRACE(_T(".. HID write %s."), bStatusReceived? _T("succeeded") : + _T("failed")); + } // still failed? - if (!bStatusReceived) { + if(!bStatusReceived) { WARN(_T("output failed - wiimote is not connected (or confused).")); Disconnect(); goto skip; - } + } - //Sleep(500); - // reset it +//Sleep(500); + // reset it Reset(); // read the wiimote calibration info @@ -406,113 +416,113 @@ bool wiimote::Connect(unsigned wiimote_index, bool force_hidwrites) // create a 2nd alternative id by simply adding all the characters // in the device path to create a single number UniqueID2 = 0; - for (unsigned index = 0; index < _tcslen(didetail->DevicePath); index++) + for(unsigned index=0; index<_tcslen(didetail->DevicePath); index++) UniqueID2 += didetail->DevicePath[index]; #endif // and show when we want to trigger the next periodic status request // (for battery level and connection loss detection) - NextStatusTime = timeGetTime() + REQUEST_STATUS_EVERY_MS; + NextStatusTime = timeGetTime() + REQUEST_STATUS_EVERY_MS; NextMPlusDetectTime = timeGetTime() + DETECT_MPLUS_EVERY_MS; - MPlusDetectCount = DETECT_MPLUS_COUNT; + MPlusDetectCount = DETECT_MPLUS_COUNT; // tidy up - delete[](BYTE*)didetail; + delete[] (BYTE*)didetail; break; - } - skip: + } +skip: // tidy up - delete[](BYTE*)didetail; + delete[] (BYTE*)didetail; - if (Handle != INVALID_HANDLE_VALUE) { + if(Handle != INVALID_HANDLE_VALUE) { CloseHandle(Handle); Handle = INVALID_HANDLE_VALUE; - } + } // if this was the specified wiimote index, abort - if ((wiimote_index != FIRST_AVAILABLE) && - (wiimote_index == (wiimotes_found - 1))) - break; + if((wiimote_index != FIRST_AVAILABLE) && + (wiimote_index == (wiimotes_found-1))) + break; index++; - } + } // clean up our list SetupDiDestroyDeviceInfoList(dev_info); bConnectInProgress = false; - if (IsConnected()) { + if(IsConnected()) { TRACE(_T(".. connected!")); // notify the callbacks (if requested to do so) - if (CallbackTriggerFlags & CONNECTED) - { + if(CallbackTriggerFlags & CONNECTED) + { ChangedNotifier(CONNECTED, Internal); - if (ChangedCallback) + if(ChangedCallback) ChangedCallback(*this, CONNECTED, Internal); - } + } return true; - } + } TRACE(_T(".. connection failed.")); return false; -} + } // ------------------------------------------------------------------------------------ -void wiimote::CalibrateAtRest() -{ +void wiimote::CalibrateAtRest () + { _ASSERT(IsConnected()); - if (!IsConnected()) + if(!IsConnected()) return; // the app calls this to remove 'at rest' offsets from the analogue sensor // values (currently only works for the Balance Board): - if (IsBalanceBoard()) { + if(IsBalanceBoard()) { TRACE(_T(".. removing 'at rest' BBoard offsets.")); Internal.BalanceBoard.AtRestKg = Internal.BalanceBoard.Kg; RefreshState(); + } } -} // ------------------------------------------------------------------------------------ -void wiimote::Disconnect() -{ - if (Handle == INVALID_HANDLE_VALUE) +void wiimote::Disconnect () + { + if(Handle == INVALID_HANDLE_VALUE) return; TRACE(_T("Disconnect().")); - - if (IsConnected()) - { + + if(IsConnected()) + { _ASSERT(_TotalConnected > 0); // sanity _TotalConnected--; - - if (!bConnectionLost) + + if(!bConnectionLost) Reset(); - } + } CloseHandle(Handle); Handle = INVALID_HANDLE_VALUE; - UniqueID = 0; + UniqueID = 0; #ifdef ID2_FROM_DEVICEPATH // (see comments in header) UniqueID2 = 0; #endif // close the read thread - if (ReadParseThread) { + if(ReadParseThread) { // unblock it so it can realise we're closing and exit straight away SetEvent(DataRead); WaitForSingleObject(ReadParseThread, 3000); CloseHandle(ReadParseThread); - ReadParseThread = NULL; - } + ReadParseThread = NULL; + } // close the rumble thread - if (AsyncRumbleThread) { + if(AsyncRumbleThread) { WaitForSingleObject(AsyncRumbleThread, 3000); CloseHandle(AsyncRumbleThread); - AsyncRumbleThread = NULL; + AsyncRumbleThread = NULL; AsyncRumbleTimeout = 0; - } + } // and the sample streaming thread - if (SampleThread) { + if(SampleThread) { WaitForSingleObject(SampleThread, 3000); CloseHandle(SampleThread); SampleThread = NULL; - } + } #ifndef USE_DYNAMIC_HIDQUEUE HID.Deallocate(); @@ -521,197 +531,197 @@ void wiimote::Disconnect() bStatusReceived = false; // and clear the state - Clear(false); // (preserves deadzones) + Clear (false); // (preserves deadzones) Internal.Clear(false); // " InternalChanged = NO_CHANGE; -} + } // ------------------------------------------------------------------------------------ -void wiimote::Reset() -{ +void wiimote::Reset () + { TRACE(_T("Resetting wiimote.")); - - if (bMotionPlusEnabled) + + if(bMotionPlusEnabled) DisableMotionPlus(); // stop updates (by setting report type to non-continuous, buttons-only) - if (IsBalanceBoard()) + if(IsBalanceBoard()) SetReportType(IN_BUTTONS_BALANCE_BOARD, false); else SetReportType(IN_BUTTONS, false); - SetRumble(false); - SetLEDs(0x00); - // MuteSpeaker (true); + SetRumble (false); + SetLEDs (0x00); +// MuteSpeaker (true); EnableSpeaker(false); Sleep(150); // avoids loosing the extension calibration data on Connect() -} + } // ------------------------------------------------------------------------------------ -unsigned __stdcall wiimote::ReadParseThreadfunc(void* param) -{ +unsigned __stdcall wiimote::ReadParseThreadfunc (void* param) + { // this thread waits for the async ReadFile() to deliver data & parses it. // it also requests periodic status updates, deals with connection loss // and ends state recordings with a specific duration: _ASSERT(param); - wiimote &remote = *(wiimote*)param; + wiimote &remote = *(wiimote*)param; OVERLAPPED &overlapped = remote.Overlapped; - unsigned exit_code = 0; // (success) + unsigned exit_code = 0; // (success) - while (1) - { + while(1) + { // wait until the overlapped read completes, or the timeout is reached: DWORD wait = WaitForSingleObject(overlapped.hEvent, 500); // before we deal with the result, let's do some housekeeping: // if we were recently Disconect()ed, exit now - if (remote.Handle == INVALID_HANDLE_VALUE) { + if(remote.Handle == INVALID_HANDLE_VALUE) { DEEP_TRACE(_T("read thread: wiimote was disconnected")); break; - } + } // ditto if the connection was lost (eg. through a failed write) - if (remote.bConnectionLost) - { - connection_lost: + if(remote.bConnectionLost) + { +connection_lost: TRACE(_T("read thread: connection to wiimote was lost")); remote.Disconnect(); remote.InternalChanged = (state_change_flags) - (remote.InternalChanged | CONNECTION_LOST); + (remote.InternalChanged | CONNECTION_LOST); // report via the callback (if any) - if (remote.CallbackTriggerFlags & CONNECTION_LOST) - { + if(remote.CallbackTriggerFlags & CONNECTION_LOST) + { remote.ChangedNotifier(CONNECTION_LOST, remote.Internal); - if (remote.ChangedCallback) + if(remote.ChangedCallback) remote.ChangedCallback(remote, CONNECTION_LOST, remote.Internal); - } + } break; - } + } DWORD time = timeGetTime(); // periodic events (but not if we're streaming audio, // we don't want to cause a glitch) - if (remote.IsConnected() && !remote.bInitInProgress && - !remote.IsPlayingAudio()) - { - // status request due? - if (time > remote.NextStatusTime) + if(remote.IsConnected() && !remote.bInitInProgress && + !remote.IsPlayingAudio()) { + // status request due? + if(time > remote.NextStatusTime) + { #ifdef BEEP_ON_PERIODIC_STATUSREFRESH - Beep(2000, 50); + Beep(2000,50); #endif remote.RequestStatusReport(); // and schedule the next one remote.NextStatusTime = time + REQUEST_STATUS_EVERY_MS; - } + } // motion plus detection due? - if (!remote.IsBalanceBoard() && - // !remote.bConnectInProgress && - !remote.bMotionPlusExtension && - (remote.Internal.ExtensionType != MOTION_PLUS) && - (remote.Internal.ExtensionType != PARTIALLY_INSERTED) && - (time > remote.NextMPlusDetectTime)) - { + if(!remote.IsBalanceBoard() && +// !remote.bConnectInProgress && + !remote.bMotionPlusExtension && + (remote.Internal.ExtensionType != MOTION_PLUS) && + (remote.Internal.ExtensionType != PARTIALLY_INSERTED) && + (time > remote.NextMPlusDetectTime)) + { remote.DetectMotionPlusExtensionAsync(); // we try several times in quick succession before the next // delay: - if (--remote.MPlusDetectCount == 0) { + if(--remote.MPlusDetectCount == 0) { remote.NextMPlusDetectTime = time + DETECT_MPLUS_EVERY_MS; - remote.MPlusDetectCount = DETECT_MPLUS_COUNT; + remote.MPlusDetectCount = DETECT_MPLUS_COUNT; #ifdef _DEBUG TRACE(_T("--")); #endif + } } } - } // if we're state recording and have reached the specified duration, stop - if (remote.Recording.bEnabled && (remote.Recording.EndTimeMS != UNTIL_STOP) && - (time >= remote.Recording.EndTimeMS)) - remote.Recording.bEnabled = false; + if(remote.Recording.bEnabled && (remote.Recording.EndTimeMS != UNTIL_STOP) && + (time >= remote.Recording.EndTimeMS)) + remote.Recording.bEnabled = false; // now handle the wait result: // did the wait time out? - if (wait == WAIT_TIMEOUT) { + if(wait == WAIT_TIMEOUT) { DEEP_TRACE(_T("read thread: timed out")); continue; // wait again - } + } // did an error occurr? - if (wait != WAIT_OBJECT_0) { + if(wait != WAIT_OBJECT_0) { DEEP_TRACE(_T("read thread: error waiting!")); remote.bConnectionLost = true; // deal with it straight away to avoid a longer delay goto connection_lost; - } - + } + // data was received: #ifdef BEEP_DEBUG_READS - Beep(500, 1); + Beep(500,1); #endif DWORD read = 0; // get the data read result GetOverlappedResult(remote.Handle, &overlapped, &read, TRUE); // if we read data, parse it - if (read) { + if(read) { DEEP_TRACE(_T("read thread: parsing data")); remote.OnReadData(read); - } + } else DEEP_TRACE(_T("read thread: didn't get any data??")); - } + } TRACE(_T("(ending read thread)")); #ifdef BEEP_DEBUG_READS - if (exit_code != 0) - Beep(200, 1000); + if(exit_code != 0) + Beep(200,1000); #endif return exit_code; -} + } // ------------------------------------------------------------------------------------ -bool wiimote::BeginAsyncRead() -{ +bool wiimote::BeginAsyncRead () + { // (this is also called before we're fully connected) - if (Handle == INVALID_HANDLE_VALUE) + if(Handle == INVALID_HANDLE_VALUE) return false; DEEP_TRACE(_T(".. starting async read")); #ifdef BEEP_DEBUG_READS - Beep(1000, 1); + Beep(1000,1); #endif DWORD read; if (!ReadFile(Handle, ReadBuff, REPORT_LENGTH, &read, &Overlapped)) { DWORD err = GetLastError(); - if (err != ERROR_IO_PENDING) { + if(err != ERROR_IO_PENDING) { DEEP_TRACE(_T(".... ** ReadFile() failed! **")); return false; + } } - } // launch the completion wait/callback thread - if (!ReadParseThread) { + if(!ReadParseThread) { ReadParseThread = (HANDLE)_beginthreadex(NULL, 0, ReadParseThreadfunc, - this, 0, NULL); + this, 0, NULL); DEEP_TRACE(_T(".... creating read thread")); _ASSERT(ReadParseThread); - if (!ReadParseThread) + if(!ReadParseThread) return false; SetThreadPriority(ReadParseThread, WORKER_THREAD_PRIORITY); - } + } // if ReadFile completed while we called, signal the thread to proceed - if (read) { + if(read) { DEEP_TRACE(_T(".... got data right away")); SetEvent(DataRead); - } + } return true; -} + } // ------------------------------------------------------------------------------------ -void wiimote::OnReadData(DWORD bytes_read) -{ +void wiimote::OnReadData (DWORD bytes_read) + { _ASSERT(bytes_read == REPORT_LENGTH); // copy our input buffer - BYTE buff[REPORT_LENGTH]; + BYTE buff [REPORT_LENGTH]; memcpy(buff, ReadBuff, bytes_read); // start reading again @@ -719,122 +729,122 @@ void wiimote::OnReadData(DWORD bytes_read) // parse it ParseInput(buff); -} + } // ------------------------------------------------------------------------------------ -void wiimote::SetReportType(input_report type, bool continuous) -{ +void wiimote::SetReportType (input_report type, bool continuous) + { _ASSERT(IsConnected()); - if (!IsConnected()) + if(!IsConnected()) return; // the balance board only uses one type of report _ASSERT(!IsBalanceBoard() || type == IN_BUTTONS_BALANCE_BOARD); - if (IsBalanceBoard() && (type != IN_BUTTONS_BALANCE_BOARD)) + if(IsBalanceBoard() && (type != IN_BUTTONS_BALANCE_BOARD)) return; #ifdef TRACE -#define TYPE2NAME(_type) (type==_type)? _T(#_type) - const TCHAR* name = TYPE2NAME(IN_BUTTONS) : - TYPE2NAME(IN_BUTTONS_ACCEL_IR) : - TYPE2NAME(IN_BUTTONS_ACCEL_EXT) : - TYPE2NAME(IN_BUTTONS_ACCEL_IR_EXT) : - TYPE2NAME(IN_BUTTONS_BALANCE_BOARD) : - _T("(unknown?)"); - TRACE(_T("ReportType: %s (%s)"), name, (continuous ? _T("continuous") : - _T("non-continuous"))); + #define TYPE2NAME(_type) (type==_type)? _T(#_type) + const TCHAR* name = TYPE2NAME(IN_BUTTONS) : + TYPE2NAME(IN_BUTTONS_ACCEL_IR) : + TYPE2NAME(IN_BUTTONS_ACCEL_EXT) : + TYPE2NAME(IN_BUTTONS_ACCEL_IR_EXT) : + TYPE2NAME(IN_BUTTONS_BALANCE_BOARD) : + _T("(unknown??)"); + TRACE(_T("ReportType: %s (%s)"), name, (continuous? _T("continuous") : + _T("non-continuous"))); #endif ReportType = type; - switch (type) - { - case IN_BUTTONS_ACCEL_IR: - EnableIR(wiimote_state::ir::EXTENDED); - break; - case IN_BUTTONS_ACCEL_IR_EXT: - EnableIR(wiimote_state::ir::BASIC); - break; - default: - DisableIR(); - break; - } + switch(type) + { + case IN_BUTTONS_ACCEL_IR: + EnableIR(wiimote_state::ir::EXTENDED); + break; + case IN_BUTTONS_ACCEL_IR_EXT: + EnableIR(wiimote_state::ir::BASIC); + break; + default: + DisableIR(); + break; + } - BYTE buff[REPORT_LENGTH] = { 0 }; + BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_TYPE; buff[1] = (continuous ? 0x04 : 0x00) | GetRumbleBit(); buff[2] = (BYTE)type; WriteReport(buff); - // Sleep(15); -} +// Sleep(15); + } // ------------------------------------------------------------------------------------ -void wiimote::SetLEDs(BYTE led_bits) -{ +void wiimote::SetLEDs (BYTE led_bits) + { _ASSERT(IsConnected()); - if (!IsConnected() || bInitInProgress) + if(!IsConnected() || bInitInProgress) return; _ASSERT(led_bits <= 0x0f); led_bits &= 0xf; - - BYTE buff[REPORT_LENGTH] = { 0 }; + + BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_LEDs; - buff[1] = (led_bits << 4) | GetRumbleBit(); + buff[1] = (led_bits<<4) | GetRumbleBit(); WriteReport(buff); Internal.LED.Bits = led_bits; -} + } // ------------------------------------------------------------------------------------ -void wiimote::SetRumble(bool on) -{ +void wiimote::SetRumble (bool on) + { _ASSERT(IsConnected()); - if (!IsConnected()) + if(!IsConnected()) return; - if (Internal.bRumble == on) + if(Internal.bRumble == on) return; Internal.bRumble = on; // if we're streaming audio, we don't need to send a report (sending it makes // the audio glitch, and the rumble bit is sent with every report anyway) - if (IsPlayingAudio()) + if(IsPlayingAudio()) return; - BYTE buff[REPORT_LENGTH] = { 0 }; + BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_STATUS; - buff[1] = on ? 0x01 : 0x00; + buff[1] = on? 0x01 : 0x00; WriteReport(buff); -} + } // ------------------------------------------------------------------------------------ -unsigned __stdcall wiimote::AsyncRumbleThreadfunc(void* param) -{ +unsigned __stdcall wiimote::AsyncRumbleThreadfunc (void* param) + { // auto-disables rumble after x milliseconds: _ASSERT(param); wiimote &remote = *(wiimote*)param; - - while (remote.IsConnected()) - { - if (remote.AsyncRumbleTimeout) + + while(remote.IsConnected()) { - DWORD current_time = timeGetTime(); - if (current_time >= remote.AsyncRumbleTimeout) + if(remote.AsyncRumbleTimeout) { - if (remote.Internal.bRumble) + DWORD current_time = timeGetTime(); + if(current_time >= remote.AsyncRumbleTimeout) + { + if(remote.Internal.bRumble) remote.SetRumble(false); remote.AsyncRumbleTimeout = 0; - } + } Sleep(1); - } + } else Sleep(4); - } + } return 0; -} + } // ------------------------------------------------------------------------------------ -void wiimote::RumbleForAsync(unsigned milliseconds) -{ +void wiimote::RumbleForAsync (unsigned milliseconds) + { // rumble for a fixed amount of time _ASSERT(IsConnected()); - if (!IsConnected()) + if(!IsConnected()) return; SetRumble(true); @@ -844,146 +854,146 @@ void wiimote::RumbleForAsync(unsigned milliseconds) AsyncRumbleTimeout = timeGetTime() + milliseconds; // create the thread? - if (AsyncRumbleThread) + if(AsyncRumbleThread) return; AsyncRumbleThread = (HANDLE)_beginthreadex(NULL, 0, AsyncRumbleThreadfunc, this, - 0, NULL); + 0, NULL); _ASSERT(AsyncRumbleThread); - if (!AsyncRumbleThread) { + if(!AsyncRumbleThread) { WARN(_T("couldn't create rumble thread!")); return; - } + } SetThreadPriority(AsyncRumbleThread, WORKER_THREAD_PRIORITY); -} + } // ------------------------------------------------------------------------------------ -void wiimote::RequestStatusReport() -{ +void wiimote::RequestStatusReport () + { // (this can be called before we're fully connected) _ASSERT(Handle != INVALID_HANDLE_VALUE); - if (Handle == INVALID_HANDLE_VALUE) + if(Handle == INVALID_HANDLE_VALUE) return; - BYTE buff[REPORT_LENGTH] = { 0 }; + BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_STATUS; buff[1] = GetRumbleBit(); WriteReport(buff); -} + } // ------------------------------------------------------------------------------------ -bool wiimote::ReadAddress(int address, short size) -{ +bool wiimote::ReadAddress (int address, short size) + { // asynchronous - BYTE buff[REPORT_LENGTH] = { 0 }; + BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_READMEMORY; buff[1] = (BYTE)(((address & 0xff000000) >> 24) | GetRumbleBit()); - buff[2] = (BYTE)((address & 0x00ff0000) >> 16); - buff[3] = (BYTE)((address & 0x0000ff00) >> 8); - buff[4] = (BYTE)((address & 0x000000ff)); - buff[5] = (BYTE)((size & 0xff00) >> 8); - buff[6] = (BYTE)((size & 0xff)); + buff[2] = (BYTE)( (address & 0x00ff0000) >> 16); + buff[3] = (BYTE)( (address & 0x0000ff00) >> 8); + buff[4] = (BYTE)( (address & 0x000000ff)); + buff[5] = (BYTE)( (size & 0xff00 ) >> 8); + buff[6] = (BYTE)( (size & 0xff)); return WriteReport(buff); -} + } // ------------------------------------------------------------------------------------ -void wiimote::WriteData(int address, BYTE size, const BYTE* buff) -{ +void wiimote::WriteData (int address, BYTE size, const BYTE* buff) + { // asynchronous - BYTE write[REPORT_LENGTH] = { 0 }; + BYTE write [REPORT_LENGTH] = {0}; write[0] = OUT_WRITEMEMORY; write[1] = (BYTE)(((address & 0xff000000) >> 24) | GetRumbleBit()); - write[2] = (BYTE)((address & 0x00ff0000) >> 16); - write[3] = (BYTE)((address & 0x0000ff00) >> 8); - write[4] = (BYTE)((address & 0x000000ff)); + write[2] = (BYTE)( (address & 0x00ff0000) >> 16); + write[3] = (BYTE)( (address & 0x0000ff00) >> 8); + write[4] = (BYTE)( (address & 0x000000ff)); write[5] = size; - memcpy(write + 6, buff, size); + memcpy(write+6, buff, size); WriteReport(write); -} + } // ------------------------------------------------------------------------------------ -int wiimote::ParseInput(BYTE* buff) -{ +int wiimote::ParseInput (BYTE* buff) + { int changed = 0; // lock our internal state (so RefreshState() is blocked until we're done EnterCriticalSection(&StateLock); - switch (buff[0]) - { - case IN_BUTTONS: - DEEP_TRACE(_T(".. parsing buttons.")); - changed |= ParseButtons(buff); - break; - - case IN_BUTTONS_ACCEL: - DEEP_TRACE(_T(".. parsing buttons/accel.")); - changed |= ParseButtons(buff); - if (!IsBalanceBoard()) - changed |= ParseAccel(buff); - break; - - case IN_BUTTONS_ACCEL_EXT: - DEEP_TRACE(_T(".. parsing extenion/accel.")); - changed |= ParseButtons(buff); - changed |= ParseExtension(buff, 6); - if (!IsBalanceBoard()) - changed |= ParseAccel(buff); - break; - - case IN_BUTTONS_ACCEL_IR: - DEEP_TRACE(_T(".. parsing ir/accel.")); - changed |= ParseButtons(buff); - if (!IsBalanceBoard()) { - changed |= ParseAccel(buff); - changed |= ParseIR(buff); - } - break; - - case IN_BUTTONS_ACCEL_IR_EXT: - DEEP_TRACE(_T(".. parsing ir/extenion/accel.")); - changed |= ParseButtons(buff); - changed |= ParseExtension(buff, 16); - if (!IsBalanceBoard()) { - changed |= ParseAccel(buff); - changed |= ParseIR(buff); + switch(buff[0]) + { + case IN_BUTTONS: + DEEP_TRACE(_T(".. parsing buttons.")); + changed |= ParseButtons(buff); + break; + + case IN_BUTTONS_ACCEL: + DEEP_TRACE(_T(".. parsing buttons/accel.")); + changed |= ParseButtons(buff); + if(!IsBalanceBoard()) + changed |= ParseAccel(buff); + break; + + case IN_BUTTONS_ACCEL_EXT: + DEEP_TRACE(_T(".. parsing extenion/accel.")); + changed |= ParseButtons(buff); + changed |= ParseExtension(buff, 6); + if(!IsBalanceBoard()) + changed |= ParseAccel(buff); + break; + + case IN_BUTTONS_ACCEL_IR: + DEEP_TRACE(_T(".. parsing ir/accel.")); + changed |= ParseButtons(buff); + if(!IsBalanceBoard()) { + changed |= ParseAccel(buff); + changed |= ParseIR(buff); + } + break; + + case IN_BUTTONS_ACCEL_IR_EXT: + DEEP_TRACE(_T(".. parsing ir/extenion/accel.")); + changed |= ParseButtons(buff); + changed |= ParseExtension(buff, 16); + if(!IsBalanceBoard()) { + changed |= ParseAccel(buff); + changed |= ParseIR (buff); + } + break; + + case IN_BUTTONS_BALANCE_BOARD: + DEEP_TRACE(_T(".. parsing buttson/balance.")); + changed |= ParseButtons(buff); + changed |= ParseExtension(buff, 3); + break; + + case IN_READADDRESS: + DEEP_TRACE(_T(".. parsing read address.")); + changed |= ParseButtons (buff); + changed |= ParseReadAddress(buff); + break; + + case IN_STATUS: + DEEP_TRACE(_T(".. parsing status.")); + changed |= ParseStatus(buff); + // show that we received the status report (used for output method + // detection during Connect()) + bStatusReceived = true; + break; + + default: + DEEP_TRACE(_T(".. ** unknown input ** (happens).")); + ///_ASSERT(0); + //Debug.WriteLine("Unknown report type: " + type.ToString()); + LeaveCriticalSection(&StateLock); + return false; } - break; - - case IN_BUTTONS_BALANCE_BOARD: - DEEP_TRACE(_T(".. parsing buttson/balance.")); - changed |= ParseButtons(buff); - changed |= ParseExtension(buff, 3); - break; - - case IN_READADDRESS: - DEEP_TRACE(_T(".. parsing read address.")); - changed |= ParseButtons(buff); - changed |= ParseReadAddress(buff); - break; - - case IN_STATUS: - DEEP_TRACE(_T(".. parsing status.")); - changed |= ParseStatus(buff); - // show that we received the status report (used for output method - // detection during Connect()) - bStatusReceived = true; - break; - - default: - DEEP_TRACE(_T(".. ** unknown input ** (happens).")); - ///_ASSERT(0); - //Debug.WriteLine("Unknown report type: " + type.ToString()); - LeaveCriticalSection(&StateLock); - return false; - } // if we're recording and some state we care about has changed, insert it into // the state history - if (Recording.bEnabled && (changed & Recording.TriggerFlags)) - { + if(Recording.bEnabled && (changed & Recording.TriggerFlags)) + { DEEP_TRACE(_T(".. adding state to history")); state_event event; event.time_ms = timeGetTime(); - event.state = *(wiimote_state*)this; + event.state = *(wiimote_state*)this; Recording.StateHistory->push_back(event); - } + } // for polling: show which state has changed since the last RefreshState() InternalChanged = (state_change_flags)(InternalChanged | changed); @@ -991,53 +1001,53 @@ int wiimote::ParseInput(BYTE* buff) LeaveCriticalSection(&StateLock); // callbacks: call it (if set & state the app is interested in has changed) - if (changed & CallbackTriggerFlags) - { + if(changed & CallbackTriggerFlags) + { DEEP_TRACE(_T(".. calling state change callback")); ChangedNotifier((state_change_flags)changed, Internal); - if (ChangedCallback) + if(ChangedCallback) ChangedCallback(*this, (state_change_flags)changed, Internal); - } - + } + DEEP_TRACE(_T(".. parse complete.")); return true; -} + } // ------------------------------------------------------------------------------------ -state_change_flags wiimote::RefreshState() -{ +state_change_flags wiimote::RefreshState () + { // nothing changed since the last call? - if (InternalChanged == NO_CHANGE) + if(InternalChanged == NO_CHANGE) return NO_CHANGE; // copy the internal state to our public data members: // synchronise the interal state with the read/parse thread (we don't want // values changing during the copy) EnterCriticalSection(&StateLock); - + // remember which state changed since the last call state_change_flags changed = InternalChanged; - + // preserve the application-set deadzones (if any) - joystick::deadzone nunchuk_deadzone = Nunchuk.Joystick.DeadZone; + joystick::deadzone nunchuk_deadzone = Nunchuk.Joystick.DeadZone; joystick::deadzone classic_joyl_deadzone = ClassicController.JoystickL.DeadZone; joystick::deadzone classic_joyr_deadzone = ClassicController.JoystickR.DeadZone; - - // copy the internal state to the public one + + // copy the internal state to the public one *(wiimote_state*)this = Internal; - InternalChanged = NO_CHANGE; - - // restore the application-set deadzones - Nunchuk.Joystick.DeadZone = nunchuk_deadzone; + InternalChanged = NO_CHANGE; + + // restore the application-set deadzones + Nunchuk.Joystick.DeadZone = nunchuk_deadzone; ClassicController.JoystickL.DeadZone = classic_joyl_deadzone; ClassicController.JoystickR.DeadZone = classic_joyr_deadzone; LeaveCriticalSection(&StateLock); - + return changed; -} + } // ------------------------------------------------------------------------------------ -void wiimote::DetectMotionPlusExtensionAsync() -{ +void wiimote::DetectMotionPlusExtensionAsync () + { #ifdef _DEBUG TRACE(_T("(looking for motion plus)")); #endif @@ -1047,35 +1057,35 @@ void wiimote::DetectMotionPlusExtensionAsync() // activated, when it maps itself into the usual extension registers), so // try to detect it first: ReadAddress(REGISTER_MOTIONPLUS_DETECT, 6); -} + } // ------------------------------------------------------------------------------------ -bool wiimote::EnableMotionPlus() -{ +bool wiimote::EnableMotionPlus () + { _ASSERT(bMotionPlusDetected); - if (!bMotionPlusDetected) + if(!bMotionPlusDetected) return false; - if (bMotionPlusEnabled) + if(bMotionPlusEnabled) return true; TRACE(_T("Enabling Motion Plus:")); - + bMotionPlusExtension = false; - bInitInProgress = true; - bEnablingMotionPlus = true; + bInitInProgress = true; + bEnablingMotionPlus = true; // Initialize it: - WriteData(REGISTER_MOTIONPLUS_INIT, 0x55); - // Sleep(50); - // Enable it (this maps it to the standard extension port): + WriteData(REGISTER_MOTIONPLUS_INIT , 0x55); +// Sleep(50); + // Enable it (this maps it to the standard extension port): WriteData(REGISTER_MOTIONPLUS_ENABLE, 0x04); - // Sleep(50); - Sleep(500); +// Sleep(50); +Sleep(500); return true; -} + } // ------------------------------------------------------------------------------------ -bool wiimote::DisableMotionPlus() -{ - if (!bMotionPlusDetected || !bMotionPlusEnabled) +bool wiimote::DisableMotionPlus () + { + if(!bMotionPlusDetected || !bMotionPlusEnabled) return false; TRACE(_T("Disabling Motion Plus:")); @@ -1083,53 +1093,53 @@ bool wiimote::DisableMotionPlus() // disable it (this makes standard extensions visible again) WriteData(REGISTER_EXTENSION_INIT1, 0x55); return true; -} + } // ------------------------------------------------------------------------------------ -void wiimote::InitializeExtension() -{ +void wiimote::InitializeExtension () + { TRACE(_T("Initialising Extension.")); // wibrew.org: The new way to initialize the extension is by writing 0x55 to // 0x(4)A400F0, then writing 0x00 to 0x(4)A400FB. It works on all extensions, and // makes the extension type bytes unencrypted. This means that you no longer have // to decrypt the extension bytes using the transform listed above. bInitInProgress = true; - _ASSERT(Internal.bExtension); +_ASSERT(Internal.bExtension); // only initialize if it's not a MotionPlus - if (!bEnablingMotionPlus) { - WriteData(REGISTER_EXTENSION_INIT1, 0x55); - WriteData(REGISTER_EXTENSION_INIT2, 0x00); - } + if(!bEnablingMotionPlus) { + WriteData (REGISTER_EXTENSION_INIT1, 0x55); + WriteData (REGISTER_EXTENSION_INIT2, 0x00); + } else bEnablingMotionPlus = false; - - ReadAddress(REGISTER_EXTENSION_TYPE, 6); -} + + ReadAddress(REGISTER_EXTENSION_TYPE , 6); + } // ------------------------------------------------------------------------------------ -int wiimote::ParseStatus(BYTE* buff) -{ +int wiimote::ParseStatus (BYTE* buff) + { // parse the buttons int changed = ParseButtons(buff); - + // get the battery level BYTE battery_raw = buff[6]; - if (Internal.BatteryRaw != battery_raw) + if(Internal.BatteryRaw != battery_raw) changed |= BATTERY_CHANGED; - Internal.BatteryRaw = battery_raw; + Internal.BatteryRaw = battery_raw; // it is estimated that ~200 is the maximum battery level Internal.BatteryPercent = battery_raw / 2; // there is also a flag that shows if the battery is nearly empty bool drained = buff[3] & 0x01; - if (drained != bBatteryDrained) - { + if(drained != bBatteryDrained) + { bBatteryDrained = drained; - if (drained) + if(drained) changed |= BATTERY_DRAINED; - } + } // leds BYTE leds = buff[3] >> 4; - if (leds != Internal.LED.Bits) + if(leds != Internal.LED.Bits) changed |= LEDS_CHANGED; Internal.LED.Bits = leds; @@ -1138,50 +1148,50 @@ int wiimote::ParseStatus(BYTE* buff) // return changed; bool extension = ((buff[3] & 0x02) != 0); - // TRACE(_T("(extension = %s)"), (extension? _T("TRUE") : _T("false"))); +// TRACE(_T("(extension = %s)"), (extension? _T("TRUE") : _T("false"))); - if (extension != Internal.bExtension) - { - if (!Internal.bExtension) + if(extension != Internal.bExtension) { + if(!Internal.bExtension) + { TRACE(_T("Extension connected:")); Internal.bExtension = true; InitializeExtension(); - } - else { + } + else{ TRACE(_T("Extension disconnected.")); - Internal.bExtension = false; + Internal.bExtension = false; Internal.ExtensionType = wiimote_state::NONE; - bMotionPlusEnabled = false; - bMotionPlusExtension = false; - bMotionPlusDetected = false; - bInitInProgress = false; - bEnablingMotionPlus = false; - changed |= EXTENSION_DISCONNECTED; + bMotionPlusEnabled = false; + bMotionPlusExtension = false; + bMotionPlusDetected = false; + bInitInProgress = false; + bEnablingMotionPlus = false; + changed |= EXTENSION_DISCONNECTED; // renable reports // SetReportType(ReportType); + } } - } - + return changed; -} + } // ------------------------------------------------------------------------------------ -int wiimote::ParseButtons(BYTE* buff) -{ +int wiimote::ParseButtons (BYTE* buff) + { int changed = 0; + +// WORD bits = *(WORD*)(buff+1); + WORD bits = *(WORD*)(buff+1) & Button.ALL; - // WORD bits = *(WORD*)(buff+1); - WORD bits = *(WORD*)(buff + 1) & Button.ALL; - - if (bits != Internal.Button.Bits) + if(bits != Internal.Button.Bits) changed |= BUTTONS_CHANGED; Internal.Button.Bits = bits; - + return changed; -} + } // ------------------------------------------------------------------------------------ -bool wiimote::EstimateOrientationFrom(wiimote_state::acceleration &accel) -{ +bool wiimote::EstimateOrientationFrom (wiimote_state::acceleration &accel) + { // Orientation estimate from acceleration data (shared between wiimote and nunchuk) // return true if the orientation was updated @@ -1191,17 +1201,17 @@ bool wiimote::EstimateOrientationFrom(wiimote_state::acceleration &accel) // TODO: as I'm comparing _squared_ length, I really need different // min/max epsilons... -#define DOT(x1,y1,z1, x2,y2,z2) ((x1*x2) + (y1*y2) + (z1*z2)) + #define DOT(x1,y1,z1, x2,y2,z2) ((x1*x2) + (y1*y2) + (z1*z2)) static const float epsilon = 0.2f; - if ((length_sq >= (1.f - epsilon)) && (length_sq <= (1.f + epsilon))) - { - if (++WiimoteNearGUpdates < 2) + if((length_sq >= (1.f-epsilon)) && (length_sq <= (1.f+epsilon))) + { + if(++WiimoteNearGUpdates < 2) return false; - + // wiimote seems to be stationary: normalize the current acceleration // (ie. the assumed gravity vector) - float inv_len = 1.f / std::sqrt(length_sq); + float inv_len = 1.f / sqrt(length_sq); float x = accel.X * inv_len; float y = accel.Y * inv_len; float z = accel.Z * inv_len; @@ -1213,16 +1223,16 @@ bool wiimote::EstimateOrientationFrom(wiimote_state::acceleration &accel) // and extract pitch & roll from them: // (may not be optimal) - float pitch = -std::asin(y) * 57.2957795f; - // float roll = asin(x) * 57.2957795f; - float roll = std::atan2(x, z) * 57.2957795f; - if (z < 0) { - pitch = (y < 0) ? 180 - pitch : -180 - pitch; - roll = (x < 0) ? -180 - roll : 180 - roll; - } + float pitch = -asin(y) * 57.2957795f; +// float roll = asin(x) * 57.2957795f; + float roll = atan2(x,z) * 57.2957795f; + if(z < 0) { + pitch = (y < 0)? 180 - pitch : -180 - pitch; + roll = (x < 0)? -180 - roll : 180 - roll; + } accel.Orientation.Pitch = pitch; - accel.Orientation.Roll = roll; + accel.Orientation.Roll = roll; // show that we just updated orientation accel.Orientation.UpdateAge = 0; @@ -1230,89 +1240,89 @@ bool wiimote::EstimateOrientationFrom(wiimote_state::acceleration &accel) Beep(2000, 1); #endif return true; // updated - } + } // not updated this time: - WiimoteNearGUpdates = 0; + WiimoteNearGUpdates = 0; // age the last orientation update accel.Orientation.UpdateAge++; return false; -} + } // ------------------------------------------------------------------------------------ -void wiimote::ApplyJoystickDeadZones(wiimote_state::joystick &joy) -{ - // apply the deadzones to each axis (if set) - if ((joy.DeadZone.X > 0.f) && (joy.DeadZone.X <= 1.f)) +void wiimote::ApplyJoystickDeadZones (wiimote_state::joystick &joy) { - if (fabs(joy.X) <= joy.DeadZone.X) + // apply the deadzones to each axis (if set) + if((joy.DeadZone.X > 0.f) && (joy.DeadZone.X <= 1.f)) + { + if(fabs(joy.X) <= joy.DeadZone.X) joy.X = 0; - else { + else{ joy.X -= joy.DeadZone.X * sign(joy.X); joy.X /= 1.f - joy.DeadZone.X; + } } - } - if ((joy.DeadZone.Y > 0.f) && (joy.DeadZone.Y <= 1.f)) - { - if (fabs(joy.Y) <= joy.DeadZone.Y) + if((joy.DeadZone.Y > 0.f) && (joy.DeadZone.Y <= 1.f)) + { + if(fabs(joy.Y) <= joy.DeadZone.Y) joy.Y = 0; - else { + else{ joy.Y -= joy.DeadZone.Y * sign(joy.Y); joy.Y /= 1.f - joy.DeadZone.Y; + } } } -} // ------------------------------------------------------------------------------------ -int wiimote::ParseAccel(BYTE* buff) -{ +int wiimote::ParseAccel (BYTE* buff) + { int changed = 0; - + BYTE raw_x = buff[3]; BYTE raw_y = buff[4]; BYTE raw_z = buff[5]; - if ((raw_x != Internal.Acceleration.RawX) || - (raw_y != Internal.Acceleration.RawY) || - (raw_z != Internal.Acceleration.RawZ)) - changed |= ACCEL_CHANGED; - + if((raw_x != Internal.Acceleration.RawX) || + (raw_y != Internal.Acceleration.RawY) || + (raw_z != Internal.Acceleration.RawZ)) + changed |= ACCEL_CHANGED; + Internal.Acceleration.RawX = raw_x; Internal.Acceleration.RawY = raw_y; Internal.Acceleration.RawZ = raw_z; // avoid / 0.0 when calibration data hasn't arrived yet - if (Internal.CalibrationInfo.X0) - { + if(Internal.CalibrationInfo.X0) + { Internal.Acceleration.X = - ((float)Internal.Acceleration.RawX - Internal.CalibrationInfo.X0) / - ((float)Internal.CalibrationInfo.XG - Internal.CalibrationInfo.X0); + ((float)Internal.Acceleration.RawX - Internal.CalibrationInfo.X0) / + ((float)Internal.CalibrationInfo.XG - Internal.CalibrationInfo.X0); Internal.Acceleration.Y = - ((float)Internal.Acceleration.RawY - Internal.CalibrationInfo.Y0) / - ((float)Internal.CalibrationInfo.YG - Internal.CalibrationInfo.Y0); + ((float)Internal.Acceleration.RawY - Internal.CalibrationInfo.Y0) / + ((float)Internal.CalibrationInfo.YG - Internal.CalibrationInfo.Y0); Internal.Acceleration.Z = - ((float)Internal.Acceleration.RawZ - Internal.CalibrationInfo.Z0) / - ((float)Internal.CalibrationInfo.ZG - Internal.CalibrationInfo.Z0); - } - else { + ((float)Internal.Acceleration.RawZ - Internal.CalibrationInfo.Z0) / + ((float)Internal.CalibrationInfo.ZG - Internal.CalibrationInfo.Z0); + } + else{ Internal.Acceleration.X = - Internal.Acceleration.Y = - Internal.Acceleration.Z = 0.f; - } + Internal.Acceleration.Y = + Internal.Acceleration.Z = 0.f; + } // see if we can estimate the orientation from the current values - if (EstimateOrientationFrom(Internal.Acceleration)) + if(EstimateOrientationFrom(Internal.Acceleration)) changed |= ORIENTATION_CHANGED; - + return changed; -} + } // ------------------------------------------------------------------------------------ -int wiimote::ParseIR(BYTE* buff) -{ - if (Internal.IR.Mode == wiimote_state::ir::OFF) +int wiimote::ParseIR (BYTE* buff) + { + if(Internal.IR.Mode == wiimote_state::ir::OFF) return NO_CHANGE; // avoid garbage values when the MotionPlus is enabled, but the app is // still using the extended IR report type - if (bMotionPlusEnabled && (Internal.IR.Mode == wiimote_state::ir::EXTENDED)) + if(bMotionPlusEnabled && (Internal.IR.Mode == wiimote_state::ir::EXTENDED)) return NO_CHANGE; // take a copy of the existing IR state (so we can detect changes) @@ -1320,100 +1330,100 @@ int wiimote::ParseIR(BYTE* buff) // only updates the other values if the dots are visible (so that the last // valid values stay unmodified) - switch (Internal.IR.Mode) - { - case wiimote_state::ir::BASIC: - // 2 dots are encoded in 5 bytes, so read 2 at a time - for (unsigned step = 0; step < 2; step++) + switch(Internal.IR.Mode) { - ir::dot &dot0 = Internal.IR.Dot[step * 2]; - ir::dot &dot1 = Internal.IR.Dot[step * 2 + 1]; - const unsigned offs = 6 + (step * 5); // 5 bytes for 2 dots - - dot0.bVisible = !(buff[offs] == 0xff && buff[offs + 1] == 0xff); - dot1.bVisible = !(buff[offs + 3] == 0xff && buff[offs + 4] == 0xff); - - if (dot0.bVisible) { - dot0.RawX = buff[offs] | ((buff[offs + 2] >> 4) & 0x03) << 8;; - dot0.RawY = buff[offs + 1] | ((buff[offs + 2] >> 6) & 0x03) << 8;; - dot0.X = 1.f - (dot0.RawX / (float)wiimote_state::ir::MAX_RAW_X); - dot0.Y = (dot0.RawY / (float)wiimote_state::ir::MAX_RAW_Y); - } - if (dot1.bVisible) { - dot1.RawX = buff[offs + 3] | ((buff[offs + 2] >> 0) & 0x03) << 8; - dot1.RawY = buff[offs + 4] | ((buff[offs + 2] >> 2) & 0x03) << 8; - dot1.X = 1.f - (dot1.RawX / (float)wiimote_state::ir::MAX_RAW_X); - dot1.Y = (dot1.RawY / (float)wiimote_state::ir::MAX_RAW_Y); - } - } - break; + case wiimote_state::ir::BASIC: + // 2 dots are encoded in 5 bytes, so read 2 at a time + for(unsigned step=0; step<2; step++) + { + ir::dot &dot0 = Internal.IR.Dot[step*2 ]; + ir::dot &dot1 = Internal.IR.Dot[step*2+1]; + const unsigned offs = 6 + (step*5); // 5 bytes for 2 dots + + dot0.bVisible = !(buff[offs ] == 0xff && buff[offs+1] == 0xff); + dot1.bVisible = !(buff[offs+3] == 0xff && buff[offs+4] == 0xff); + + if(dot0.bVisible) { + dot0.RawX = buff[offs ] | ((buff[offs+2] >> 4) & 0x03) << 8;; + dot0.RawY = buff[offs+1] | ((buff[offs+2] >> 6) & 0x03) << 8;; + dot0.X = 1.f - (dot0.RawX / (float)wiimote_state::ir::MAX_RAW_X); + dot0.Y = (dot0.RawY / (float)wiimote_state::ir::MAX_RAW_Y); + } + if(dot1.bVisible) { + dot1.RawX = buff[offs+3] | ((buff[offs+2] >> 0) & 0x03) << 8; + dot1.RawY = buff[offs+4] | ((buff[offs+2] >> 2) & 0x03) << 8; + dot1.X = 1.f - (dot1.RawX / (float)wiimote_state::ir::MAX_RAW_X); + dot1.Y = (dot1.RawY / (float)wiimote_state::ir::MAX_RAW_Y); + } + } + break; + + case wiimote_state::ir::EXTENDED: + // each dot is encoded into 3 bytes + for(unsigned index=0; index<4; index++) + { + ir::dot &dot = Internal.IR.Dot[index]; + const unsigned offs = 6 + (index * 3); + + dot.bVisible = !(buff[offs ]==0xff && buff[offs+1]==0xff && + buff[offs+2]==0xff); + if(dot.bVisible) { + dot.RawX = buff[offs ] | ((buff[offs+2] >> 4) & 0x03) << 8; + dot.RawY = buff[offs+1] | ((buff[offs+2] >> 6) & 0x03) << 8; + dot.X = 1.f - (dot.RawX / (float)wiimote_state::ir::MAX_RAW_X); + dot.Y = (dot.RawY / (float)wiimote_state::ir::MAX_RAW_Y); + dot.Size = buff[offs+2] & 0x0f; + } + } + break; - case wiimote_state::ir::EXTENDED: - // each dot is encoded into 3 bytes - for (unsigned index = 0; index < 4; index++) - { - ir::dot &dot = Internal.IR.Dot[index]; - const unsigned offs = 6 + (index * 3); - - dot.bVisible = !(buff[offs] == 0xff && buff[offs + 1] == 0xff && - buff[offs + 2] == 0xff); - if (dot.bVisible) { - dot.RawX = buff[offs] | ((buff[offs + 2] >> 4) & 0x03) << 8; - dot.RawY = buff[offs + 1] | ((buff[offs + 2] >> 6) & 0x03) << 8; - dot.X = 1.f - (dot.RawX / (float)wiimote_state::ir::MAX_RAW_X); - dot.Y = (dot.RawY / (float)wiimote_state::ir::MAX_RAW_Y); - dot.Size = buff[offs + 2] & 0x0f; - } + case wiimote_state::ir::FULL: + _ASSERT(0); // not supported yet; + break; } - break; - case wiimote_state::ir::FULL: - _ASSERT(0); // not supported yet; - break; + return memcmp(&prev_ir, &Internal.IR, sizeof(Internal.IR))? IR_CHANGED : 0; } - - return memcmp(&prev_ir, &Internal.IR, sizeof(Internal.IR)) ? IR_CHANGED : 0; -} // ------------------------------------------------------------------------------------ -inline float wiimote::GetBalanceValue(short sensor, short min, short mid, short max) -{ - if (max == mid || mid == min) +inline float wiimote::GetBalanceValue (short sensor, short min, short mid, short max) + { + if(max == mid || mid == min) return 0; - float val = (sensor < mid) ? - 68.0f * ((float)(sensor - min) / (mid - min)) : - 68.0f * ((float)(sensor - mid) / (max - mid)) + 68.0f; - + float val = (sensor < mid)? + 68.0f * ((float)(sensor - min) / (mid - min)) : + 68.0f * ((float)(sensor - mid) / (max - mid)) + 68.0f; + // divide by four (so that each sensor is correct) return val * 0.25f; -} + } // ------------------------------------------------------------------------------------ -int wiimote::ParseExtension(BYTE *buff, unsigned offset) -{ - int changed = 0; - - switch (Internal.ExtensionType) +int wiimote::ParseExtension (BYTE *buff, unsigned offset) { - case wiimote_state::NUNCHUK: - { - // buttons - bool c = (buff[offset + 5] & 0x02) == 0; - bool z = (buff[offset + 5] & 0x01) == 0; - - if ((c != Internal.Nunchuk.C) || (z != Internal.Nunchuk.Z)) - changed |= NUNCHUK_BUTTONS_CHANGED; - - Internal.Nunchuk.C = c; - Internal.Nunchuk.Z = z; - - // acceleration + int changed = 0; + + switch(Internal.ExtensionType) { + case wiimote_state::NUNCHUK: + { + // buttons + bool c = (buff[offset+5] & 0x02) == 0; + bool z = (buff[offset+5] & 0x01) == 0; + + if((c != Internal.Nunchuk.C) || (z != Internal.Nunchuk.Z)) + changed |= NUNCHUK_BUTTONS_CHANGED; + + Internal.Nunchuk.C = c; + Internal.Nunchuk.Z = z; + + // acceleration + { wiimote_state::acceleration &accel = Internal.Nunchuk.Acceleration; - - BYTE raw_x = buff[offset + 2]; - BYTE raw_y = buff[offset + 3]; - BYTE raw_z = buff[offset + 4]; - if ((raw_x != accel.RawX) || (raw_y != accel.RawY) || (raw_z != accel.RawZ)) + + BYTE raw_x = buff[offset+2]; + BYTE raw_y = buff[offset+3]; + BYTE raw_z = buff[offset+4]; + if((raw_x != accel.RawX) || (raw_y != accel.RawY) || (raw_z != accel.RawZ)) changed |= NUNCHUK_ACCEL_CHANGED; accel.RawX = raw_x; @@ -1421,23 +1431,23 @@ int wiimote::ParseExtension(BYTE *buff, unsigned offset) accel.RawZ = raw_z; wiimote_state::nunchuk::calibration_info &calib = - Internal.Nunchuk.CalibrationInfo; + Internal.Nunchuk.CalibrationInfo; accel.X = ((float)raw_x - calib.X0) / ((float)calib.XG - calib.X0); accel.Y = ((float)raw_y - calib.Y0) / ((float)calib.YG - calib.Y0); accel.Z = ((float)raw_z - calib.Z0) / ((float)calib.ZG - calib.Z0); // try to extract orientation from the accel: - if (EstimateOrientationFrom(accel)) + if(EstimateOrientationFrom(accel)) changed |= NUNCHUK_ORIENTATION_CHANGED; - } - { + } + { // joystick: wiimote_state::joystick &joy = Internal.Nunchuk.Joystick; - float raw_x = buff[offset + 0]; - float raw_y = buff[offset + 1]; - - if (std::fabs(raw_x - joy.RawX) < 1e-6f || std::fabs(raw_y - joy.RawY) < 1e-6f) + float raw_x = buff[offset+0]; + float raw_y = buff[offset+1]; + + if((raw_x != joy.RawX) || (raw_y != joy.RawY)) changed |= NUNCHUK_JOYSTICK_CHANGED; joy.RawX = raw_x; @@ -1445,10 +1455,10 @@ int wiimote::ParseExtension(BYTE *buff, unsigned offset) // apply the calibration data wiimote_state::nunchuk::calibration_info &calib = - Internal.Nunchuk.CalibrationInfo; - if (Internal.Nunchuk.CalibrationInfo.MaxX != 0x00) + Internal.Nunchuk.CalibrationInfo; + if(Internal.Nunchuk.CalibrationInfo.MaxX != 0x00) joy.X = ((float)raw_x - calib.MidX) / ((float)calib.MaxX - calib.MinX); - if (calib.MaxY != 0x00) + if(calib.MaxY != 0x00) joy.Y = ((float)raw_y - calib.MidY) / ((float)calib.MaxY - calib.MinY); // i prefer the outputs to range -1 - +1 (note this also affects the @@ -1458,255 +1468,255 @@ int wiimote::ParseExtension(BYTE *buff, unsigned offset) // apply the public deadzones to the internal state (if set) joy.DeadZone = Nunchuk.Joystick.DeadZone; ApplyJoystickDeadZones(joy); - } - } - break; + } + } + break; + + case wiimote_state::CLASSIC: + case wiimote_state::GH3_GHWT_GUITAR: + case wiimote_state::GHWT_DRUMS: + { + // buttons: + WORD bits = *(WORD*)(buff+offset+4); + bits = ~bits; // need to invert bits since 0 is down, and 1 is up + + if(bits != Internal.ClassicController.Button.Bits) + changed |= CLASSIC_BUTTONS_CHANGED; + + Internal.ClassicController.Button.Bits = bits; + + // joysticks: + wiimote_state::joystick &joyL = Internal.ClassicController.JoystickL; + wiimote_state::joystick &joyR = Internal.ClassicController.JoystickR; + + float l_raw_x = (float) (buff[offset+0] & 0x3f); + float l_raw_y = (float) (buff[offset+1] & 0x3f); + float r_raw_x = (float)((buff[offset+2] >> 7) | + ((buff[offset+1] & 0xc0) >> 5) | + ((buff[offset+0] & 0xc0) >> 3)); + float r_raw_y = (float) (buff[offset+2] & 0x1f); + + if((joyL.RawX != l_raw_x) || (joyL.RawY != l_raw_y)) + changed |= CLASSIC_JOYSTICK_L_CHANGED; + if((joyR.RawX != r_raw_x) || (joyR.RawY != r_raw_y)) + changed |= CLASSIC_JOYSTICK_R_CHANGED; + + joyL.RawX = l_raw_x; joyL.RawY = l_raw_y; + joyR.RawX = r_raw_x; joyR.RawY = r_raw_y; + + // apply calibration + wiimote_state::classic_controller::calibration_info &calib = + Internal.ClassicController.CalibrationInfo; + if(calib.MaxXL != 0x00) + joyL.X = (joyL.RawX - calib.MidXL) / ((float)calib.MaxXL - calib.MinXL); + if(calib.MaxYL != 0x00) + joyL.Y = (joyL.RawY - calib.MidYL) / ((float)calib.MaxYL - calib.MinYL); + if(calib.MaxXR != 0x00) + joyR.X = (joyR.RawX - calib.MidXR) / ((float)calib.MaxXR - calib.MinXR); + if(calib.MaxYR != 0x00) + joyR.Y = (joyR.RawY - calib.MidYR) / ((float)calib.MaxYR - calib.MinYR); + + // i prefer the joystick outputs to range -1 - +1 (note this also affects + // the deadzone calculations) + joyL.X *= 2; joyL.Y *= 2; joyR.X *= 2; joyR.Y *= 2; - case wiimote_state::CLASSIC: - case wiimote_state::GH3_GHWT_GUITAR: - case wiimote_state::GHWT_DRUMS: - { - // buttons: - WORD bits = *(WORD*)(buff + offset + 4); - bits = ~bits; // need to invert bits since 0 is down, and 1 is up - - if (bits != Internal.ClassicController.Button.Bits) - changed |= CLASSIC_BUTTONS_CHANGED; - - Internal.ClassicController.Button.Bits = bits; - - // joysticks: - wiimote_state::joystick &joyL = Internal.ClassicController.JoystickL; - wiimote_state::joystick &joyR = Internal.ClassicController.JoystickR; - - float l_raw_x = (float)(buff[offset + 0] & 0x3f); - float l_raw_y = (float)(buff[offset + 1] & 0x3f); - float r_raw_x = (float)((buff[offset + 2] >> 7) | - ((buff[offset + 1] & 0xc0) >> 5) | - ((buff[offset + 0] & 0xc0) >> 3)); - float r_raw_y = (float)(buff[offset + 2] & 0x1f); - - if ((joyL.RawX != l_raw_x) || (joyL.RawY != l_raw_y)) - changed |= CLASSIC_JOYSTICK_L_CHANGED; - if ((joyR.RawX != r_raw_x) || (joyR.RawY != r_raw_y)) - changed |= CLASSIC_JOYSTICK_R_CHANGED; - - joyL.RawX = l_raw_x; joyL.RawY = l_raw_y; - joyR.RawX = r_raw_x; joyR.RawY = r_raw_y; - - // apply calibration - wiimote_state::classic_controller::calibration_info &calib = - Internal.ClassicController.CalibrationInfo; - if (calib.MaxXL != 0x00) - joyL.X = (joyL.RawX - calib.MidXL) / ((float)calib.MaxXL - calib.MinXL); - if (calib.MaxYL != 0x00) - joyL.Y = (joyL.RawY - calib.MidYL) / ((float)calib.MaxYL - calib.MinYL); - if (calib.MaxXR != 0x00) - joyR.X = (joyR.RawX - calib.MidXR) / ((float)calib.MaxXR - calib.MinXR); - if (calib.MaxYR != 0x00) - joyR.Y = (joyR.RawY - calib.MidYR) / ((float)calib.MaxYR - calib.MinYR); - - // i prefer the joystick outputs to range -1 - +1 (note this also affects - // the deadzone calculations) - joyL.X *= 2; joyL.Y *= 2; joyR.X *= 2; joyR.Y *= 2; - - // apply the public deadzones to the internal state (if set) - joyL.DeadZone = ClassicController.JoystickL.DeadZone; - joyR.DeadZone = ClassicController.JoystickR.DeadZone; - ApplyJoystickDeadZones(joyL); - ApplyJoystickDeadZones(joyR); - - // triggers - BYTE raw_trigger_l = ((buff[offset + 2] & 0x60) >> 2) | - (buff[offset + 3] >> 5); - BYTE raw_trigger_r = buff[offset + 3] & 0x1f; - - if ((raw_trigger_l != Internal.ClassicController.RawTriggerL) || - (raw_trigger_r != Internal.ClassicController.RawTriggerR)) - changed |= CLASSIC_TRIGGERS_CHANGED; - - Internal.ClassicController.RawTriggerL = raw_trigger_l; - Internal.ClassicController.RawTriggerR = raw_trigger_r; - - if (calib.MaxTriggerL != 0x00) - Internal.ClassicController.TriggerL = - (float)Internal.ClassicController.RawTriggerL / - ((float)calib.MaxTriggerL - calib.MinTriggerL); - if (calib.MaxTriggerR != 0x00) - Internal.ClassicController.TriggerR = - (float)Internal.ClassicController.RawTriggerR / - ((float)calib.MaxTriggerR - calib.MinTriggerR); - } - break; + // apply the public deadzones to the internal state (if set) + joyL.DeadZone = ClassicController.JoystickL.DeadZone; + joyR.DeadZone = ClassicController.JoystickR.DeadZone; + ApplyJoystickDeadZones(joyL); + ApplyJoystickDeadZones(joyR); + + // triggers + BYTE raw_trigger_l = ((buff[offset+2] & 0x60) >> 2) | + (buff[offset+3] >> 5); + BYTE raw_trigger_r = buff[offset+3] & 0x1f; + + if((raw_trigger_l != Internal.ClassicController.RawTriggerL) || + (raw_trigger_r != Internal.ClassicController.RawTriggerR)) + changed |= CLASSIC_TRIGGERS_CHANGED; + + Internal.ClassicController.RawTriggerL = raw_trigger_l; + Internal.ClassicController.RawTriggerR = raw_trigger_r; + + if(calib.MaxTriggerL != 0x00) + Internal.ClassicController.TriggerL = + (float)Internal.ClassicController.RawTriggerL / + ((float)calib.MaxTriggerL - calib.MinTriggerL); + if(calib.MaxTriggerR != 0x00) + Internal.ClassicController.TriggerR = + (float)Internal.ClassicController.RawTriggerR / + ((float)calib.MaxTriggerR - calib.MinTriggerR); + } + break; - case BALANCE_BOARD: - { - wiimote_state::balance_board::sensors_raw prev_raw = - Internal.BalanceBoard.Raw; - Internal.BalanceBoard.Raw.TopR = - (short)((short)buff[offset + 0] << 8 | buff[offset + 1]); - Internal.BalanceBoard.Raw.BottomR = - (short)((short)buff[offset + 2] << 8 | buff[offset + 3]); - Internal.BalanceBoard.Raw.TopL = - (short)((short)buff[offset + 4] << 8 | buff[offset + 5]); - Internal.BalanceBoard.Raw.BottomL = - (short)((short)buff[offset + 6] << 8 | buff[offset + 7]); - - if ((Internal.BalanceBoard.Raw.TopL != prev_raw.TopL) || - (Internal.BalanceBoard.Raw.TopR != prev_raw.TopR) || - (Internal.BalanceBoard.Raw.BottomL != prev_raw.BottomL) || - (Internal.BalanceBoard.Raw.BottomR != prev_raw.BottomR)) - changed |= BALANCE_WEIGHT_CHANGED; - - Internal.BalanceBoard.Kg.TopL = - GetBalanceValue(Internal.BalanceBoard.Raw.TopL, - Internal.BalanceBoard.CalibrationInfo.Kg0.TopL, - Internal.BalanceBoard.CalibrationInfo.Kg17.TopL, - Internal.BalanceBoard.CalibrationInfo.Kg34.TopL); - Internal.BalanceBoard.Kg.TopR = - GetBalanceValue(Internal.BalanceBoard.Raw.TopR, - Internal.BalanceBoard.CalibrationInfo.Kg0.TopR, - Internal.BalanceBoard.CalibrationInfo.Kg17.TopR, - Internal.BalanceBoard.CalibrationInfo.Kg34.TopR); - Internal.BalanceBoard.Kg.BottomL = - GetBalanceValue(Internal.BalanceBoard.Raw.BottomL, - Internal.BalanceBoard.CalibrationInfo.Kg0.BottomL, - Internal.BalanceBoard.CalibrationInfo.Kg17.BottomL, - Internal.BalanceBoard.CalibrationInfo.Kg34.BottomL); - Internal.BalanceBoard.Kg.BottomR = - GetBalanceValue(Internal.BalanceBoard.Raw.BottomR, - Internal.BalanceBoard.CalibrationInfo.Kg0.BottomR, - Internal.BalanceBoard.CalibrationInfo.Kg17.BottomR, - Internal.BalanceBoard.CalibrationInfo.Kg34.BottomR); - - // uses these as the 'at rest' offsets? (immediately after Connect(), - // or if the app called CalibrateAtRest()) - if (bCalibrateAtRest) { - bCalibrateAtRest = false; - TRACE(_T(".. Auto-removing 'at rest' BBoard offsets.")); - Internal.BalanceBoard.AtRestKg = Internal.BalanceBoard.Kg; - } + case BALANCE_BOARD: + { + wiimote_state::balance_board::sensors_raw prev_raw = + Internal.BalanceBoard.Raw; + Internal.BalanceBoard.Raw.TopR = + (short)((short)buff[offset+0] << 8 | buff[offset+1]); + Internal.BalanceBoard.Raw.BottomR = + (short)((short)buff[offset+2] << 8 | buff[offset+3]); + Internal.BalanceBoard.Raw.TopL = + (short)((short)buff[offset+4] << 8 | buff[offset+5]); + Internal.BalanceBoard.Raw.BottomL = + (short)((short)buff[offset+6] << 8 | buff[offset+7]); + + if((Internal.BalanceBoard.Raw.TopL != prev_raw.TopL) || + (Internal.BalanceBoard.Raw.TopR != prev_raw.TopR) || + (Internal.BalanceBoard.Raw.BottomL != prev_raw.BottomL) || + (Internal.BalanceBoard.Raw.BottomR != prev_raw.BottomR)) + changed |= BALANCE_WEIGHT_CHANGED; + + Internal.BalanceBoard.Kg.TopL = + GetBalanceValue(Internal.BalanceBoard.Raw.TopL, + Internal.BalanceBoard.CalibrationInfo.Kg0 .TopL, + Internal.BalanceBoard.CalibrationInfo.Kg17.TopL, + Internal.BalanceBoard.CalibrationInfo.Kg34.TopL); + Internal.BalanceBoard.Kg.TopR = + GetBalanceValue(Internal.BalanceBoard.Raw.TopR, + Internal.BalanceBoard.CalibrationInfo.Kg0 .TopR, + Internal.BalanceBoard.CalibrationInfo.Kg17.TopR, + Internal.BalanceBoard.CalibrationInfo.Kg34.TopR); + Internal.BalanceBoard.Kg.BottomL = + GetBalanceValue(Internal.BalanceBoard.Raw.BottomL, + Internal.BalanceBoard.CalibrationInfo.Kg0 .BottomL, + Internal.BalanceBoard.CalibrationInfo.Kg17.BottomL, + Internal.BalanceBoard.CalibrationInfo.Kg34.BottomL); + Internal.BalanceBoard.Kg.BottomR = + GetBalanceValue(Internal.BalanceBoard.Raw.BottomR, + Internal.BalanceBoard.CalibrationInfo.Kg0 .BottomR, + Internal.BalanceBoard.CalibrationInfo.Kg17.BottomR, + Internal.BalanceBoard.CalibrationInfo.Kg34.BottomR); + + // uses these as the 'at rest' offsets? (immediately after Connect(), + // or if the app called CalibrateAtRest()) + if(bCalibrateAtRest) { + bCalibrateAtRest = false; + TRACE(_T(".. Auto-removing 'at rest' BBoard offsets.")); + Internal.BalanceBoard.AtRestKg = Internal.BalanceBoard.Kg; + } - // remove the 'at rest' offsets - Internal.BalanceBoard.Kg.TopL -= BalanceBoard.AtRestKg.TopL; - Internal.BalanceBoard.Kg.TopR -= BalanceBoard.AtRestKg.TopR; - Internal.BalanceBoard.Kg.BottomL -= BalanceBoard.AtRestKg.BottomL; - Internal.BalanceBoard.Kg.BottomR -= BalanceBoard.AtRestKg.BottomR; - - // compute the average - Internal.BalanceBoard.Kg.Total = Internal.BalanceBoard.Kg.TopL + - Internal.BalanceBoard.Kg.TopR + - Internal.BalanceBoard.Kg.BottomL + - Internal.BalanceBoard.Kg.BottomR; - // and convert to Lbs - const float KG2LB = 2.20462262f; - Internal.BalanceBoard.Lb = Internal.BalanceBoard.Kg; - Internal.BalanceBoard.Lb.TopL *= KG2LB; - Internal.BalanceBoard.Lb.TopR *= KG2LB; - Internal.BalanceBoard.Lb.BottomL *= KG2LB; - Internal.BalanceBoard.Lb.BottomR *= KG2LB; - Internal.BalanceBoard.Lb.Total *= KG2LB; - } - break; + // remove the 'at rest' offsets + Internal.BalanceBoard.Kg.TopL -= BalanceBoard.AtRestKg.TopL; + Internal.BalanceBoard.Kg.TopR -= BalanceBoard.AtRestKg.TopR; + Internal.BalanceBoard.Kg.BottomL -= BalanceBoard.AtRestKg.BottomL; + Internal.BalanceBoard.Kg.BottomR -= BalanceBoard.AtRestKg.BottomR; + + // compute the average + Internal.BalanceBoard.Kg.Total = Internal.BalanceBoard.Kg.TopL + + Internal.BalanceBoard.Kg.TopR + + Internal.BalanceBoard.Kg.BottomL + + Internal.BalanceBoard.Kg.BottomR; + // and convert to Lbs + const float KG2LB = 2.20462262f; + Internal.BalanceBoard.Lb = Internal.BalanceBoard.Kg; + Internal.BalanceBoard.Lb.TopL *= KG2LB; + Internal.BalanceBoard.Lb.TopR *= KG2LB; + Internal.BalanceBoard.Lb.BottomL *= KG2LB; + Internal.BalanceBoard.Lb.BottomR *= KG2LB; + Internal.BalanceBoard.Lb.Total *= KG2LB; + } + break; - case MOTION_PLUS: - { - bMotionPlusDetected = true; - bMotionPlusEnabled = true; - - short yaw = ((unsigned short)buff[offset + 3] & 0xFC) << 6 | - (unsigned short)buff[offset + 0]; - short pitch = ((unsigned short)buff[offset + 5] & 0xFC) << 6 | - (unsigned short)buff[offset + 2]; - short roll = ((unsigned short)buff[offset + 4] & 0xFC) << 6 | - (unsigned short)buff[offset + 1]; - - // we get one set of bogus values when the MotionPlus is disconnected, - // so ignore them - if ((yaw != 0x3fff) || (pitch != 0x3fff) || (roll != 0x3fff)) - { - wiimote_state::motion_plus::sensors_raw &raw = Internal.MotionPlus.Raw; - - if ((raw.Yaw != yaw) || (raw.Pitch != pitch) || (raw.Roll != roll)) - changed |= MOTIONPLUS_SPEED_CHANGED; - - raw.Yaw = yaw; - raw.Pitch = pitch; - raw.Roll = roll; - - // convert to float values - bool yaw_slow = (buff[offset + 3] & 0x2) == 0x2; - bool pitch_slow = (buff[offset + 3] & 0x1) == 0x1; - bool roll_slow = (buff[offset + 4] & 0x2) == 0x2; - float y_scale = yaw_slow ? 0.05f : 0.25f; - float p_scale = pitch_slow ? 0.05f : 0.25f; - float r_scale = roll_slow ? 0.05f : 0.25f; - - Internal.MotionPlus.Speed.Yaw = -(raw.Yaw - 0x1F7F) * y_scale; - Internal.MotionPlus.Speed.Pitch = -(raw.Pitch - 0x1F7F) * p_scale; - Internal.MotionPlus.Speed.Roll = -(raw.Roll - 0x1F7F) * r_scale; - - // show if there's an extension plugged into the MotionPlus: - bool extension = buff[offset + 4] & 1; - if (extension != bMotionPlusExtension) + case MOTION_PLUS: { - if (extension) { - TRACE(_T(".. MotionPlus extension found.")); - changed |= MOTIONPLUS_EXTENSION_CONNECTED; - } - else { - TRACE(_T(".. MotionPlus' extension disconnected.")); - changed |= MOTIONPLUS_EXTENSION_DISCONNECTED; + bMotionPlusDetected = true; + bMotionPlusEnabled = true; + + short yaw = ((unsigned short)buff[offset+3] & 0xFC)<<6 | + (unsigned short)buff[offset+0]; + short pitch = ((unsigned short)buff[offset+5] & 0xFC)<<6 | + (unsigned short)buff[offset+2]; + short roll = ((unsigned short)buff[offset+4] & 0xFC)<<6 | + (unsigned short)buff[offset+1]; + + // we get one set of bogus values when the MotionPlus is disconnected, + // so ignore them + if((yaw != 0x3fff) || (pitch != 0x3fff) || (roll != 0x3fff)) + { + wiimote_state::motion_plus::sensors_raw &raw = Internal.MotionPlus.Raw; + + if((raw.Yaw != yaw) || (raw.Pitch != pitch) || (raw.Roll != roll)) + changed |= MOTIONPLUS_SPEED_CHANGED; + + raw.Yaw = yaw; + raw.Pitch = pitch; + raw.Roll = roll; + + // convert to float values + bool yaw_slow = (buff[offset+3] & 0x2) == 0x2; + bool pitch_slow = (buff[offset+3] & 0x1) == 0x1; + bool roll_slow = (buff[offset+4] & 0x2) == 0x2; + float y_scale = yaw_slow? 0.05f : 0.25f; + float p_scale = pitch_slow? 0.05f : 0.25f; + float r_scale = roll_slow? 0.05f : 0.25f; + + Internal.MotionPlus.Speed.Yaw = -(raw.Yaw - 0x1F7F) * y_scale; + Internal.MotionPlus.Speed.Pitch = -(raw.Pitch - 0x1F7F) * p_scale; + Internal.MotionPlus.Speed.Roll = -(raw.Roll - 0x1F7F) * r_scale; + + // show if there's an extension plugged into the MotionPlus: + bool extension = buff[offset+4] & 1; + if(extension != bMotionPlusExtension) + { + if(extension) { + TRACE(_T(".. MotionPlus extension found.")); + changed |= MOTIONPLUS_EXTENSION_CONNECTED; + } + else{ + TRACE(_T(".. MotionPlus' extension disconnected.")); + changed |= MOTIONPLUS_EXTENSION_DISCONNECTED; + } + } + bMotionPlusExtension = extension; } + // while we're getting data, the plus is obviously detected/enabled +// bMotionPlusDetected = bMotionPlusEnabled = true; } - bMotionPlusExtension = extension; + break; } - // while we're getting data, the plus is obviously detected/enabled -// bMotionPlusDetected = bMotionPlusEnabled = true; - } - break; - } - + return changed; -} + } // ------------------------------------------------------------------------------------ -int wiimote::ParseReadAddress(BYTE* buff) -{ +int wiimote::ParseReadAddress (BYTE* buff) + { // decode the address that was queried: - int address = buff[4] << 8 | buff[5]; - int size = buff[3] >> 4; - (void)size; - int changed = 0; + int address = buff[4]<<8 | buff[5]; + int size = buff[3] >> 4; + (void)size; + int changed = 0; - if ((buff[3] & 0x08) != 0) { + if((buff[3] & 0x08) != 0) { WARN(_T("error: read address not valid.")); _ASSERT(0); return NO_CHANGE; - } + } // address read failed (write-only)? - else if ((buff[3] & 0x07) != 0) - { - // this also happens when attempting to detect a non-existant MotionPlus - if (MotionPlusDetectCount) + else if((buff[3] & 0x07) != 0) { - --MotionPlusDetectCount; - if (Internal.ExtensionType == MOTION_PLUS) + // this also happens when attempting to detect a non-existant MotionPlus + if(MotionPlusDetectCount) { - if (bMotionPlusDetected) + --MotionPlusDetectCount; + if(Internal.ExtensionType == MOTION_PLUS) + { + if(bMotionPlusDetected) TRACE(_T(".. MotionPlus removed.")); - bMotionPlusDetected = false; - bMotionPlusEnabled = false; + bMotionPlusDetected = false; + bMotionPlusEnabled = false; // the MotionPlus can sometimes get confused - initializing // extenions fixes it: // if(address == 0xfa) // InitializeExtension(); + } } - } else WARN(_T("error: attempt to read from write-only register 0x%X."), buff[3]); return NO_CHANGE; - } + } // *NOTE*: this is a major (but convenient) hack! The returned data only // contains the lower two bytes of the address that was queried. @@ -1716,264 +1726,258 @@ int wiimote::ParseReadAddress(BYTE* buff) // skip the header buff += 6; - switch (address) - { - case (REGISTER_CALIBRATION & 0xffff): - { - _ASSERT(size == 6); - TRACE(_T(".. got wiimote calibration.")); - Internal.CalibrationInfo.X0 = buff[0]; - Internal.CalibrationInfo.Y0 = buff[1]; - Internal.CalibrationInfo.Z0 = buff[2]; - Internal.CalibrationInfo.XG = buff[4]; - Internal.CalibrationInfo.YG = buff[5]; - Internal.CalibrationInfo.ZG = buff[6]; - //changed |= CALIBRATION_CHANGED; - } - break; - - // note: this covers both the normal extension and motion plus extension - // addresses (0x4a400fa / 0x4a600fa) - case (REGISTER_EXTENSION_TYPE & 0xffff): - { - _ASSERT(size == 5); - QWORD type = *(QWORD*)buff; - - // TRACE(_T("(found extension 0x%I64x)"), type); - - static const QWORD NUNCHUK = 0x000020A40000ULL; - static const QWORD CLASSIC = 0x010120A40000ULL; - static const QWORD GH3_GHWT_GUITAR = 0x030120A40000ULL; - static const QWORD GHWT_DRUMS = 0x030120A40001ULL; - static const QWORD BALANCE_BOARD = 0x020420A40000ULL; - static const QWORD MOTION_PLUS = 0x050420A40000ULL; - static const QWORD MOTION_PLUS_DETECT = 0x050020a60000ULL; - static const QWORD MOTION_PLUS_DETECT2 = 0x050420a60000ULL; - static const QWORD PARTIALLY_INSERTED = 0xffffffffffffULL; - - // MotionPlus: _before_ it's been activated - if ((type == MOTION_PLUS_DETECT) || (type == MOTION_PLUS_DETECT2)) + switch(address) { - if (!bMotionPlusDetected) { - TRACE(_T("Motion Plus detected!")); - changed |= MOTIONPLUS_DETECTED; + case (REGISTER_CALIBRATION & 0xffff): + { + _ASSERT(size == 6); + TRACE(_T(".. got wiimote calibration.")); + Internal.CalibrationInfo.X0 = buff[0]; + Internal.CalibrationInfo.Y0 = buff[1]; + Internal.CalibrationInfo.Z0 = buff[2]; + Internal.CalibrationInfo.XG = buff[4]; + Internal.CalibrationInfo.YG = buff[5]; + Internal.CalibrationInfo.ZG = buff[6]; + //changed |= CALIBRATION_CHANGED; } - bMotionPlusDetected = true; - --MotionPlusDetectCount; break; - } + + // note: this covers both the normal extension and motion plus extension + // addresses (0x4a400fa / 0x4a600fa) + case (REGISTER_EXTENSION_TYPE & 0xffff): + { + _ASSERT(size == 5); + QWORD type = *(QWORD*)buff; + +// TRACE(_T("(found extension 0x%I64x)"), type); + + static const QWORD NUNCHUK = 0x000020A40000ULL; + static const QWORD CLASSIC = 0x010120A40000ULL; + static const QWORD GH3_GHWT_GUITAR = 0x030120A40000ULL; + static const QWORD GHWT_DRUMS = 0x030120A40001ULL; + static const QWORD BALANCE_BOARD = 0x020420A40000ULL; + static const QWORD MOTION_PLUS = 0x050420A40000ULL; + static const QWORD MOTION_PLUS_DETECT = 0x050020a60000ULL; + static const QWORD MOTION_PLUS_DETECT2 = 0x050420a60000ULL; + static const QWORD PARTIALLY_INSERTED = 0xffffffffffffULL; + + // MotionPlus: _before_ it's been activated + if((type == MOTION_PLUS_DETECT) || (type == MOTION_PLUS_DETECT2)) + { + if(!bMotionPlusDetected) { + TRACE(_T("Motion Plus detected!")); + changed |= MOTIONPLUS_DETECTED; + } + bMotionPlusDetected = true; + --MotionPlusDetectCount; + break; + } - // sometimes we get idempotent ExtensionType events -#define IF_TYPE(id, ...) \ - if(type == id) \ - { \ - if(Internal.ExtensionType == wiimote_state::id) \ - break; \ - Internal.ExtensionType = wiimote_state::id; \ - { __VA_ARGS__ } \ - } + #define IF_TYPE(id) if(type == id) { \ + /* sometimes it comes in more than once */ \ + if(Internal.ExtensionType == wiimote_state::id)\ + break; \ + Internal.ExtensionType = wiimote_state::id; // MotionPlus: once it's activated & mapped to the standard ext. port - IF_TYPE(MOTION_PLUS, - TRACE(_T(".. Motion Plus!")); - // and start a query for the calibration data - ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); - bMotionPlusDetected = true; - ) - else IF_TYPE(NUNCHUK, - TRACE(_T(".. Nunchuk!")); - bMotionPlusEnabled = false; - // and start a query for the calibration data - ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); - ) - else IF_TYPE(CLASSIC, - TRACE(_T(".. Classic Controller!")); - bMotionPlusEnabled = false; - // and start a query for the calibration data - ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); - ) - else IF_TYPE(GH3_GHWT_GUITAR, - // sometimes it comes in more than once? - TRACE(_T(".. GH3/GHWT Guitar Controller!")); - bMotionPlusEnabled = false; - // and start a query for the calibration data - ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); - ) - else IF_TYPE(GHWT_DRUMS, - TRACE(_T(".. GHWT Drums!")); - bMotionPlusEnabled = false; - // and start a query for the calibration data - ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); - ) - else IF_TYPE(BALANCE_BOARD, - TRACE(_T(".. Balance Board!")); - bMotionPlusEnabled = false; - // and start a query for the calibration data - ReadAddress(REGISTER_BALANCE_CALIBRATION, 24); - ) - else if (type == PARTIALLY_INSERTED) { - // sometimes it comes in more than once? - if (Internal.ExtensionType == wiimote_state::PARTIALLY_INSERTED) - Sleep(50); - TRACE(_T(".. partially inserted!")); - bMotionPlusEnabled = false; - Internal.ExtensionType = wiimote_state::PARTIALLY_INSERTED; - changed |= EXTENSION_PARTIALLY_INSERTED; - // try initializing the extension again by requesting another - // status report (this usually fixes it) - Internal.bExtension = false; - RequestStatusReport(); - } - else { + IF_TYPE(MOTION_PLUS) + TRACE(_T(".. Motion Plus!")); + // and start a query for the calibration data + ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); + bMotionPlusDetected = true; + } + else IF_TYPE(NUNCHUK) + TRACE(_T(".. Nunchuk!")); + bMotionPlusEnabled = false; + // and start a query for the calibration data + ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); + } + else IF_TYPE(CLASSIC) + TRACE(_T(".. Classic Controller!")); + bMotionPlusEnabled = false; + // and start a query for the calibration data + ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); + } + else IF_TYPE(GH3_GHWT_GUITAR) + // sometimes it comes in more than once? + TRACE(_T(".. GH3/GHWT Guitar Controller!")); + bMotionPlusEnabled = false; + // and start a query for the calibration data + ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); + } + else IF_TYPE(GHWT_DRUMS) + TRACE(_T(".. GHWT Drums!")); + bMotionPlusEnabled = false; + // and start a query for the calibration data + ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); + } + else IF_TYPE(BALANCE_BOARD) + TRACE(_T(".. Balance Board!")); + bMotionPlusEnabled = false; + // and start a query for the calibration data + ReadAddress(REGISTER_BALANCE_CALIBRATION, 24); + } + else if(type == PARTIALLY_INSERTED) { + // sometimes it comes in more than once? + if(Internal.ExtensionType == wiimote_state::PARTIALLY_INSERTED) + Sleep(50); + TRACE(_T(".. partially inserted!")); + bMotionPlusEnabled = false; + Internal.ExtensionType = wiimote_state::PARTIALLY_INSERTED; + changed |= EXTENSION_PARTIALLY_INSERTED; + // try initializing the extension again by requesting another + // status report (this usually fixes it) + Internal.bExtension = false; + RequestStatusReport(); + } + else{ TRACE(_T("unknown extension controller found (0x%I64x)"), type); + } } - } - break; - - case (REGISTER_EXTENSION_CALIBRATION & 0xffff): - case (REGISTER_BALANCE_CALIBRATION & 0xffff): - { - // _ASSERT(((Internal.ExtensionType == BALANCE_BOARD) && (size == 31)) || - // ((Internal.ExtensionType != BALANCE_BOARD) && (size == 15))); + break; + + case (REGISTER_EXTENSION_CALIBRATION & 0xffff): + case (REGISTER_BALANCE_CALIBRATION & 0xffff): + { +// _ASSERT(((Internal.ExtensionType == BALANCE_BOARD) && (size == 31)) || +// ((Internal.ExtensionType != BALANCE_BOARD) && (size == 15))); - switch (Internal.ExtensionType) - { - case wiimote_state::NUNCHUK: - { - wiimote_state::nunchuk::calibration_info - &calib = Internal.Nunchuk.CalibrationInfo; - - calib.X0 = buff[0]; - calib.Y0 = buff[1]; - calib.Z0 = buff[2]; - calib.XG = buff[4]; - calib.YG = buff[5]; - calib.ZG = buff[6]; - calib.MaxX = buff[8]; - calib.MinX = buff[9]; - calib.MidX = buff[10]; - calib.MaxY = buff[11]; - calib.MinY = buff[12]; - calib.MidY = buff[13]; - - changed |= NUNCHUK_CONNECTED;//|NUNCHUK_CALIBRATION_CHANGED; - // reenable reports + switch(Internal.ExtensionType) + { + case wiimote_state::NUNCHUK: + { + wiimote_state::nunchuk::calibration_info + &calib = Internal.Nunchuk.CalibrationInfo; + + calib.X0 = buff[ 0]; + calib.Y0 = buff[ 1]; + calib.Z0 = buff[ 2]; + calib.XG = buff[ 4]; + calib.YG = buff[ 5]; + calib.ZG = buff[ 6]; + calib.MaxX = buff[ 8]; + calib.MinX = buff[ 9]; + calib.MidX = buff[10]; + calib.MaxY = buff[11]; + calib.MinY = buff[12]; + calib.MidY = buff[13]; + + changed |= NUNCHUK_CONNECTED;//|NUNCHUK_CALIBRATION_CHANGED; + // reenable reports // SetReportType(ReportType); - } - break; - - case wiimote_state::CLASSIC: - case wiimote_state::GH3_GHWT_GUITAR: - case wiimote_state::GHWT_DRUMS: - { - wiimote_state::classic_controller::calibration_info - &calib = Internal.ClassicController.CalibrationInfo; - - calib.MaxXL = buff[0] >> 2; - calib.MinXL = buff[1] >> 2; - calib.MidXL = buff[2] >> 2; - calib.MaxYL = buff[3] >> 2; - calib.MinYL = buff[4] >> 2; - calib.MidYL = buff[5] >> 2; - calib.MaxXR = buff[6] >> 3; - calib.MinXR = buff[7] >> 3; - calib.MidXR = buff[8] >> 3; - calib.MaxYR = buff[9] >> 3; - calib.MinYR = buff[10] >> 3; - calib.MidYR = buff[11] >> 3; - // this doesn't seem right... - // calib.MinTriggerL = buff[12] >> 3; - // calib.MaxTriggerL = buff[14] >> 3; - // calib.MinTriggerR = buff[13] >> 3; - // calib.MaxTriggerR = buff[15] >> 3; - calib.MinTriggerL = 0; - calib.MaxTriggerL = 31; - calib.MinTriggerR = 0; - calib.MaxTriggerR = 31; - - changed |= CLASSIC_CONNECTED;//|CLASSIC_CALIBRATION_CHANGED; - // reenable reports + } + break; + + case wiimote_state::CLASSIC: + case wiimote_state::GH3_GHWT_GUITAR: + case wiimote_state::GHWT_DRUMS: + { + wiimote_state::classic_controller::calibration_info + &calib = Internal.ClassicController.CalibrationInfo; + + calib.MaxXL = buff[ 0] >> 2; + calib.MinXL = buff[ 1] >> 2; + calib.MidXL = buff[ 2] >> 2; + calib.MaxYL = buff[ 3] >> 2; + calib.MinYL = buff[ 4] >> 2; + calib.MidYL = buff[ 5] >> 2; + calib.MaxXR = buff[ 6] >> 3; + calib.MinXR = buff[ 7] >> 3; + calib.MidXR = buff[ 8] >> 3; + calib.MaxYR = buff[ 9] >> 3; + calib.MinYR = buff[10] >> 3; + calib.MidYR = buff[11] >> 3; + // this doesn't seem right... + // calib.MinTriggerL = buff[12] >> 3; + // calib.MaxTriggerL = buff[14] >> 3; + // calib.MinTriggerR = buff[13] >> 3; + // calib.MaxTriggerR = buff[15] >> 3; + calib.MinTriggerL = 0; + calib.MaxTriggerL = 31; + calib.MinTriggerR = 0; + calib.MaxTriggerR = 31; + + changed |= CLASSIC_CONNECTED;//|CLASSIC_CALIBRATION_CHANGED; + // reenable reports // SetReportType(ReportType); - } - break; + } + break; - case BALANCE_BOARD: - { - // first part, 0 & 17kg calibration values - wiimote_state::balance_board::calibration_info - &calib = Internal.BalanceBoard.CalibrationInfo; + case BALANCE_BOARD: + { + // first part, 0 & 17kg calibration values + wiimote_state::balance_board::calibration_info + &calib = Internal.BalanceBoard.CalibrationInfo; - calib.Kg0.TopR = (short)((short)buff[0] << 8 | buff[1]); - calib.Kg0.BottomR = (short)((short)buff[2] << 8 | buff[3]); - calib.Kg0.TopL = (short)((short)buff[4] << 8 | buff[5]); - calib.Kg0.BottomL = (short)((short)buff[6] << 8 | buff[7]); + calib.Kg0 .TopR = (short)((short)buff[0] << 8 | buff[1]); + calib.Kg0 .BottomR = (short)((short)buff[2] << 8 | buff[3]); + calib.Kg0 .TopL = (short)((short)buff[4] << 8 | buff[5]); + calib.Kg0 .BottomL = (short)((short)buff[6] << 8 | buff[7]); - calib.Kg17.TopR = (short)((short)buff[8] << 8 | buff[9]); - calib.Kg17.BottomR = (short)((short)buff[10] << 8 | buff[11]); - calib.Kg17.TopL = (short)((short)buff[12] << 8 | buff[13]); - calib.Kg17.BottomL = (short)((short)buff[14] << 8 | buff[15]); + calib.Kg17.TopR = (short)((short)buff[8] << 8 | buff[9]); + calib.Kg17.BottomR = (short)((short)buff[10] << 8 | buff[11]); + calib.Kg17.TopL = (short)((short)buff[12] << 8 | buff[13]); + calib.Kg17.BottomL = (short)((short)buff[14] << 8 | buff[15]); - // 2nd part is scanned above - } - break; + // 2nd part is scanned above + } + break; - case MOTION_PLUS: - { - // TODO: not known how the calibration values work - changed |= MOTIONPLUS_ENABLED; - bMotionPlusEnabled = true; - bInitInProgress = false; - // reenable reports + case MOTION_PLUS: + { + // TODO: not known how the calibration values work + changed |= MOTIONPLUS_ENABLED; + bMotionPlusEnabled = true; + bInitInProgress = false; + // reenable reports // SetReportType(ReportType); - } - break; - } - break; - // XXX missing break here? -sh - case 0x34: - { - if (Internal.ExtensionType == BALANCE_BOARD) - { - wiimote_state::balance_board::calibration_info - &calib = Internal.BalanceBoard.CalibrationInfo; - - // 2nd part of the balance board calibration, - // 34kg calibration values - calib.Kg34.TopR = (short)((short)buff[0] << 8 | buff[1]); - calib.Kg34.BottomR = (short)((short)buff[2] << 8 | buff[3]); - calib.Kg34.TopL = (short)((short)buff[4] << 8 | buff[5]); - calib.Kg34.BottomL = (short)((short)buff[6] << 8 | buff[7]); - - changed |= BALANCE_CONNECTED; - // reenable reports - SetReportType(IN_BUTTONS_BALANCE_BOARD); - } - // else unknown what these are for - } - bInitInProgress = false; - } - break; - - default: - // _ASSERT(0); // shouldn't happen - break; - } + } + break; + } + case 0x34: + { + if(Internal.ExtensionType == BALANCE_BOARD) + { + wiimote_state::balance_board::calibration_info + &calib = Internal.BalanceBoard.CalibrationInfo; + + // 2nd part of the balance board calibration, + // 34kg calibration values + calib.Kg34.TopR = (short)((short)buff[0] << 8 | buff[1]); + calib.Kg34.BottomR = (short)((short)buff[2] << 8 | buff[3]); + calib.Kg34.TopL = (short)((short)buff[4] << 8 | buff[5]); + calib.Kg34.BottomL = (short)((short)buff[6] << 8 | buff[7]); + + changed |= BALANCE_CONNECTED; + // reenable reports + SetReportType(IN_BUTTONS_BALANCE_BOARD); + } + // else unknown what these are for + } + bInitInProgress = false; + } + break; + default: +// _ASSERT(0); // shouldn't happen + break; + } + return changed; -} + } // ------------------------------------------------------------------------------------ -void wiimote::ReadCalibration() -{ +void wiimote::ReadCalibration () + { TRACE(_T("Requestion wiimote calibration:")); // this appears to change the report type to 0x31 ReadAddress(REGISTER_CALIBRATION, 7); -} + } // ------------------------------------------------------------------------------------ -void wiimote::EnableIR(wiimote_state::ir::mode mode) -{ +void wiimote::EnableIR (wiimote_state::ir::mode mode) + { Internal.IR.Mode = mode; - BYTE buff[REPORT_LENGTH] = { 0 }; + BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_IR; buff[1] = 0x04 | GetRumbleBit(); WriteReport(buff); @@ -1983,22 +1987,22 @@ void wiimote::EnableIR(wiimote_state::ir::mode mode) buff[1] = 0x04 | GetRumbleBit(); WriteReport(buff); - static const BYTE ir_sens1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, - 0xc0 }; - static const BYTE ir_sens2[] = { 0x40, 0x00 }; + static const BYTE ir_sens1[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, + 0xc0}; + static const BYTE ir_sens2[] = {0x40, 0x00}; WriteData(REGISTER_IR, 0x08); Sleep(25); // wait a little to make IR more reliable (for some) WriteData(REGISTER_IR_SENSITIVITY_1, sizeof(ir_sens1), ir_sens1); WriteData(REGISTER_IR_SENSITIVITY_2, sizeof(ir_sens2), ir_sens2); WriteData(REGISTER_IR_MODE, (BYTE)mode); -} + } // ------------------------------------------------------------------------------------ -void wiimote::DisableIR() -{ +void wiimote::DisableIR () + { Internal.IR.Mode = wiimote_state::ir::OFF; - BYTE buff[REPORT_LENGTH] = { 0 }; + BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_IR; buff[1] = GetRumbleBit(); WriteReport(buff); @@ -2007,91 +2011,91 @@ void wiimote::DisableIR() buff[0] = OUT_IR2; buff[1] = GetRumbleBit(); WriteReport(buff); -} + } // ------------------------------------------------------------------------------------ -unsigned __stdcall wiimote::HIDwriteThreadfunc(void* param) -{ +unsigned __stdcall wiimote::HIDwriteThreadfunc (void* param) + { _ASSERT(param); TRACE(_T("(starting HID write thread)")); wiimote &remote = *(wiimote*)param; - while (remote.Handle != INVALID_HANDLE_VALUE) - { + while(remote.Handle != INVALID_HANDLE_VALUE) + { // try to write the oldest entry in the queue #ifdef USE_DYNAMIC_HIDQUEUE - if (!remote.HIDwriteQueue.empty()) + if(!remote.HIDwriteQueue.empty()) #else - if (!remote.HID.IsEmpty()) + if(!remote.HID.IsEmpty()) #endif - { + { #ifdef BEEP_DEBUG_WRITES - Beep(1500, 1); + Beep(1500,1); #endif EnterCriticalSection(&remote.HIDwriteQueueLock); #ifdef USE_DYNAMIC_HIDQUEUE - BYTE *buff = remote.HIDwriteQueue.front(); - _ASSERT(buff); + BYTE *buff = remote.HIDwriteQueue.front(); + _ASSERT(buff); #else - BYTE *buff = remote.HID.Queue[remote.HID.ReadIndex].Report; + BYTE *buff = remote.HID.Queue[remote.HID.ReadIndex].Report; #endif LeaveCriticalSection(&remote.HIDwriteQueueLock); - if (!_HidD_SetOutputReport(remote.Handle, buff, REPORT_LENGTH)) - { + if(!_HidD_SetOutputReport(remote.Handle, buff, REPORT_LENGTH)) + { DWORD err = GetLastError(); - if (err == ERROR_BUSY) - TRACE(_T("**** HID WRITE: BUSY ****")); - else if (err == ERROR_NOT_READY) - TRACE(_T("**** HID WRITE: NOT READY ****")); +if(err==ERROR_BUSY) +TRACE(_T("**** HID WRITE: BUSY ****")); +else if(err == ERROR_NOT_READY) +TRACE(_T("**** HID WRITE: NOT READY ****")); - if ((err != ERROR_BUSY) && // "the requested resource is in use" - (err != ERROR_NOT_READY)) // "the device is not ready" - { - if (err == ERROR_NOT_SUPPORTED) { + if((err != ERROR_BUSY) && // "the requested resource is in use" + (err != ERROR_NOT_READY)) // "the device is not ready" + { + if(err == ERROR_NOT_SUPPORTED) { WARN(_T("BT Stack doesn't suport HID writes!")); goto remove_entry; - } - else { + } + else{ DEEP_TRACE(_T("HID write failed (err %u)! - "), err); // if this worked previously, the connection was probably lost - if (remote.IsConnected()) + if(remote.IsConnected()) remote.bConnectionLost = true; - } + } //_T("aborting write thread"), err); //return 911; + } } - } - else { - remove_entry: + else{ +remove_entry: EnterCriticalSection(&remote.HIDwriteQueueLock); #ifdef USE_DYNAMIC_HIDQUEUE - remote.HIDwriteQueue.pop(); - delete[] buff; + remote.HIDwriteQueue.pop(); + delete[] buff; #else - remote.HID.ReadIndex++; - remote.HID.ReadIndex &= (hid::MAX_QUEUE_ENTRIES - 1); + remote.HID.ReadIndex++; + remote.HID.ReadIndex &= (hid::MAX_QUEUE_ENTRIES-1); #endif LeaveCriticalSection(&remote.HIDwriteQueueLock); + } } - } Sleep(1); - } + } TRACE(_T("ending HID write thread")); return 0; -} + } // ------------------------------------------------------------------------------------ -bool wiimote::WriteReport(BYTE *buff) -{ +bool wiimote::WriteReport (BYTE *buff) + { #ifdef BEEP_DEBUG_WRITES - Beep(2000, 1); + Beep(2000,1); #endif #ifdef _DEBUG -#define DEEP_TRACE_TYPE(type) case OUT_##type: DEEP_TRACE(_T("WriteReport: ")\ + #define DEEP_TRACE_TYPE(type) case OUT_##type: DEEP_TRACE(_T("WriteReport: ")\ _T(#type)); break - switch (buff[0]) - { + switch(buff[0]) + { DEEP_TRACE_TYPE(NONE); DEEP_TRACE_TYPE(LEDs); DEEP_TRACE_TYPE(TYPE); @@ -2103,13 +2107,13 @@ bool wiimote::WriteReport(BYTE *buff) DEEP_TRACE_TYPE(SPEAKER_DATA); DEEP_TRACE_TYPE(SPEAKER_MUTE); DEEP_TRACE_TYPE(IR2); - default: - TRACE(_T("WriteReport: type [%02x][%02x]"), buff[1], buff[2]); - } + default: + TRACE(_T("WriteReport: type [%02x][%02x]"), buff[1], buff[2]); + } #endif - if (bUseHIDwrite) - { + if(bUseHIDwrite) + { /* no where to release handle, I have to do it myself */ if (HIDwriteThread) { @@ -2120,231 +2124,231 @@ bool wiimote::WriteReport(BYTE *buff) } // HidD_SetOutputReport: +: works on MS Bluetooth stacks (WriteFile doesn't). // -: is synchronous, so make it async - if (!HIDwriteThread) - { + if(!HIDwriteThread) + { HIDwriteThread = (HANDLE)_beginthreadex(NULL, 0, HIDwriteThreadfunc, - this, 0, NULL); + this, 0, NULL); _ASSERT(HIDwriteThread); - if (!HIDwriteThread) { + if(!HIDwriteThread) { WARN(_T("couldn't create HID write thread!")); return false; - } + } SetThreadPriority(HIDwriteThread, WORKER_THREAD_PRIORITY); - } + } // insert the write request into the thread's queue #ifdef USE_DYNAMIC_HIDQUEUE EnterCriticalSection(&HIDwriteQueueLock); - BYTE *buff_copy = new BYTE[REPORT_LENGTH]; + BYTE *buff_copy = new BYTE[REPORT_LENGTH]; #else // allocate the HID write queue once - if (!HID.Queue && !HID.Allocate()) + if(!HID.Queue && !HID.Allocate()) return false; EnterCriticalSection(&HIDwriteQueueLock); - BYTE *buff_copy = HID.Queue[HID.WriteIndex].Report; + BYTE *buff_copy = HID.Queue[HID.WriteIndex].Report; #endif - memcpy(buff_copy, buff, REPORT_LENGTH); + memcpy(buff_copy, buff, REPORT_LENGTH); #ifdef USE_DYNAMIC_HIDQUEUE - HIDwriteQueue.push(buff_copy); + HIDwriteQueue.push(buff_copy); #else - HID.WriteIndex++; - HID.WriteIndex &= (HID.MAX_QUEUE_ENTRIES - 1); - - // check if the fixed report queue has overflown: - // if this ASSERT triggers, the HID write queue (that stores reports - // for asynchronous output by HIDwriteThreadfunc) has overflown. - // this can happen if the connection with the wiimote has been lost - // and in that case is harmless. - // - // if it happens during normal operation though you need to increase - // hid::MAX_QUEUE_ENTRIES to the next power-of-2 (see comments) - // _and_ email me the working setting so I can update the next release - _ASSERT(HID.WriteIndex != HID.ReadIndex); + HID.WriteIndex++; + HID.WriteIndex &= (HID.MAX_QUEUE_ENTRIES-1); + + // check if the fixed report queue has overflown: + // if this ASSERT triggers, the HID write queue (that stores reports + // for asynchronous output by HIDwriteThreadfunc) has overflown. + // this can happen if the connection with the wiimote has been lost + // and in that case is harmless. + // + // if it happens during normal operation though you need to increase + // hid::MAX_QUEUE_ENTRIES to the next power-of-2 (see comments) + // _and_ email me the working setting so I can update the next release + _ASSERT(HID.WriteIndex != HID.ReadIndex); #endif LeaveCriticalSection(&HIDwriteQueueLock); return true; - } + } // WriteFile: DWORD written; - if (!WriteFile(Handle, buff, REPORT_LENGTH, &written, &Overlapped)) - { + if(!WriteFile(Handle, buff, REPORT_LENGTH, &written, &Overlapped)) + { DWORD error = GetLastError(); - if (error != ERROR_IO_PENDING) { + if(error != ERROR_IO_PENDING) { TRACE(_T("WriteFile failed, err: %u!"), error); // if it worked previously, assume we lost the connection - if (IsConnected()) + if(IsConnected()) bConnectionLost = true; #ifndef USE_DYNAMIC_HIDQUEUE HID.Deallocate(); #endif return false; + } } - } return true; -} + } // ------------------------------------------------------------------------------------ // experimental speaker support: // ------------------------------------------------------------------------------------ -bool wiimote::MuteSpeaker(bool on) -{ +bool wiimote::MuteSpeaker (bool on) + { _ASSERT(IsConnected()); - if (!IsConnected()) + if(!IsConnected()) return false; - if (Internal.Speaker.bMuted == on) + if(Internal.Speaker.bMuted == on) return true; - if (on) TRACE(_T("muting speaker.")); + if(on) TRACE(_T("muting speaker." )); else TRACE(_T("unmuting speaker.")); - BYTE buff[REPORT_LENGTH] = { 0 }; + BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_SPEAKER_MUTE; - buff[1] = (on ? 0x04 : 0x00) | GetRumbleBit(); - if (!WriteReport(buff)) + buff[1] = (on? 0x04 : 0x00) | GetRumbleBit(); + if(!WriteReport(buff)) return false; Sleep(1); Internal.Speaker.bMuted = on; return true; -} + } // ------------------------------------------------------------------------------------ -bool wiimote::EnableSpeaker(bool on) -{ +bool wiimote::EnableSpeaker (bool on) + { _ASSERT(IsConnected()); - if (!IsConnected()) + if(!IsConnected()) return false; - if (Internal.Speaker.bEnabled == on) + if(Internal.Speaker.bEnabled == on) return true; - if (on) TRACE(_T("enabling speaker.")); else TRACE(_T("disabling speaker.")); + if(on) TRACE(_T("enabling speaker.")); else TRACE(_T("disabling speaker.")); - BYTE buff[REPORT_LENGTH] = { 0 }; + BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_SPEAKER_ENABLE; - buff[1] = (on ? 0x04 : 0x00) | GetRumbleBit(); - if (!WriteReport(buff)) + buff[1] = (on? 0x04 : 0x00) | GetRumbleBit(); + if(!WriteReport(buff)) return false; - if (!on) { - Internal.Speaker.Freq = FREQ_NONE; + if(!on) { + Internal.Speaker.Freq = FREQ_NONE; Internal.Speaker.Volume = 0; MuteSpeaker(true); - } + } Internal.Speaker.bEnabled = on; return true; -} + } // ------------------------------------------------------------------------------------ #ifdef TR4 // TEMP, ignore -extern int hzinc; + extern int hzinc; #endif // ------------------------------------------------------------------------------------ -unsigned __stdcall wiimote::SampleStreamThreadfunc(void* param) -{ +unsigned __stdcall wiimote::SampleStreamThreadfunc (void* param) + { TRACE(_T("(starting sample thread)")); // sends a simple square wave sample stream wiimote &remote = *(wiimote*)param; - + static BYTE squarewave_report[REPORT_LENGTH] = - { OUT_SPEAKER_DATA, 20 << 3, 0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3, - 0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3, }; - static BYTE sample_report[REPORT_LENGTH] = - { OUT_SPEAKER_DATA, 0 }; - - bool last_playing = false; - DWORD frame = 0; - DWORD frame_start = 0; - unsigned total_samples = 0; - unsigned sample_index = 0; + { OUT_SPEAKER_DATA, 20<<3, 0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3, + 0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3, }; + static BYTE sample_report [REPORT_LENGTH] = + { OUT_SPEAKER_DATA, 0 }; + + bool last_playing = false; + DWORD frame = 0; + DWORD frame_start = 0; + unsigned total_samples = 0; + unsigned sample_index = 0; wiimote_sample *current_sample = NULL; - + // TODO: duration!! - while (remote.IsConnected()) - { + while(remote.IsConnected()) + { bool playing = remote.IsPlayingAudio(); - - if (!playing) + + if(!playing) Sleep(1); - else { - const unsigned freq_hz = FreqLookup[remote.Internal.Speaker.Freq]; + else{ + const unsigned freq_hz = FreqLookup[remote.Internal.Speaker.Freq]; #ifdef TR4 - const float frame_ms = 1000 / ((freq_hz + hzinc) / 40.f); // 20bytes = 40 samples per write + const float frame_ms = 1000 / ((freq_hz+hzinc) / 40.f); // 20bytes = 40 samples per write #else - const float frame_ms = 1000 / (freq_hz / 40.f); // 20bytes = 40 samples per write + const float frame_ms = 1000 / (freq_hz / 40.f); // 20bytes = 40 samples per write #endif // has the sample just changed? bool sample_changed = (current_sample != remote.CurrentSample); - current_sample = (wiimote_sample*)remote.CurrentSample; + current_sample = (wiimote_sample*)remote.CurrentSample; - // (attempts to minimise glitches, doesn't seem to help though) - //#define FIRSTFRAME_IS_SILENT // send all-zero for first frame +// (attempts to minimise glitches, doesn't seem to help though) +//#define FIRSTFRAME_IS_SILENT // send all-zero for first frame #ifdef FIRSTFRAME_IS_SILENT bool silent_frame = false; #endif - if (!last_playing || sample_changed) { - frame = 0; - frame_start = timeGetTime(); - total_samples = current_sample ? current_sample->length : 0; - sample_index = 0; + if(!last_playing || sample_changed) { + frame = 0; + frame_start = timeGetTime(); + total_samples = current_sample? current_sample->length : 0; + sample_index = 0; #ifdef FIRSTFRAME_IS_SILENT - silent_frame = true; + silent_frame = true; #endif - } + } // are we streaming a sample? - if (current_sample) - { - if (sample_index < current_sample->length) + if(current_sample) { + if(sample_index < current_sample->length) + { // (remember that samples are 4bit, ie. 2 per byte) - unsigned samples_left = (current_sample->length - sample_index); + unsigned samples_left = (current_sample->length - sample_index); unsigned report_samples = min(samples_left, (unsigned)40); // round the entries up to the nearest multiple of 2 - unsigned report_entries = (report_samples + 1) >> 1; - - sample_report[1] = (BYTE)((report_entries << 3) | - remote.GetRumbleBit()); + unsigned report_entries = (report_samples+1) >> 1; + + sample_report[1] = (BYTE)((report_entries<<3) | + remote.GetRumbleBit()); #ifdef FIRSTFRAME_IS_SILENT - if (silent_frame) { + if(silent_frame) { // send all-zeroes - for (unsigned index = 0; index < report_entries; index++) - sample_report[2 + index] = 0; + for(unsigned index=0; index<report_entries; index++) + sample_report[2+index] = 0; remote.WriteReport(sample_report); - } + } else #endif { - for (unsigned index = 0; index < report_entries; index++) - sample_report[2 + index] = - current_sample->samples[(sample_index >> 1) + index]; + for(unsigned index=0; index<report_entries; index++) + sample_report[2+index] = + current_sample->samples[(sample_index>>1)+index]; remote.WriteReport(sample_report); sample_index += report_samples; + } } - } - else { + else{ // we reached the sample end - remote.CurrentSample = NULL; - current_sample = NULL; - remote.Internal.Speaker.Freq = FREQ_NONE; + remote.CurrentSample = NULL; + current_sample = NULL; + remote.Internal.Speaker.Freq = FREQ_NONE; remote.Internal.Speaker.Volume = 0; + } } - } // no, a squarewave - else { - squarewave_report[1] = (20 << 3) | remote.GetRumbleBit(); + else{ + squarewave_report[1] = (20<<3) | remote.GetRumbleBit(); remote.WriteReport(squarewave_report); #if 0 // verify that we're sending at the correct rate (we are) - DWORD elapsed = (timeGetTime() - frame_start); + DWORD elapsed = (timeGetTime()-frame_start); unsigned total_samples = frame * 40; - float elapsed_secs = elapsed / 1000.f; - float sent_persec = total_samples / elapsed_secs; + float elapsed_secs = elapsed / 1000.f; + float sent_persec = total_samples / elapsed_secs; #endif - } + } frame++; @@ -2352,60 +2356,64 @@ unsigned __stdcall wiimote::SampleStreamThreadfunc(void* param) // startup glitches by assuming we're filling a small sample // (or general input) buffer on the wiimote) - doesn't seem to help // if(frame > 2) { - while ((timeGetTime() - frame_start) < (unsigned)(frame*frame_ms)) - Sleep(1); - // } - } + while((timeGetTime()-frame_start) < (unsigned)(frame*frame_ms)) + Sleep(1); +// } + } last_playing = playing; - } - + } + TRACE(_T("(ending sample thread)")); return 0; -} + } // ------------------------------------------------------------------------------------ -bool wiimote::Load16bitMonoSampleWAV(const TCHAR* filepath, wiimote_sample &out) -{ - out = {}; +bool wiimote::Load16bitMonoSampleWAV (const TCHAR* filepath, wiimote_sample &out) + { // converts unsigned 16bit mono .wav audio data to the 4bit ADPCM variant // used by the Wiimote (at least the closest match so far), and returns // the data in a BYTE array (caller must delete[] it when no longer needed): + memset(&out, 0, sizeof(out)); TRACE(_T("Loading '%s'"), filepath); FILE *file; +#if (_MSC_VER >= 1400) // VC 2005+ _tfopen_s(&file, filepath, _T("rb")); +#else + file = _tfopen(filepath, _T("rb")); +#endif _ASSERT(file); - if (!file) { + if(!file) { WARN(_T("Couldn't open '%s"), filepath); return false; - } + } // parse the .wav file struct riff_chunkheader { - char ckID[4]; + char ckID [4]; DWORD ckSize; - char formType[4]; - }; + char formType [4]; + }; struct chunk_header { - char ckID[4]; + char ckID [4]; DWORD ckSize; - }; + }; union { WAVEFORMATEX x; WAVEFORMATEXTENSIBLE xe; - } wf = {}; + } wf = {0}; riff_chunkheader riff_chunkheader; chunk_header chunk_header; speaker_freq freq = FREQ_NONE; -#define READ(data) if(fread(&data, sizeof(data), 1, file) != 1) { \ + #define READ(data) if(fread(&data, sizeof(data), 1, file) != 1) { \ TRACE(_T(".wav file corrupt")); \ fclose(file); \ return false; \ } -#define READ_SIZE(ptr,size) if(fread(ptr, size, 1, file) != 1) { \ + #define READ_SIZE(ptr,size) if(fread(ptr, size, 1, file) != 1) { \ TRACE(_T(".wav file corrupt")); \ fclose(file); \ return false; \ @@ -2415,107 +2423,107 @@ bool wiimote::Load16bitMonoSampleWAV(const TCHAR* filepath, wiimote_sample &out) // valid RIFF file? _ASSERT(!strncmp(riff_chunkheader.ckID, "RIFF", 4)); - if (strncmp(riff_chunkheader.ckID, "RIFF", 4)) + if(strncmp(riff_chunkheader.ckID, "RIFF", 4)) goto unsupported; // nope // valid WAV variant? _ASSERT(!strncmp(riff_chunkheader.formType, "WAVE", 4)); - if (strncmp(riff_chunkheader.formType, "WAVE", 4)) + if(strncmp(riff_chunkheader.formType, "WAVE", 4)) goto unsupported; // nope // find the format & data chunks - while (1) - { - READ(chunk_header); - - if (!strncmp(chunk_header.ckID, "fmt ", 4)) + while(1) { + READ(chunk_header); + + if(!strncmp(chunk_header.ckID, "fmt ", 4)) + { // not a valid .wav file? - if (chunk_header.ckSize < 16 || - chunk_header.ckSize > sizeof(WAVEFORMATEXTENSIBLE)) + if(chunk_header.ckSize < 16 || + chunk_header.ckSize > sizeof(WAVEFORMATEXTENSIBLE)) goto unsupported; READ_SIZE((BYTE*)&wf.x, chunk_header.ckSize); // now we know it's true wav file bool extensible = (wf.x.wFormatTag == WAVE_FORMAT_EXTENSIBLE); - int format = extensible ? wf.xe.SubFormat.Data1 : - wf.x.wFormatTag; + int format = extensible? wf.xe.SubFormat.Data1 : + wf.x .wFormatTag; // must be uncompressed PCM (the format comparisons also work on // the 'extensible' header, even though they're named differently) - if (format != WAVE_FORMAT_PCM) { + if(format != WAVE_FORMAT_PCM) { TRACE(_T(".. not uncompressed PCM")); goto unsupported; - } + } // must be mono, 16bit - if ((wf.x.nChannels != 1) || (wf.x.wBitsPerSample != 16)) { + if((wf.x.nChannels != 1) || (wf.x.wBitsPerSample != 16)) { TRACE(_T(".. %d bit, %d channel%s"), wf.x.wBitsPerSample, - wf.x.nChannels, - (wf.x.nChannels > 1 ? _T("s") : _T(""))); + wf.x.nChannels, + (wf.x.nChannels>1? _T("s"):_T(""))); goto unsupported; - } + } // must be _near_ a supported speaker frequency range (but allow some // tolerance, especially as the speaker freq values aren't final yet): unsigned sample_freq = wf.x.nSamplesPerSec; - const unsigned epsilon = 100; // for now - - for (unsigned index = 1; index < ARRAY_ENTRIES(FreqLookup); index++) - { - if ((sample_freq + epsilon) >= FreqLookup[index] && - (sample_freq - epsilon) <= FreqLookup[index]) { + const unsigned epsilon = 100; // for now + + for(unsigned index=1; index<ARRAY_ENTRIES(FreqLookup); index++) + { + if((sample_freq+epsilon) >= FreqLookup[index] && + (sample_freq-epsilon) <= FreqLookup[index]) { freq = (speaker_freq)index; TRACE(_T(".. using speaker freq %u"), FreqLookup[index]); break; + } } - } - if (freq == FREQ_NONE) { + if(freq == FREQ_NONE) { WARN(_T("Couldn't (loosely) match .wav samplerate %u Hz to speaker"), - sample_freq); + sample_freq); goto unsupported; + } } - } - else if (!strncmp(chunk_header.ckID, "data", 4)) - { + else if(!strncmp(chunk_header.ckID, "data", 4)) + { // make sure we got a valid fmt chunk first - if (!wf.x.nBlockAlign) + if(!wf.x.nBlockAlign) goto corrupt_file; // grab the data unsigned total_samples = chunk_header.ckSize / wf.x.nBlockAlign; - if (total_samples == 0) + if(total_samples == 0) goto corrupt_file; - + short *samples = new short[total_samples]; size_t read = fread(samples, 2, total_samples, file); fclose(file); - if (read != total_samples) - { - if (read == 0) { + if(read != total_samples) + { + if(read == 0) { delete[] samples; goto corrupt_file; - } + } // got a different number, but use them anyway WARN(_T("found %s .wav audio data than expected (%u/%u samples)"), - ((read < total_samples) ? _T("less") : _T("more")), + ((read < total_samples)? _T("less") : _T("more")), read, total_samples); total_samples = read; - } + } // and convert them bool res = Convert16bitMonoSamples(samples, true, total_samples, freq, - out); + out); delete[] samples; return res; - } - else { + } + else{ // unknown chunk, skip its data DWORD chunk_bytes = (chunk_header.ckSize + 1) & ~1L; - if (fseek(file, chunk_bytes, SEEK_CUR)) + if(fseek(file, chunk_bytes, SEEK_CUR)) goto corrupt_file; + } } - } corrupt_file: WARN(_T(".wav file is corrupt")); @@ -2526,56 +2534,61 @@ unsupported: WARN(_T(".wav file format not supported (must be mono 16bit PCM)")); fclose(file); return false; -} + } // ------------------------------------------------------------------------------------ -bool wiimote::Load16BitMonoSampleRAW(const TCHAR* filepath, - bool _signed, - speaker_freq freq, - wiimote_sample &out) -{ - out = {}; +bool wiimote::Load16BitMonoSampleRAW (const TCHAR* filepath, + bool _signed, + speaker_freq freq, + wiimote_sample &out) + { // converts (.wav style) unsigned 16bit mono raw data to the 4bit ADPCM variant // used by the Wiimote, and returns the data in a BYTE array (caller must // delete[] it when no longer needed): + memset(&out, 0, sizeof(out)); // get the length of the file struct _stat file_info; - if (_tstat(filepath, &file_info)) { + if(_tstat(filepath, &file_info)) { WARN(_T("couldn't get filesize for '%s'"), filepath); return false; - } - + } + DWORD len = file_info.st_size; _ASSERT(len); - if (!len) { + if(!len) { WARN(_T("zero-size sample file '%s'"), filepath); return false; - } + } - unsigned total_samples = (len + 1) / 2; // round up just in case file is corrupt + unsigned total_samples = (len+1) / 2; // round up just in case file is corrupt // allocate a buffer to hold the samples to convert - if (!total_samples) { + short *samples = new short[total_samples]; + _ASSERT(samples); + if(!samples) { TRACE(_T("Couldn't open '%s"), filepath); return false; - } - short *samples = new short[total_samples]; + } // load them FILE *file; bool res; +#if (_MSC_VER >= 1400) // VC 2005+ _tfopen_s(&file, filepath, _T("rb")); +#else + file = _tfopen(filepath, _T("rb")); +#endif _ASSERT(file); - if (!file) { + if(!file) { TRACE(_T("Couldn't open '%s"), filepath); - goto error; - } + goto error; + } res = (fread(samples, 1, len, file) == len); fclose(file); - if (!res) { + if(!res) { WARN(_T("Couldn't load file '%s'"), filepath); goto error; - } + } // and convert them res = Convert16bitMonoSamples(samples, _signed, total_samples, freq, out); @@ -2585,100 +2598,99 @@ bool wiimote::Load16BitMonoSampleRAW(const TCHAR* filepath, error: delete[] samples; return false; -} + } // ------------------------------------------------------------------------------------ -bool wiimote::Convert16bitMonoSamples(const short* samples, - bool _signed, - DWORD length, - speaker_freq freq, - wiimote_sample &out) -{ - out = {}; - +bool wiimote::Convert16bitMonoSamples (const short* samples, + bool _signed, + DWORD length, + speaker_freq freq, + wiimote_sample &out) + { // converts 16bit mono sample data to the native 4bit format used by the Wiimote, // and returns the data in a BYTE array (caller must delete[] when no // longer needed): + memset(&out, 0, sizeof(0)); _ASSERT(samples && length); - if (!samples || !length) + if(!samples || !length) return false; // allocate the output buffer out.samples = new BYTE[length]; _ASSERT(out.samples); - if (!out.samples) + if(!out.samples) return false; // clear it memset(out.samples, 0, length); out.length = length; - out.freq = freq; + out.freq = freq; // ADPCM code, adapted from // http://www.wiindows.org/index.php/Talk:Wiimote#Input.2FOutput_Reports - static const int index_table[16] = { -1, -1, -1, -1, 2, 4, 6, 8, + static const int index_table[16] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 }; - static const int diff_table[16] = { 1, 3, 5, 7, 9, 11, 13, 15, + static const int diff_table [16] = { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, 15 }; - static const int step_scale[16] = { 230, 230, 230, 230, 307, 409, 512, 614, + static const int step_scale [16] = { 230, 230, 230, 230, 307, 409, 512, 614, 230, 230, 230, 230, 307, 409, 512, 614 }; // Encode to ADPCM, on initialization set adpcm_prev_value to 0 and adpcm_step // to 127 (these variables must be preserved across reports) int adpcm_prev_value = 0; - int adpcm_step = 127; + int adpcm_step = 127; - for (size_t i = 0; i < length; i++) - { + for(size_t i=0; i<length; i++) + { // convert to 16bit signed int value = samples[i];// (8bit) << 8);// | samples[i]; // dither it? - if (!_signed) + if(!_signed) value -= 32768; // encode: int diff = value - adpcm_prev_value; BYTE encoded_val = 0; - if (diff < 0) { + if(diff < 0) { encoded_val |= 8; diff = -diff; - } + } diff = (diff << 2) / adpcm_step; if (diff > 7) diff = 7; encoded_val |= diff; adpcm_prev_value += ((adpcm_step * diff_table[encoded_val]) / 8); - if (adpcm_prev_value > 0x7fff) - adpcm_prev_value = 0x7fff; - if (adpcm_prev_value < -0x8000) + if(adpcm_prev_value > 0x7fff) + adpcm_prev_value = 0x7fff; + if(adpcm_prev_value < -0x8000) adpcm_prev_value = -0x8000; adpcm_step = (adpcm_step * step_scale[encoded_val]) >> 8; - if (adpcm_step < 127) + if(adpcm_step < 127) adpcm_step = 127; - if (adpcm_step > 24567) + if(adpcm_step > 24567) adpcm_step = 24567; - if (i & 1) - out.samples[i >> 1] |= encoded_val; + if(i & 1) + out.samples[i>>1] |= encoded_val; else - out.samples[i >> 1] |= encoded_val << 4; - } + out.samples[i>>1] |= encoded_val << 4; + } return true; -} + } // ------------------------------------------------------------------------------------ -bool wiimote::PlaySample(const wiimote_sample &sample, BYTE volume, - speaker_freq freq_override) -{ +bool wiimote::PlaySample (const wiimote_sample &sample, BYTE volume, + speaker_freq freq_override) + { _ASSERT(IsConnected()); - if (!IsConnected()) + if(!IsConnected()) return false; - speaker_freq freq = freq_override ? freq_override : sample.freq; + speaker_freq freq = freq_override? freq_override : sample.freq; TRACE(_T("playing sample.")); EnableSpeaker(true); - MuteSpeaker(true); + MuteSpeaker (true); #if 0 // combine everything into one write - faster, seems to work? - BYTE bytes[9] = { 0x00, 0x00, 0x00, 10 + freq, vol, 0x00, 0x00, 0x01, 0x01 }; + BYTE bytes[9] = { 0x00, 0x00, 0x00, 10+freq, vol, 0x00, 0x00, 0x01, 0x01 }; WriteData(0x04a20001, sizeof(bytes), bytes); #else // Write 0x01 to register 0x04a20009 @@ -2692,45 +2704,45 @@ bool wiimote::PlaySample(const wiimote_sample &sample, BYTE volume, WriteData(0x04a20008, 0x01); #endif - Internal.Speaker.Freq = freq; + Internal.Speaker.Freq = freq; Internal.Speaker.Volume = volume; - CurrentSample = &sample; + CurrentSample = &sample; MuteSpeaker(false); return StartSampleThread(); -} + } // ------------------------------------------------------------------------------------ -bool wiimote::StartSampleThread() -{ - if (SampleThread) +bool wiimote::StartSampleThread () + { + if(SampleThread) return true; SampleThread = (HANDLE)_beginthreadex(NULL, 0, SampleStreamThreadfunc, - this, 0, NULL); + this, 0, NULL); _ASSERT(SampleThread); - if (!SampleThread) { + if(!SampleThread) { WARN(_T("couldn't create sample thread!")); - MuteSpeaker(true); - EnableSpeaker(false); + MuteSpeaker (true); + EnableSpeaker(false); return false; - } + } SetThreadPriority(SampleThread, WORKER_THREAD_PRIORITY); return true; -} + } // ------------------------------------------------------------------------------------ -bool wiimote::PlaySquareWave(speaker_freq freq, BYTE volume) -{ +bool wiimote::PlaySquareWave (speaker_freq freq, BYTE volume) + { _ASSERT(IsConnected()); - if (!IsConnected()) + if(!IsConnected()) return false; // if we're already playing a sample, stop it first - if (IsPlayingSample()) + if(IsPlayingSample()) CurrentSample = NULL; // if we're already playing a square wave at this freq and volume, return - else if (IsPlayingAudio() && (Internal.Speaker.Freq == freq) && - (Internal.Speaker.Volume == volume)) + else if(IsPlayingAudio() && (Internal.Speaker.Freq == freq) && + (Internal.Speaker.Volume == volume)) return true; TRACE(_T("playing square wave.")); @@ -2738,7 +2750,7 @@ bool wiimote::PlaySquareWave(speaker_freq freq, BYTE volume) CurrentSample = 0; EnableSpeaker(true); - MuteSpeaker(true); + MuteSpeaker (true); #if 0 // combined everything into one write - much faster, seems to work? @@ -2751,56 +2763,53 @@ bool wiimote::PlaySquareWave(speaker_freq freq, BYTE volume) WriteData(0x04a20001, 0x08); // write default sound mode (4bit ADPCM, we assume) 7-byte configuration // to registers 0xa20001-0xa20008 - BYTE bytes[7] = { '\0', '\0', '\0', BYTE(10 + freq), volume, '\0', '\0' }; + BYTE bytes[7] = { '\0', '\0', '\0', BYTE(10+freq), volume, '\0', '\0' }; WriteData(0x04a20001, sizeof(bytes), bytes); // write 0x01 to register 0xa20008 WriteData(0x04a20008, 0x01); #endif - Internal.Speaker.Freq = freq; + Internal.Speaker.Freq = freq; Internal.Speaker.Volume = volume; MuteSpeaker(false); return StartSampleThread(); -} + } // ------------------------------------------------------------------------------------ -void wiimote::RecordState(state_history &events_out, - unsigned max_time_ms, - state_change_flags change_trigger) -{ +void wiimote::RecordState (state_history &events_out, + unsigned max_time_ms, + state_change_flags change_trigger) + { // user being naughty? - if (Recording.bEnabled) + if(Recording.bEnabled) StopRecording(); // clear the list - if (!events_out.empty()) + if(!events_out.empty()) events_out.clear(); // start recording Recording.StateHistory = &events_out; - Recording.StartTimeMS = timeGetTime(); - Recording.EndTimeMS = Recording.StartTimeMS + max_time_ms; + Recording.StartTimeMS = timeGetTime(); + Recording.EndTimeMS = Recording.StartTimeMS + max_time_ms; Recording.TriggerFlags = change_trigger; // as this call happens outside the read/parse thread, set the boolean // which will enable reocrding last, so that all params are in place. // TODO: * stricly speaking this only works on VC2005+ or better, as it // automatically places a memory barrier on volatile variables - earlier/ // other compilers may reorder the assignments!). * - Recording.bEnabled = true; -} + Recording.bEnabled = true; + } // ------------------------------------------------------------------------------------ -void wiimote::StopRecording() -{ - if (!Recording.bEnabled) +void wiimote::StopRecording () + { + if(!Recording.bEnabled) return; Recording.bEnabled = false; // make sure the read/parse thread has time to notice the change (else it might // still write one more state to the list) Sleep(10); // too much? -} + } // ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------ - -#include "warns-end.hpp" - diff --git a/tracker-wii/wiiyourself/wiimote.h b/tracker-wii/wiiyourself/wiimote.h index 73212e05..3588b7c7 100644 --- a/tracker-wii/wiiyourself/wiimote.h +++ b/tracker-wii/wiiyourself/wiimote.h @@ -10,18 +10,15 @@ #pragma once -#undef NDEBUG - -#include "warns-begin.hpp" - -#undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <tchar.h> // auto Unicode/Ansi support #include <queue> // for HID write method #include <list> // for state recording -typedef unsigned __int64 QWORD; +#ifndef QWORD + typedef unsigned __int64 QWORD; +#endif #ifdef _MSC_VER // VC-specific: _DEBUG build only _ASSERT() sanity checks # include <crtdbg.h> @@ -184,7 +181,7 @@ class wiimote : public wiimote_state // get the frequency from speaker_freq enum static const unsigned FreqLookup [TOTAL_FREQUENCIES]; - static unsigned GetFreqLookup(unsigned index) + static const unsigned GetFreqLookup (unsigned index) { _ASSERT(index < TOTAL_FREQUENCIES); if(index >= TOTAL_FREQUENCIES) @@ -474,7 +471,7 @@ volatile int MotionPlusDetectCount; // waiting for the result volatile DWORD AsyncRumbleTimeout; // orientation estimation unsigned WiimoteNearGUpdates; - //unsigned NunchukNearGUpdates; + unsigned NunchukNearGUpdates; // audio HANDLE SampleThread; const wiimote_sample* volatile CurrentSample; // otherwise playing square wave @@ -489,5 +486,3 @@ volatile int MotionPlusDetectCount; // waiting for the result unsigned ExtTriggerFlags;// extension changes " } Recording; }; - -#include "warns-end.hpp" diff --git a/tracker-wii/wiiyourself/wiimote_common.h b/tracker-wii/wiiyourself/wiimote_common.h index 9934d6ec..c0fd01e1 100644 --- a/tracker-wii/wiiyourself/wiimote_common.h +++ b/tracker-wii/wiiyourself/wiimote_common.h @@ -1,5 +1,3 @@ -#pragma once - // _______________________________________________________________________________ // // - WiiYourself! - native C++ Wiimote library v1.15 RC |