1 |
// _______________________________________________________________________________
|
2 |
//
|
3 |
// - WiiYourself! - native C++ Wiimote library v1.15
|
4 |
// (c) gl.tter 2007-10 - http://gl.tter.org
|
5 |
//
|
6 |
// see License.txt for conditions of use. see History.txt for change log.
|
7 |
// _______________________________________________________________________________
|
8 |
//
|
9 |
// wiimote.h (tab = 4 spaces)
|
10 |
|
11 |
#ifdef _MSC_VER // VC
|
12 |
# pragma once
|
13 |
#endif
|
14 |
|
15 |
#ifndef _WIIMOTE_H
|
16 |
# define _WIIMOTE_H
|
17 |
|
18 |
#define WIN32_LEAN_AND_MEAN
|
19 |
#include <windows.h>
|
20 |
#include <tchar.h> // auto Unicode/Ansi support
|
21 |
#include <queue> // for HID write method
|
22 |
#include <list> // for state recording
|
23 |
|
24 |
#ifndef QWORD
|
25 |
typedef unsigned __int64 QWORD;
|
26 |
#endif
|
27 |
|
28 |
#ifdef _MSC_VER // VC-specific: _DEBUG build only _ASSERT() sanity checks
|
29 |
# include <crtdbg.h>
|
30 |
#elif defined(__MINGW32__) // define NDEBUG to disable assert
|
31 |
# include <assert.h>
|
32 |
# define _ASSERT assert
|
33 |
#else
|
34 |
# define _ASSERT(x) ((void)0) // (add your compiler's implementation if you like)
|
35 |
#endif
|
36 |
|
37 |
#ifdef SWIGWRAPPER // Python Wrapper
|
38 |
#include "Python/wiimote_state.i"
|
39 |
#else
|
40 |
#include "wiimote_state.h"
|
41 |
#endif
|
42 |
|
43 |
// configs:
|
44 |
//#define USE_DYNAMIC_HIDQUEUE // deprecated
|
45 |
|
46 |
// we request periodic status report updates to refresh the battery level
|
47 |
// and to detect connection loss (through failed writes)
|
48 |
#define REQUEST_STATUS_EVERY_MS 1000
|
49 |
#define DETECT_MPLUS_EVERY_MS 1000
|
50 |
#define DETECT_MPLUS_COUNT 1 // # of tries in quick succession
|
51 |
|
52 |
// all threads (read/parse, audio streaming, async rumble...) use this priority
|
53 |
#define WORKER_THREAD_PRIORITY THREAD_PRIORITY_HIGHEST
|
54 |
|
55 |
// internals
|
56 |
#define WIIYOURSELF_VERSION_MAJOR 1
|
57 |
#define WIIYOURSELF_VERSION_MINOR1 1
|
58 |
#define WIIYOURSELF_VERSION_MINOR2 5
|
59 |
//#define WIIYOURSELF_VERSION_BETA // not defined for non-beta releases
|
60 |
#define WIIYOURSELF_VERSION_STR _T("1.15")
|
61 |
|
62 |
// array sizes
|
63 |
#define TOTAL_BUTTON_BITS 16 // Number of bits for (Classic)ButtonNameFromBit[]
|
64 |
#define TOTAL_FREQUENCIES 10 // Number of frequencies (see speaker_freq[])
|
65 |
|
66 |
// clarity
|
67 |
typedef HANDLE EVENT;
|
68 |
|
69 |
|
70 |
// state data changes can be signalled to the app via a callback. Set the wiimote
|
71 |
// object's 'ChangedCallback' any time to enable them, or alternatively inherit
|
72 |
// from the wiimote object and override the ChangedNotifier() virtual method.
|
73 |
|
74 |
// of flags indicating which state has changed since the last callback.
|
75 |
typedef void (*state_changed_callback) (class wiimote &owner,
|
76 |
state_change_flags changed,
|
77 |
const wiimote_state &new_state);
|
78 |
|
79 |
// internals
|
80 |
typedef BOOLEAN (__stdcall *hidwrite_ptr)(HANDLE HidDeviceObject,
|
81 |
PVOID ReportBuffer,
|
82 |
ULONG ReportBufferLength);
|
83 |
|
84 |
// (global due to Python wrapper)
|
85 |
struct wiimote_state_event {
|
86 |
DWORD time_ms; // system timestamp in milliseconds
|
87 |
wiimote_state state;
|
88 |
};
|
89 |
|
90 |
// wiimote class - connects and manages a wiimote and its optional extensions
|
91 |
// (Nunchuk/Classic Controller), and exposes their state
|
92 |
class wiimote : public wiimote_state
|
93 |
{
|
94 |
public:
|
95 |
wiimote ();
|
96 |
virtual ~wiimote ();
|
97 |
|
98 |
public:
|
99 |
// these can be used to identify Connect()ed wiimote objects (if both
|
100 |
// are unconnected they will pass the compare as their handles are invalid)
|
101 |
inline bool operator == (const wiimote& remote)
|
102 |
{ return Handle == remote.Handle; }
|
103 |
inline bool operator != (const wiimote& remote)
|
104 |
{ return Handle != remote.Handle; }
|
105 |
|
106 |
// wiimote data input mode (use with SetReportType())
|
107 |
// (only enable what you need to save battery power)
|
108 |
enum input_report
|
109 |
{
|
110 |
// combinations if buttons/acceleration/IR/Extension data
|
111 |
IN_BUTTONS = 0x30,
|
112 |
IN_BUTTONS_ACCEL = 0x31,
|
113 |
IN_BUTTONS_ACCEL_IR = 0x33, // reports IR EXTENDED data (dot sizes)
|
114 |
IN_BUTTONS_ACCEL_EXT = 0x35,
|
115 |
IN_BUTTONS_ACCEL_IR_EXT = 0x37, // reports IR BASIC data (no dot sizes)
|
116 |
IN_BUTTONS_BALANCE_BOARD = 0x32, // must use this for the balance board
|
117 |
};
|
118 |
// string versions
|
119 |
static const TCHAR* ReportTypeName [];
|
120 |
|
121 |
|
122 |
public: // convenience accessors:
|
123 |
inline bool IsConnected () const { return bStatusReceived; }
|
124 |
// if IsConnected() unexpectedly returns false, connection was probably lost
|
125 |
inline bool ConnectionLost () const { return bConnectionLost; }
|
126 |
inline bool IsBalanceBoard () const { return (Internal.bExtension &&
|
127 |
(Internal.ExtensionType==wiimote_state::BALANCE_BOARD)); }
|
128 |
inline bool NunchukConnected () const { return (Internal.bExtension &&
|
129 |
(Internal.ExtensionType==wiimote_state::NUNCHUK)); }
|
130 |
inline bool ClassicConnected () const { return (Internal.bExtension &&
|
131 |
(Internal.ExtensionType==wiimote_state::CLASSIC)); }
|
132 |
inline bool MotionPlusConnected () const { return bMotionPlusDetected; }
|
133 |
inline bool MotionPlusEnabled () const { return bMotionPlusEnabled; }
|
134 |
inline bool MotionPlusHasExtension() const { return bMotionPlusExtension; }
|
135 |
inline bool IsPlayingAudio () const { return (Internal.Speaker.Freq &&
|
136 |
Internal.Speaker.Volume); }
|
137 |
inline bool IsPlayingSample () const { return IsPlayingAudio() &&
|
138 |
(CurrentSample != NULL); }
|
139 |
inline bool IsUsingHIDwrites () const { return bUseHIDwrite; }
|
140 |
inline bool IsRecordingState () const { return Recording.bEnabled; }
|
141 |
|
142 |
static inline unsigned TotalConnected() { return _TotalConnected; }
|
143 |
|
144 |
|
145 |
public: // data
|
146 |
QWORD UniqueID; // constructed from device-specific calibration info.
|
147 |
// Note this is not guaranteed to be truly unique
|
148 |
// as several devices may contain the same calibration
|
149 |
// vluaes - but unique amongst a small number of
|
150 |
// devices.
|
151 |
#ifdef ID2_FROM_DEVICEPATH
|
152 |
QWORD UniqueID2; // (low-reliabilty, left for reference)
|
153 |
// constructed from the 'device path' string (as
|
154 |
// reported by the OS/stack). This is hopefully
|
155 |
// unique as long as the devices remain installed
|
156 |
// (or at least paired).
|
157 |
#endif
|
158 |
// optional callbacks - set these to your own fuctions (if required)
|
159 |
state_changed_callback ChangedCallback;
|
160 |
// you can avoid unnecessary callback overhead by specifying a mask
|
161 |
// of which state changes should trigger them (default is any)
|
162 |
state_change_flags CallbackTriggerFlags;
|
163 |
// alternatively, inherit from this class and override this virtual function:
|
164 |
virtual void ChangedNotifier (state_change_flags changed,
|
165 |
const wiimote_state &new_state) {};
|
166 |
|
167 |
// get the button name from its bit index (some bits are unused)
|
168 |
static const TCHAR* ButtonNameFromBit [TOTAL_BUTTON_BITS];
|
169 |
static const TCHAR* GetButtonNameFromBit (unsigned index)
|
170 |
{
|
171 |
_ASSERT(index < TOTAL_BUTTON_BITS);
|
172 |
if(index >= TOTAL_BUTTON_BITS)
|
173 |
return _T("[invalid index]");
|
174 |
return ButtonNameFromBit[index];
|
175 |
}
|
176 |
|
177 |
// same for the Classic Controller
|
178 |
static const TCHAR* ClassicButtonNameFromBit [TOTAL_BUTTON_BITS];
|
179 |
static const TCHAR* GetClassicButtonNameFromBit (unsigned index)
|
180 |
{
|
181 |
_ASSERT(index < TOTAL_BUTTON_BITS);
|
182 |
if(index >= TOTAL_BUTTON_BITS)
|
183 |
return _T("[invalid index]");
|
184 |
return ClassicButtonNameFromBit[index];
|
185 |
}
|
186 |
|
187 |
// get the frequency from speaker_freq enum
|
188 |
static const unsigned FreqLookup [TOTAL_FREQUENCIES];
|
189 |
static const unsigned GetFreqLookup (unsigned index)
|
190 |
{
|
191 |
_ASSERT(index < TOTAL_FREQUENCIES);
|
192 |
if(index >= TOTAL_FREQUENCIES)
|
193 |
return 0;
|
194 |
return FreqLookup[index];
|
195 |
}
|
196 |
|
197 |
public: // methods
|
198 |
// call Connect() first - returns true if wiimote was found & enabled
|
199 |
// - 'wiimote_index' specifies which *installed* (not necessarily
|
200 |
// *connected*) wiimote should be tried (1 = first, 2 = 2nd etc).
|
201 |
// if you just want the first *available* wiimote that isn't already
|
202 |
// in use, pass in FIRST_AVAILABLE (default).
|
203 |
// - 'force_hidwrites' forces HID output method (it's auto-selected
|
204 |
// when needed and less efficient, so only force for testing).
|
205 |
static const unsigned FIRST_AVAILABLE = 0xffffffff;
|
206 |
bool Connect (unsigned wiimote_index = FIRST_AVAILABLE,
|
207 |
bool force_hidwrites = false);
|
208 |
// disconnect from the controller and stop reading data from it
|
209 |
void Disconnect ();
|
210 |
// set wiimote reporting mode (call after Connnect())
|
211 |
// continous = true forces the wiimote to send constant updates, even when
|
212 |
// nothing has changed.
|
213 |
// = false only sends data when something has changed (note that
|
214 |
// acceleration data will cause frequent updates anyway as it
|
215 |
// jitters even when the wiimote is stationary)
|
216 |
void SetReportType (input_report type, bool continuous = false);
|
217 |
|
218 |
// toggle the MotionPlus extension. Call MotionPlusDetected() first to
|
219 |
// see if it's attached. Unlike normal extensions, the MotionPlus does
|
220 |
// not report itself as one until enabled. Once done, it then replaces
|
221 |
// any standard extension attached to it, so be sure to disable it
|
222 |
// if you want to read those (it's not currently known of both can
|
223 |
// be read simultaneously).
|
224 |
bool EnableMotionPlus ();
|
225 |
bool DisableMotionPlus ();
|
226 |
|
227 |
// this is used to remove unwanted 'at rest' offsets, currently only from
|
228 |
// the Balance Board. make sure there is no weight on the board before
|
229 |
// calling this. it reads the current sensor values and then removes them
|
230 |
// offsets from all subsequent KG and LB state values (the 'raw' values
|
231 |
// are never modified).
|
232 |
void CalibrateAtRest ();
|
233 |
// NOTE: the library automatically calls this when the first weight values
|
234 |
// come in after Connect()ion, but if the device wasn't at rest at
|
235 |
// the time the app can call it again later.
|
236 |
|
237 |
// to read the state via polling (reading the public state data direct from
|
238 |
// the wiimote object) you must call RefreshState() at the top of every pass.
|
239 |
// returns a combination of flags to indicate which state (if any) has
|
240 |
// changed since the last call.
|
241 |
state_change_flags RefreshState ();
|
242 |
|
243 |
// reset the wiimote (changes report type to non-continuous buttons-only,
|
244 |
// clears LEDs & rumble, mutes & disables speaker)
|
245 |
void Reset ();
|
246 |
// set/clear the wiimote LEDs
|
247 |
void SetLEDs (BYTE led_bits); // bits 0-3 are valid
|
248 |
// set/clear rumble
|
249 |
void SetRumble (bool on);
|
250 |
// alternative - rumble for a fixed amount of time (asynchronous)
|
251 |
void RumbleForAsync (unsigned milliseconds);
|
252 |
|
253 |
// *experimental* speaker support:
|
254 |
bool MuteSpeaker (bool on);
|
255 |
bool EnableSpeaker (bool on);
|
256 |
bool PlaySquareWave (speaker_freq freq, BYTE volume = 0x40);
|
257 |
// note: PlaySample currently streams from the passed-in wiimote_sample -
|
258 |
// don't delete it until playback has stopped.
|
259 |
bool PlaySample (const wiimote_sample &sample,
|
260 |
BYTE volume = 0x40,
|
261 |
speaker_freq freq_override = FREQ_NONE);
|
262 |
|
263 |
// 16bit mono sample loading/conversion to native format:
|
264 |
// .wav sample
|
265 |
static bool Load16bitMonoSampleWAV (const TCHAR* filepath,
|
266 |
wiimote_sample &out);
|
267 |
// raw 16bit mono audio data (can be signed or unsigned)
|
268 |
static bool Load16BitMonoSampleRAW (const TCHAR* filepath,
|
269 |
bool _signed,
|
270 |
speaker_freq freq,
|
271 |
wiimote_sample &out);
|
272 |
// converts a 16bit mono sample array to a wiimote_sample
|
273 |
static bool Convert16bitMonoSamples (const short* samples,
|
274 |
bool _signed,
|
275 |
DWORD length,
|
276 |
speaker_freq freq,
|
277 |
wiimote_sample &out);
|
278 |
|
279 |
// state recording - records state snapshots to a 'state_history' supplied
|
280 |
// by the caller. states are timestamped and only added
|
281 |
// to the list when the specified state changes.
|
282 |
#ifndef SWIG // !Python Wrapper
|
283 |
typedef wiimote_state_event state_event;
|
284 |
#endif
|
285 |
typedef std::list<state_event> state_history;
|
286 |
static const unsigned UNTIL_STOP = 0xffffffff;
|
287 |
// - pass in a 'state_history' list, and don't destroy/change it until
|
288 |
// recording is stopped. note the list will be cleared first.
|
289 |
// - you can request a specific duration (and use IsRecordingState() to detect
|
290 |
// the end), or UNTIL_STOP. StopRecording() can be called either way.
|
291 |
// - you can use 'change trigger' to specify specific state changes that will
|
292 |
// trigger an insert into the history (others are then ignored).
|
293 |
void RecordState (state_history &events_out,
|
294 |
unsigned max_time_ms = UNTIL_STOP,
|
295 |
state_change_flags change_trigger = CHANGED_ALL);
|
296 |
void StopRecording ();
|
297 |
|
298 |
|
299 |
private: // methods
|
300 |
// start reading asynchronously from the controller
|
301 |
bool BeginAsyncRead ();
|
302 |
// request status update (battery level, extension status etc)
|
303 |
void RequestStatusReport ();
|
304 |
// read address or register from Wiimote asynchronously (the result is
|
305 |
// parsed internally whenever it arrives)
|
306 |
bool ReadAddress (int address, short size);
|
307 |
// write a single BYTE to a wiimote address or register
|
308 |
inline void WriteData (int address, BYTE data) { WriteData(address, 1, &data); }
|
309 |
// write a BYTE array to a wiimote address or register
|
310 |
void WriteData (int address, BYTE size, const BYTE* buff);
|
311 |
// callback when data is ready to be processed
|
312 |
void OnReadData (DWORD bytes_read);
|
313 |
// parse individual reports by type
|
314 |
int ParseInput (BYTE* buff);
|
315 |
// detects if MotionPlus is attached (it doesn't report as a normal
|
316 |
// extesnion until it is enabled)
|
317 |
void DetectMotionPlusExtensionAsync ();
|
318 |
// initializes an extension when plugged in.
|
319 |
void InitializeExtension ();
|
320 |
// parses a status report
|
321 |
int ParseStatus (BYTE* buff);
|
322 |
// parses the buttons
|
323 |
int ParseButtons (BYTE* buff);
|
324 |
// parses accelerometer data
|
325 |
int ParseAccel (BYTE* buff);
|
326 |
bool EstimateOrientationFrom(wiimote_state::acceleration &accel);
|
327 |
void ApplyJoystickDeadZones (wiimote_state::joystick &joy);
|
328 |
// parses IR data from report
|
329 |
int ParseIR (BYTE* buff);
|
330 |
// parses data from an extension.
|
331 |
int ParseExtension (BYTE* buff, unsigned offset);
|
332 |
// parses data returned from a read report
|
333 |
int ParseReadAddress (BYTE* buff);
|
334 |
// reads calibration information stored on Wiimote
|
335 |
void ReadCalibration ();
|
336 |
float GetBalanceValue(short sensor, short min, short mid, short max);
|
337 |
// turns on the IR sensor (the mode must match the reporting mode caps)
|
338 |
void EnableIR (wiimote_state::ir::mode mode);
|
339 |
// disables the IR sensor
|
340 |
void DisableIR ();
|
341 |
// writes a report to the Wiimote (NULL = use 'WriteBuff')
|
342 |
bool WriteReport (BYTE* buff);
|
343 |
bool StartSampleThread ();
|
344 |
// returns the rumble BYTE that needs to be sent with reports.
|
345 |
inline BYTE GetRumbleBit () const { return Internal.bRumble? 0x01 : 0x00; }
|
346 |
|
347 |
// static thread funcs:
|
348 |
static unsigned __stdcall ReadParseThreadfunc (void* param);
|
349 |
static unsigned __stdcall AsyncRumbleThreadfunc (void* param);
|
350 |
static unsigned __stdcall SampleStreamThreadfunc(void* param);
|
351 |
static unsigned __stdcall HIDwriteThreadfunc (void* param);
|
352 |
|
353 |
private: // data
|
354 |
// wiimote output comands
|
355 |
enum output_report
|
356 |
{
|
357 |
OUT_NONE = 0x00,
|
358 |
OUT_LEDs = 0x11,
|
359 |
OUT_TYPE = 0x12,
|
360 |
OUT_IR = 0x13,
|
361 |
OUT_SPEAKER_ENABLE = 0x14,
|
362 |
OUT_STATUS = 0x15,
|
363 |
OUT_WRITEMEMORY = 0x16,
|
364 |
OUT_READMEMORY = 0x17,
|
365 |
OUT_SPEAKER_DATA = 0x18,
|
366 |
OUT_SPEAKER_MUTE = 0x19,
|
367 |
OUT_IR2 = 0x1a,
|
368 |
};
|
369 |
// input reports used only internally:
|
370 |
static const int IN_STATUS = 0x20;
|
371 |
static const int IN_READADDRESS = 0x21;
|
372 |
// wiimote device IDs:
|
373 |
static const int VID = 0x057e; // 'Nintendo'
|
374 |
static const int PID = 0x0306; // 'Wiimote'
|
375 |
// we could find this out the hard way using HID, but it's 22
|
376 |
static const int REPORT_LENGTH = 22;
|
377 |
// wiimote registers
|
378 |
static const int REGISTER_CALIBRATION = 0x0016;
|
379 |
static const int REGISTER_IR = 0x4b00030;
|
380 |
static const int REGISTER_IR_SENSITIVITY_1 = 0x4b00000;
|
381 |
static const int REGISTER_IR_SENSITIVITY_2 = 0x4b0001a;
|
382 |
static const int REGISTER_IR_MODE = 0x4b00033;
|
383 |
static const int REGISTER_EXTENSION_INIT1 = 0x4a400f0;
|
384 |
static const int REGISTER_EXTENSION_INIT2 = 0x4a400fb;
|
385 |
static const int REGISTER_EXTENSION_TYPE = 0x4a400fa;
|
386 |
static const int REGISTER_EXTENSION_CALIBRATION = 0x4a40020;
|
387 |
static const int REGISTER_BALANCE_CALIBRATION = 0x4a40024;
|
388 |
static const int REGISTER_MOTIONPLUS_DETECT = 0x4a600fa;
|
389 |
static const int REGISTER_MOTIONPLUS_INIT = 0x4a600f0;
|
390 |
static const int REGISTER_MOTIONPLUS_ENABLE = 0x4a600fe;
|
391 |
|
392 |
HANDLE Handle; // read/write device handle
|
393 |
OVERLAPPED Overlapped; // for async Read/WriteFile() IO
|
394 |
HANDLE ReadParseThread; // waits for overlapped reads & parses result
|
395 |
EVENT DataRead; // signals overlapped read complete
|
396 |
bool bUseHIDwrite; // alternative write method (less efficient
|
397 |
// but required for some BT stacks (eg. MS')
|
398 |
// HidD_SetOutputReport is only supported from XP onwards, so detect &
|
399 |
// load it dynamically:
|
400 |
static HMODULE HidDLL;
|
401 |
static hidwrite_ptr _HidD_SetOutputReport;
|
402 |
|
403 |
volatile bool bStatusReceived; // for output method detection
|
404 |
volatile bool bConnectInProgress; // don't handle extensions until complete
|
405 |
volatile bool bInitInProgress; // stop regular requests until complete
|
406 |
volatile bool bEnablingMotionPlus; // for special init codepath
|
407 |
volatile bool bConnectionLost; // auto-Disconnect()s if set
|
408 |
volatile int MotionPlusDetectCount; // waiting for the result
|
409 |
volatile bool bMotionPlusDetected;
|
410 |
volatile bool bMotionPlusEnabled;
|
411 |
volatile bool bMotionPlusExtension;// detected one plugged into MotionPlus
|
412 |
volatile bool bCalibrateAtRest; // as soon as the first sensor values // come in after a Connect() call.
|
413 |
static unsigned _TotalCreated;
|
414 |
static unsigned _TotalConnected;
|
415 |
input_report ReportType; // type of data the wiimote delivers
|
416 |
// read buffer
|
417 |
BYTE ReadBuff [REPORT_LENGTH];
|
418 |
// for polling: state is updated on a thread internally, and made only
|
419 |
// made public via RefreshState()
|
420 |
CRITICAL_SECTION StateLock;
|
421 |
wiimote_state Internal;
|
422 |
state_change_flags InternalChanged; // state changes since last RefreshState()
|
423 |
// periodic status report requests (for battery level and connection loss
|
424 |
// detection)
|
425 |
DWORD NextStatusTime;
|
426 |
DWORD NextMPlusDetectTime;// gap between motion plus detections
|
427 |
DWORD MPlusDetectCount; // # of detection tries in quick succesion
|
428 |
// async Hidd_WriteReport() thread
|
429 |
HANDLE HIDwriteThread;
|
430 |
#ifdef USE_DYNAMIC_HIDQUEUE
|
431 |
std::queue<BYTE*> HIDwriteQueue;
|
432 |
#else
|
433 |
// fixed-size queue (to eliminate glitches caused by frequent dynamic memory
|
434 |
// allocations)
|
435 |
struct hid
|
436 |
{
|
437 |
hid () : Queue(NULL), ReadIndex(0), WriteIndex(0) {}
|
438 |
|
439 |
// Increase the static queue size if you get ASSERTs signalling an
|
440 |
// overflow (too many reports queued up before being sent by the write
|
441 |
// thread). These asserts are harmless though if caused as a result of
|
442 |
// loosing the wiimote connection (eg. battery runs out, or wiimote is
|
443 |
// unpaired by holding the power button).
|
444 |
// Note: MAX_QUEUE_ENTRIES _must_ be a power-of-2, as it
|
445 |
// uses index wraparound optimisations.
|
446 |
static const unsigned MAX_QUEUE_ENTRIES = 1<<7;
|
447 |
|
448 |
inline bool IsEmpty() const { return (ReadIndex == WriteIndex); }
|
449 |
|
450 |
bool Allocate () { // allocate memory (only when needed)
|
451 |
_ASSERT(!Queue); if(Queue) return true;
|
452 |
ReadIndex = WriteIndex = 0;
|
453 |
Queue = new queue_entry[MAX_QUEUE_ENTRIES];
|
454 |
_ASSERT(Queue); return (Queue != NULL);
|
455 |
}
|
456 |
void Deallocate () {
|
457 |
if(!Queue) return;
|
458 |
delete[] Queue; Queue = NULL;
|
459 |
ReadIndex = WriteIndex = 0;
|
460 |
}
|
461 |
|
462 |
struct queue_entry
|
463 |
{
|
464 |
queue_entry() { memset(Report, 0, sizeof(Report)); }
|
465 |
|
466 |
BYTE Report [REPORT_LENGTH];
|
467 |
} *Queue;
|
468 |
|
469 |
unsigned ReadIndex, WriteIndex;
|
470 |
} HID;
|
471 |
#endif
|
472 |
CRITICAL_SECTION HIDwriteQueueLock; // queue must be locked before being modified
|
473 |
|
474 |
// async rumble
|
475 |
HANDLE AsyncRumbleThread; // automatically disables rumble if requested
|
476 |
volatile DWORD AsyncRumbleTimeout;
|
477 |
// orientation estimation
|
478 |
unsigned WiimoteNearGUpdates;
|
479 |
unsigned NunchukNearGUpdates;
|
480 |
// audio
|
481 |
HANDLE SampleThread;
|
482 |
const wiimote_sample* volatile CurrentSample; // otherwise playing square wave
|
483 |
// state recording
|
484 |
struct recording
|
485 |
{
|
486 |
volatile bool bEnabled;
|
487 |
state_history *StateHistory;
|
488 |
volatile DWORD StartTimeMS;
|
489 |
volatile DWORD EndTimeMS; // can be UNTIL_STOP
|
490 |
unsigned TriggerFlags; // wiimote changes trigger a state event
|
491 |
unsigned ExtTriggerFlags;// extension changes "
|
492 |
} Recording;
|
493 |
};
|
494 |
|
495 |
#endif // _WIIMOTE_H |