Wiimote: Partial work on movement recording (not working yet)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2021 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson
2009-01-28 16:09:08 +00:00
parent 7bc798b7f1
commit 946fb12752
13 changed files with 903 additions and 325 deletions
+201 -176
View File
@@ -16,6 +16,9 @@
// http://code.google.com/p/dolphin-emu/
// see IniFile.h
//////////////////////////////////////////////////////////////////////////////////////
// Include
// ------------
#include <stdlib.h>
#include <stdio.h>
@@ -27,15 +30,24 @@
#include "StringUtil.h"
#include "IniFile.h"
///////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// Class
// ------------
IniFile::IniFile()
{}
IniFile::~IniFile()
{}
///////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// Section functions used locally only
// ------------
Section::Section()
: lines(), name(""), comment("") {}
@@ -79,6 +91,7 @@ Section* IniFile::GetOrCreateSection(const char* sectionName)
return(section);
}
///////////////////////////////
bool IniFile::DeleteSection(const char* sectionName)
@@ -158,7 +171,194 @@ std::string* IniFile::GetLine(Section* section, const char* key, std::string* va
return 0;
}
void IniFile::SetLines(const char* sectionName, const std::vector<std::string> &lines)
{
Section* section = GetOrCreateSection(sectionName);
section->lines.clear();
for (std::vector<std::string>::const_iterator iter = lines.begin(); iter != lines.end(); ++iter)
{
section->lines.push_back(*iter);
}
}
bool IniFile::DeleteKey(const char* sectionName, const char* key)
{
Section* section = GetSection(sectionName);
if (!section)
{
return false;
}
std::string* line = GetLine(section, key, 0, 0);
for (std::vector<std::string>::iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
{
if (line == &(*liter))
{
section->lines.erase(liter);
return true;
}
}
return false; //shouldn't happen
}
bool IniFile::GetKeys(const char* sectionName, std::vector<std::string>& keys) const
{
const Section* section = GetSection(sectionName);
if (!section)
{
return false;
}
keys.clear();
for (std::vector<std::string>::const_iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
{
std::string key;
ParseLine(*liter, &key, 0, 0);
keys.push_back(key);
}
return true;
}
bool IniFile::GetLines(const char* sectionName, std::vector<std::string>& lines) const
{
const Section* section = GetSection(sectionName);
if (!section)
return false;
lines.clear();
for (std::vector<std::string>::const_iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter)
{
std::string line = StripSpaces(*iter);
int commentPos = (int)line.find('#');
if (commentPos == 0)
{
continue;
}
if (commentPos != (int)std::string::npos)
{
line = StripSpaces(line.substr(0, commentPos));
}
lines.push_back(line);
}
return true;
}
void IniFile::SortSections()
{
std::sort(sections.begin(), sections.end());
}
//////////////////////////////////////////////////////////////////////////////////////
// Load and save file
// ------------
bool IniFile::Load(const char* filename)
{
// Maximum number of letters in a line
static const int MAX_BYTES = 1024*10;
sections.clear();
sections.push_back(Section(""));
//first section consists of the comments before the first real section
// Open file
std::ifstream in;
in.open(filename, std::ios::in);
if (in.fail())
{
return false;
}
while (!in.eof())
{
char templine[MAX_BYTES];
in.getline(templine, MAX_BYTES);
std::string line = templine;
if (in.eof())
{
break;
}
if (line.size() > 0)
{
if (line[0] == '[')
{
size_t endpos = line.find("]");
if (endpos != std::string::npos)
{
// New section!
std::string sub = line.substr(1, endpos - 1);
sections.push_back(Section(sub));
if (endpos + 1 < line.size())
{
sections[sections.size() - 1].comment = line.substr(endpos + 1);
}
}
}
else
{
sections[sections.size() - 1].lines.push_back(line);
}
}
}
in.close();
return true;
}
bool IniFile::Save(const char* filename)
{
std::ofstream out;
out.open(filename, std::ios::out);
if (out.fail())
{
return false;
}
for (std::vector<Section>::const_iterator iter = sections.begin(); iter != sections.end(); ++iter)
{
const Section& section = *iter;
if (section.name != "")
{
out << "[" << section.name << "]" << section.comment << std::endl;
}
for (std::vector<std::string>::const_iterator liter = section.lines.begin(); liter != section.lines.end(); ++liter)
{
std::string s = *liter;
out << s << std::endl;
}
}
out.close();
return true;
}
//////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// Get and set elements
// ------------
void IniFile::Set(const char* sectionName, const char* key, const char* newValue)
{
Section* section = GetOrCreateSection(sectionName);
@@ -195,17 +395,6 @@ void IniFile::Set(const char* sectionName, const char* key, bool newValue)
Set(sectionName, key, StringFromBool(newValue).c_str());
}
void IniFile::SetLines(const char* sectionName, const std::vector<std::string> &lines)
{
Section* section = GetOrCreateSection(sectionName);
section->lines.clear();
for (std::vector<std::string>::const_iterator iter = lines.begin(); iter != lines.end(); ++iter)
{
section->lines.push_back(*iter);
}
}
bool IniFile::Get(const char* sectionName, const char* key, std::string* value, const char* defaultValue)
{
Section* section = GetSection(sectionName);
@@ -279,173 +468,9 @@ bool IniFile::Get(const char* sectionName, const char* key, bool* value, bool de
*value = defaultValue;
return false;
}
////////////////////////////////////////
bool IniFile::DeleteKey(const char* sectionName, const char* key)
{
Section* section = GetSection(sectionName);
if (!section)
{
return false;
}
std::string* line = GetLine(section, key, 0, 0);
for (std::vector<std::string>::iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
{
if (line == &(*liter))
{
section->lines.erase(liter);
return true;
}
}
return false; //shouldn't happen
}
bool IniFile::Load(const char* filename)
{
sections.clear();
sections.push_back(Section(""));
//first section consists of the comments before the first real section
std::ifstream in;
in.open(filename, std::ios::in);
if (in.fail())
{
return false;
}
while (!in.eof())
{
char templine[512];
in.getline(templine, 512);
std::string line = templine;
if (in.eof())
{
break;
}
if (line.size() > 0)
{
if (line[0] == '[')
{
size_t endpos = line.find("]");
if (endpos != std::string::npos)
{
// New section!
std::string sub = line.substr(1, endpos - 1);
sections.push_back(Section(sub));
if (endpos + 1 < line.size())
{
sections[sections.size() - 1].comment = line.substr(endpos + 1);
}
}
}
else
{
sections[sections.size() - 1].lines.push_back(line);
}
}
}
in.close();
return true;
}
bool IniFile::Save(const char* filename)
{
std::ofstream out;
out.open(filename, std::ios::out);
if (out.fail())
{
return false;
}
for (std::vector<Section>::const_iterator iter = sections.begin(); iter != sections.end(); ++iter)
{
const Section& section = *iter;
if (section.name != "")
{
out << "[" << section.name << "]" << section.comment << std::endl;
}
for (std::vector<std::string>::const_iterator liter = section.lines.begin(); liter != section.lines.end(); ++liter)
{
std::string s = *liter;
out << s << std::endl;
}
}
out.close();
return true;
}
bool IniFile::GetKeys(const char* sectionName, std::vector<std::string>& keys) const
{
const Section* section = GetSection(sectionName);
if (!section)
{
return false;
}
keys.clear();
for (std::vector<std::string>::const_iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
{
std::string key;
ParseLine(*liter, &key, 0, 0);
keys.push_back(key);
}
return true;
}
bool IniFile::GetLines(const char* sectionName, std::vector<std::string>& lines) const
{
const Section* section = GetSection(sectionName);
if (!section)
return false;
lines.clear();
for (std::vector<std::string>::const_iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter)
{
std::string line = StripSpaces(*iter);
int commentPos = (int)line.find('#');
if (commentPos == 0)
{
continue;
}
if (commentPos != (int)std::string::npos)
{
line = StripSpaces(line.substr(0, commentPos));
}
lines.push_back(line);
}
return true;
}
void IniFile::SortSections()
{
std::sort(sections.begin(), sections.end());
}
/*
int main()
@@ -233,7 +233,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/NODEFAULTLIB:msvcrt.lib"
AdditionalDependencies="comctl32.lib wiiuse.lib"
AdditionalDependencies="comctl32.lib winmm.lib wiiuse.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_Wiimote.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\Externals\WiiUse\win32"
+3 -1
View File
@@ -42,6 +42,7 @@ void Config::Load()
iniFile.Get("Real", "Connect", &bConnectRealWiimote, true);
iniFile.Get("Real", "Use", &bUseRealWiimote, true);
iniFile.Get("Real", "UpdateStatus", &bUpdateRealWiimote, true);
}
void Config::Save()
@@ -54,7 +55,8 @@ void Config::Save()
iniFile.Set("Settings", "ClassicControllerConnected", bClassicControllerConnected);
iniFile.Set("Real", "Connect", bConnectRealWiimote);
iniFile.Set("Real", "Use", bUseRealWiimote);
iniFile.Set("Real", "Use", bUseRealWiimote);
iniFile.Set("Real", "UpdateStatus", bUpdateRealWiimote);
iniFile.Save(FULL_CONFIG_DIR "Wiimote.ini");
}
+1 -1
View File
@@ -36,7 +36,7 @@ struct Config
bool bNunchuckConnected, bClassicControllerConnected;
// Real Wiimote
bool bConnectRealWiimote, bUseRealWiimote;
bool bConnectRealWiimote, bUseRealWiimote, bUpdateRealWiimote;
};
extern Config g_Config;
File diff suppressed because it is too large Load Diff
+48 -14
View File
@@ -18,6 +18,9 @@
#ifndef __CONFIGDIALOG_h__
#define __CONFIGDIALOG_h__
#include <iostream>
#include <vector>
#include <wx/wx.h>
#include <wx/dialog.h>
#include <wx/textctrl.h>
@@ -30,7 +33,6 @@
#include <wx/filepicker.h>
#include <wx/gbsizer.h>
class ConfigDialog : public wxDialog
{
public:
@@ -40,17 +42,33 @@ class ConfigDialog : public wxDialog
long style = wxDEFAULT_DIALOG_STYLE);
virtual ~ConfigDialog();
// General open, close and event functions
void CloseClick(wxCommandEvent& event);
void UpdateGUI();
void OnKeyDown(wxKeyEvent& event);
void LoadFile(); void SaveFile();
// Status
wxStaticText * m_TextUpdateRate;
// Flash lights on connect functions
wxTimer * m_ExitTimer;
void DoFlashLights();
void StartTimer();
void FlashLights(wxTimerEvent& WXUNUSED(event)) { DoFlashLights(); }
bool ShutDown; int TimerCounter;
//void Update(wxTimerEvent& WXUNUSED(event));
// Wiimote status
wxGauge *m_GaugeBattery, *m_GaugeRoll[2], *m_GaugeGForce[3], *m_GaugeAccel[3];
bool m_bWaitForRecording, m_bRecording, m_bAllowA;
int m_iRecordTo;
void RecordMovement(wxCommandEvent& event);
void DoRecordMovement(u8 _x, u8 _y, u8 _z);
void DoRecordA(bool Pressed);
void ConvertToString();
wxTimer *m_TimeoutTimer, *m_TimeoutATimer;
void Update(wxTimerEvent& WXUNUSED(event));
void UpdateA(wxTimerEvent& WXUNUSED(event));
private:
DECLARE_EVENT_TABLE();
@@ -60,25 +78,38 @@ class ConfigDialog : public wxDialog
wxNotebook *m_Notebook;
wxPanel *m_PageEmu, *m_PageReal;
bool ControlsCreated;
wxCheckBox *m_SidewaysDPad; // Emulated Wiimote settings
wxCheckBox *m_WideScreen;
wxCheckBox *m_NunchuckConnected, *m_ClassicControllerConnected;
wxCheckBox *m_ConnectRealWiimote, *m_UseRealWiimote; // Real Wiimote settings
wxCheckBox *m_ConnectRealWiimote, *m_UseRealWiimote, *m_UpdateMeters; // Real Wiimote settings
static const int RECORDING_ROWS = 11;
wxButton * m_RecordButton[RECORDING_ROWS];
wxChoice * m_RecordHotKey[RECORDING_ROWS];
wxTextCtrl * m_RecordText[RECORDING_ROWS];
wxTextCtrl * m_RecordGameText[RECORDING_ROWS];
wxTextCtrl * m_RecordSpeed[RECORDING_ROWS];
wxChoice * m_RecordPlayBackSpeed[RECORDING_ROWS];
//static const int RECORDING_ROWS = 15;
wxButton * m_RecordButton[RECORDING_ROWS + 1];
wxChoice * m_RecordHotKey[RECORDING_ROWS + 1];
wxTextCtrl * m_RecordText[RECORDING_ROWS + 1];
wxTextCtrl * m_RecordGameText[RECORDING_ROWS + 1];
wxTextCtrl * m_RecordSpeed[RECORDING_ROWS + 1];
wxChoice * m_RecordPlayBackSpeed[RECORDING_ROWS + 1];
/*
struct m_sRecording
{
u8 x;
u8 y;
u8 z;
double Time;
};
*/
std::vector<SRecording> m_vRecording;
enum
{
ID_CLOSE = 1000,
ID_ABOUTOGL,
IDTM_EXIT, IDTM_UPDATE, // Timer
IDTM_EXIT, IDTM_UPDATE, IDTM_UPDATEA, // Timer
ID_NOTEBOOK,
ID_PAGEEMU,
@@ -89,13 +120,14 @@ class ConfigDialog : public wxDialog
ID_NUNCHUCKCONNECTED, ID_CLASSICCONTROLLERCONNECTED,
// Real
ID_CONNECT_REAL, ID_USE_REAL, IDT_STATUS,
IDB_RECORD, IDC_RECORD, IDT_RECORD_TEXT, IDT_RECORD_GAMETEXT, IDT_RECORD_SPEED, IDT_RECORD_PLAYSPEED
ID_CONNECT_REAL, ID_USE_REAL, ID_UPDATE_REAL, IDT_STATUS,
IDB_RECORD = 2000,
IDC_RECORD = 3000,
IDT_RECORD_TEXT, IDT_RECORD_GAMETEXT, IDT_RECORD_SPEED, IDT_RECORD_PLAYSPEED
};
void OnClose(wxCloseEvent& event);
void CreateGUIControls();
void AboutClick(wxCommandEvent& event);
void DoConnectReal(); // Real
@@ -105,4 +137,6 @@ class ConfigDialog : public wxDialog
void GeneralSettingsChanged(wxCommandEvent& event);
};
extern ConfigDialog *frame;
#endif
+57 -1
View File
@@ -26,8 +26,9 @@
#include "Common.h" // Common
#include "StringUtil.h" // for ArrayToString()
#include "IniFile.h"
#include "main.h"
#include "main.h" // Local
#include "wiimote_hid.h"
#include "EmuSubroutines.h"
#include "EmuDefinitions.h"
@@ -137,6 +138,61 @@ void Initialize()
g_EmulatedWiiMoteInitialized = true;
//////////////////////////////////////
// Load pre-recorded movements
// ---------------
IniFile file;
file.Load("WiimoteMovement.ini");
for(int i = 0; i < RECORDING_ROWS; i++)
{
// Get row name
std::string SaveName = StringFromFormat("Recording%i", i + 1);
// Get movement
std::string TmpMovement; file.Get(SaveName.c_str(), "Movement", &TmpMovement, "");
// Get time
std::string TmpTime; file.Get(SaveName.c_str(), "Time", &TmpTime, "");
SRecording Tmp;
for (int j = 0, k = 0; j < TmpMovement.length(); j+=7)
{
// Skip blank savings
if (TmpMovement.length() < 3) continue;
std::string StrX = TmpMovement.substr(j, 2);
std::string StrY = TmpMovement.substr(j + 2, 2);
std::string StrZ = TmpMovement.substr(j + 4, 2);
u32 TmpX, TmpY, TmpZ;
AsciiToHex(StrX.c_str(), TmpX);
AsciiToHex(StrY.c_str(), TmpY);
AsciiToHex(StrZ.c_str(), TmpZ);
Tmp.x = (u8)TmpX;
Tmp.x = (u8)TmpY;
Tmp.x = (u8)TmpZ;
// Go to next set of time values
int Time = atoi(TmpTime.substr(k, 5).c_str());
Tmp.Time = (double)(Time/1000);
VRecording.at(i).Recording.push_back(Tmp);
k += 6;
}
// HotKey
int TmpRecordHotKey; file.Get(SaveName.c_str(), "HotKey", &TmpRecordHotKey, -1);
VRecording.at(i).HotKey = TmpRecordHotKey;
// Recording speed
int TmpPlaybackSpeed; file.Get(SaveName.c_str(), "PlaybackSpeed", &TmpPlaybackSpeed, -1);
VRecording.at(i).PlaybackSpeed = TmpPlaybackSpeed;
Console::Print("Size:%i HotKey:%i Speed:%i\n",
VRecording.at(i).Recording.size(), VRecording.at(i).HotKey, VRecording.at(i).PlaybackSpeed
);
}
//////////////////////////
// I forgot what these were for?
// g_RegExt[0xfd] = 0x1e;
// g_RegExt[0xfc] = 0x9a;
@@ -46,9 +46,12 @@ namespace WiiMoteEmu
//******************************************************************************
////////////////////////////////////////////////////////////
// Wiimote core buttons
// ---------------
void FillReportInfo(wm_core& _core)
{
/* This has to be filled with zeroes because when no buttons are pressed the
/* This has to be filled with zeroes (and not for example 0xff) because when no buttons are pressed the
value is 00 00 */
memset(&_core, 0x00, sizeof(wm_core));
@@ -67,9 +70,7 @@ void FillReportInfo(wm_core& _core)
_core.home = GetAsyncKeyState('H') ? 1 : 0;
/* Sideways controls (for example for Wario Land) was not enabled automatically
so I have to use this function. I'm not sure how it works on the actual Wii.
*/
/* Sideways controls (for example for Wario Land) if the Wiimote is intended to be held sideways */
if(g_Config.bSidewaysDPad)
{
_core.left = GetAsyncKeyState(VK_DOWN) ? 1 : 0;
@@ -88,15 +89,18 @@ void FillReportInfo(wm_core& _core)
// TODO: fill in
#endif
}
//////////////////////////
// -----------------------------
/* Global declarations for FillReportAcc. The accelerometer x, y and z values range from
0x00 to 0xff with the default netural values being [y = 0x84, x = 0x84, z = 0x9f]
according to a source. The extremes are 0x00 for (-) and 0xff for (+). It's important
that all values are not 0x80, the the mouse pointer can disappear from the screen
permanently then, until z is adjusted back. */
////////////////////////////////////////////////////////////
// Wiimote accelerometer
// ---------------
/* The accelerometer x, y and z values range from 0x00 to 0xff with the default netural values
being [y = 0x84, x = 0x84, z = 0x9f] according to a source. The extremes are 0x00 for (-)
and 0xff for (+). It's important that all values are not 0x80, the mouse pointer can disappear
from the screen permanently then, until z is adjusted back. */
// ----------
// the variables are global so they can be changed during debugging
// Global declarations for FillReportAcc: These variables are global so they can be changed during debugging
//int A = 0, B = 128, C = 64; // for debugging
//int a = 1, b = 1, c = 2, d = -2; // for debugging
//int consoleDisplay = 0;
@@ -283,6 +287,7 @@ void FillReportAcc(wm_accel& _acc)
AX, AY, AZ
);*/
}
/////////////////////////
void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
@@ -459,7 +464,7 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
int abc = 0;
// ===================================================
/* Generate the 6 byte extension report, encrypted. The bytes are JX JY AX AY AZ BT. */
/* Generate the 6 byte extension report for the Nunchuck, encrypted. The bytes are JX JY AX AY AZ BT. */
// ----------------
void FillReportExtension(wm_extension& _ext)
{
@@ -529,6 +534,7 @@ void FillReportExtension(wm_extension& _ext)
// Write it back to the extension
memcpy(&_ext, &g_RegExtTmpReport[0x08], sizeof(_ext));
}
// =======================
// ===================================================
@@ -706,6 +712,7 @@ void FillReportClassicExtension(wm_classic_extension& _ext)
// Write it back
memcpy(&_ext, &g_RegExtTmpReport[0x08], sizeof(_ext));
}
// =======================
} // end of namespace
@@ -28,7 +28,11 @@
#include "StringUtil.h"
#include "wiimote_real.h" // Local
#include "main.h" // Local
#include "main.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigDlg.h"
#endif
#include "Config.h"
////////////////////////////////////////
namespace WiiMoteReal
@@ -68,13 +72,19 @@ void handle_event(struct wiimote_t* wm)
* This is useful because it saves battery power.
*/
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS))
{
wiiuse_motion_sensing(wm, 0);
g_MotionSensing = false;
}
/*
* Pressing plus will tell the wiimote we are interested in movement.
*/
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS))
{
wiiuse_motion_sensing(wm, 1);
g_MotionSensing = true;
}
/* If the accelerometer is turned on then print angles */
if (WIIUSE_USING_ACC(wm))
@@ -85,22 +95,30 @@ void handle_event(struct wiimote_t* wm)
Tmp += StringFromFormat("Battery: %1.2f\n", wm->battery_level);
Tmp += StringFromFormat("G-Force x, y, z: %1.2f %1.2f %1.2f\n", wm->gforce.x, wm->gforce.y, wm->gforce.z);
Tmp += StringFromFormat("Accel x, y, z: %03i %03i %03i\n\n", wm->accel.x, wm->accel.y, wm->accel.z);
Console::Print("%s", Tmp.c_str());
//Console::Print("%s", Tmp.c_str());
if(frame)
{
frame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5));
if(g_Config.bUpdateRealWiimote)
{
frame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5));
frame->m_GaugeRoll[0]->SetValue(wm->orient.roll + 180);
frame->m_GaugeRoll[1]->SetValue(wm->orient.pitch + 180);
frame->m_GaugeRoll[0]->SetValue(wm->orient.roll + 180);
frame->m_GaugeRoll[1]->SetValue(wm->orient.pitch + 180);
frame->m_GaugeGForce[0]->SetValue((int)floor((wm->gforce.x * 100) + 300.5));
frame->m_GaugeGForce[1]->SetValue((int)floor((wm->gforce.y * 100) + 300.5));
frame->m_GaugeGForce[2]->SetValue((int)floor((wm->gforce.z * 100) + 300.5));
frame->m_GaugeGForce[0]->SetValue((int)floor((wm->gforce.x * 100) + 300.5));
frame->m_GaugeGForce[1]->SetValue((int)floor((wm->gforce.y * 100) + 300.5));
frame->m_GaugeGForce[2]->SetValue((int)floor((wm->gforce.z * 100) + 300.5));
frame->m_GaugeAccel[0]->SetValue(wm->accel.x);
frame->m_GaugeAccel[1]->SetValue(wm->accel.y);
frame->m_GaugeAccel[2]->SetValue(wm->accel.z);
frame->m_GaugeAccel[0]->SetValue(wm->accel.x);
frame->m_GaugeAccel[1]->SetValue(wm->accel.y);
frame->m_GaugeAccel[2]->SetValue(wm->accel.z);
}
frame->DoRecordMovement(wm->accel.x, wm->accel.y, wm->accel.z);
if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) frame->DoRecordA(true);
else frame->DoRecordA(false);
}
}
}
+94 -8
View File
@@ -20,17 +20,16 @@
// Includes
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
#include "Common.h" // Common
#include "Config.h"
#include "StringUtil.h"
#include "ConsoleWindow.h" // For Start, Print, GetHwnd
#if defined(HAVE_WX) && HAVE_WX
#include <wx/aboutdlg.h>
#include "ConfigDlg.h"
#endif
#include "Timer.h"
#define EXCLUDEMAIN_H // Avoid certain declarations in main.h
#include "main.h" // Local
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigDlg.h"
#endif
#include "Config.h"
#include "pluginspecs_wiimote.h"
#include "EmuMain.h"
#if HAVE_WIIUSE
@@ -50,6 +49,17 @@ bool g_RealWiiMotePresent = false;
bool g_RealWiiMoteInitialized = false;
bool g_EmulatedWiiMoteInitialized = false;
// Update speed
int g_UpdateCounter = 0;
double g_UpdateTime = 0;
int g_UpdateRate = 0;
int g_UpdateWriteScreen = 0;
std::vector<int> g_UpdateTimeList (5, 0);
// Movement recording
std::vector<SRecordingAll> VRecording(RECORDING_ROWS);
// DLL instance
HINSTANCE g_hInstance;
#if defined(HAVE_WX) && HAVE_WX
@@ -134,6 +144,8 @@ void DllConfig(HWND _hParent)
win.SetHWND(_hParent);
#endif
Console::Open();
g_FrameOpen = true;
frame = new ConfigDialog(&win);
@@ -266,6 +278,18 @@ extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _
// ----------------
extern "C" void Wiimote_Update()
{
// Tell us about the update rate, but only about once every second to avoid a major slowdown
if (frame)
{
GetUpdateRate();
if (g_UpdateWriteScreen > g_UpdateRate)
{
frame->m_TextUpdateRate->SetLabel(wxString::Format("Update rate: %03i times/s", g_UpdateRate));
g_UpdateWriteScreen = 0;
}
g_UpdateWriteScreen++;
}
if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent)
WiiMoteEmu::Update();
#if HAVE_WIIUSE
@@ -285,17 +309,79 @@ extern "C" unsigned int Wiimote_GetAttachedControllers()
// Supporting functions
//******************************************************************************
/* Returns a timestamp with three decimals for precise time comparisons. The return format is
of the form seconds.milleseconds for example 1234.123. The leding seconds have no particular meaning
but are just there to enable use to tell if we have entered a new second or now. */
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
double GetDoubleTime()
{
#if defined(HAVE_WX) && HAVE_WX
wxDateTime datetime = wxDateTime::UNow(); // Get timestamp
u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970(); // Get continous timestamp
/* Remove a few years. We only really want enough seconds to make sure that we are
detecting actual actions, perhaps 60 seconds is enough really, but I leave a
year of seconds anyway, in case the user's clock is incorrect or something like that */
TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60);
//if (TmpSeconds < 0) return 0; // Check the the user's clock is working somewhat
u32 Seconds = (u32)TmpSeconds; // Make a smaller integer that fits in the double
double ms = datetime.GetMillisecond() / 1000.0;
double TmpTime = Seconds + ms;
return TmpTime;
#endif
}
/* Calculate the current update frequency. Calculate the time between ten updates, and average
five such rates. If we assume there are 60 updates per second if the game is running at full
speed then we get this measure on average once every second. The reason to have a few updates
between each measurement is becase the milliseconds may not be perfectly accurate and may return
the same time even when a milliseconds has actually passed, for example.*/
int GetUpdateRate()
{
#if defined(HAVE_WX) && HAVE_WX
if(g_UpdateCounter == 10)
{
// Erase the old ones
if(g_UpdateTimeList.size() == 5) g_UpdateTimeList.erase(g_UpdateTimeList.begin() + 0);
// Calculate the time and save it
int Time = (int)(10 / (GetDoubleTime() - g_UpdateTime));
g_UpdateTimeList.push_back(Time);
//Console::Print("Time: %i %f\n", Time, GetDoubleTime());
int TotalTime = 0;
for (int i = 0; i < g_UpdateTimeList.size(); i++)
TotalTime += g_UpdateTimeList.at(i);
g_UpdateRate = TotalTime / 5;
// Write the new update time
g_UpdateTime = GetDoubleTime();
g_UpdateCounter = 0;
}
g_UpdateCounter++;
return g_UpdateRate;
#else
return 0;
#endif
}
void DoInitialize()
{
// ----------------------------------------
// Debugging window
// ----------
/*Console::Open(100, 750, "Wiimote"); // give room for 20 rows
/**/Console::Open(100, 750, "Wiimote"); // give room for 20 rows
Console::Print("Wiimote console opened\n");
// Move window
//MoveWindow(Console::GetHwnd(), 0,400, 100*8,10*14, true); // small window
MoveWindow(Console::GetHwnd(), 400,0, 100*8,70*14, true); // big window*/
MoveWindow(Console::GetHwnd(), 400,0, 100*8,70*14, true); // big window
// ---------------
// Load config settings
+31 -6
View File
@@ -22,9 +22,6 @@
// Includes
// ¯¯¯¯¯¯¯¯¯¯
#include <iostream> // System
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigDlg.h"
#endif
////////////////////////////////
@@ -41,6 +38,24 @@
// Declarations
// ¯¯¯¯¯¯¯¯¯
void DoInitialize();
double GetDoubleTime();
int GetUpdateRate();
// Movement recording
#define RECORDING_ROWS 15
struct SRecording
{
u8 x;
u8 y;
u8 z;
double Time;
};
struct SRecordingAll
{
std::vector<SRecording> Recording;
int HotKey;
int PlaybackSpeed;
};
#ifndef EXCLUDEMAIN_H
extern bool g_EmulatorRunning;
@@ -48,10 +63,20 @@ void DoInitialize();
extern bool g_RealWiiMotePresent;
extern bool g_RealWiiMoteInitialized;
extern bool g_EmulatedWiiMoteInitialized;
// Update speed
extern int g_UpdateCounter;
extern double g_UpdateTime;
extern int g_UpdateWriteScreen;
extern int g_UpdateRate;
extern std::vector<int> g_UpdateTimeList;
#if defined(HAVE_WX) && HAVE_WX
extern ConfigDialog *frame;
#endif
// Movement recording
extern std::vector<SRecordingAll> VRecording;
//#if defined(HAVE_WX) && HAVE_WX && defined(__CONFIGDIALOG_h__)
// extern ConfigDialog *frame;
//#endif
#endif
////////////////////////////////
@@ -32,8 +32,9 @@
#include "wiimote_hid.h"
#include "main.h"
#include "Config.h"
#include "EmuMain.h"
#define EXCLUDE_H // Avoid certain declarations in main.h
#define EXCLUDE_H // Avoid certain declarations in wiimote_real.h
#include "wiimote_real.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigDlg.h"
@@ -67,6 +68,7 @@ int g_NumberOfWiiMotes;
CWiiMote* g_WiiMotes[MAX_WIIMOTES];
bool g_Shutdown = false;
bool g_LocalThread = true;
bool g_MotionSensing = false;
//******************************************************************************
// Probably this class should be in its own file
@@ -121,8 +123,10 @@ void SendData(u16 _channelID, const u8* _pData, u32 _Size)
/////////////////////
//////////////////////////////////////////
// Read data from wiimote (but don't send it to the core, just filter and queue)
//////////////////////////////////////////////////
/* Read data from wiimote (but don't send it to the core, just filter and queue). If we are not currently
using the real Wiimote we only allow it to receive data mode changes, but don't ask for any data in
return */
// ---------------
void ReadData()
{
@@ -131,6 +135,7 @@ void ReadData()
// Send data to the Wiimote
if (!m_EventWriteQueue.empty())
{
Console::Print("Writing data to the Wiimote\n");
SEvent& rEvent = m_EventWriteQueue.front();
wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, MAX_PAYLOAD);
m_EventWriteQueue.pop();
@@ -138,35 +143,37 @@ void ReadData()
m_pCriticalSection->Leave();
if (wiiuse_io_read(m_pWiiMote))
{
const byte* pBuffer = m_pWiiMote->event_buf;
// Don't queue up data if we are not using the real Wiimote
if(g_Config.bUseRealWiimote)
if (wiiuse_io_read(m_pWiiMote))
{
const byte* pBuffer = m_pWiiMote->event_buf;
// Check if we have a channel (connection) if so save the data...
if (m_channelID > 0)
{
m_pCriticalSection->Enter();
// Check if we have a channel (connection) if so save the data...
if (m_channelID > 0)
{
m_pCriticalSection->Enter();
// Filter out reports
if (pBuffer[0] >= 0x30)
{
// Copy Buffer to LastReport
memcpy(m_LastReport.m_PayLoad, pBuffer, MAX_PAYLOAD);
m_LastReportValid = true;
}
else
{
// Copy Buffer to ImportantEvent
SEvent ImportantEvent;
memcpy(ImportantEvent.m_PayLoad, pBuffer, MAX_PAYLOAD);
m_EventReadQueue.push(ImportantEvent);
}
m_pCriticalSection->Leave();
}
// Filter out reports
if (pBuffer[0] >= 0x30)
{
// Copy Buffer to LastReport
memcpy(m_LastReport.m_PayLoad, pBuffer, MAX_PAYLOAD);
m_LastReportValid = true;
}
else
{
// Copy Buffer to ImportantEvent
SEvent ImportantEvent;
memcpy(ImportantEvent.m_PayLoad, pBuffer, MAX_PAYLOAD);
m_EventReadQueue.push(ImportantEvent);
}
m_pCriticalSection->Leave();
}
//std::string Temp = ArrayToString(pBuffer, sizeof(pBuffer), 0);
//Console::Print("Data:\n%s\n", Temp.c_str());
}
//std::string Temp = ArrayToString(pBuffer, sizeof(pBuffer), 0);
//Console::Print("Data:\n%s\n", Temp.c_str());
}
};
/////////////////////
@@ -181,10 +188,12 @@ void Update()
if (m_EventReadQueue.empty())
{
// Send the same data as last time
if (m_LastReportValid) SendEvent(m_LastReport);
}
else
{
// Send all the new data we have collected
SendEvent(m_EventReadQueue.front());
m_EventReadQueue.pop();
}
@@ -352,7 +361,11 @@ void Update()
}
//////////////////////////////////
// Continuously read the Wiimote status
/* Continuously read the Wiimote status. However, the actual sending of data occurs in Update(). If we are
not currently using the real Wiimote we allow the separate ReadWiimote() function to run. Todo: Figure
out how to manually send the current data reporting mode to the real Wiimote so that we can entirely turn
off ReadData() (including wiiuse_io_write()) while we are not using the real wiimote. For example to risk
interrupting accelerometer recordings by a wiiuse_io_write(). */
// ---------------
#ifdef _WIN32
DWORD WINAPI ReadWiimote_ThreadFunc(void* arg)
@@ -364,7 +377,7 @@ void Update()
{
if(g_EmulatorRunning)
for (int i = 0; i < g_NumberOfWiiMotes; i++) g_WiiMotes[i]->ReadData();
else
else if (!g_Config.bUseRealWiimote)
ReadWiimote();
}
return 0;
@@ -43,6 +43,7 @@ void ReadWiimote();
#ifndef EXCLUDE_H
extern wiimote_t** g_WiiMotesFromWiiUse;
extern int g_NumberOfWiiMotes;
extern bool g_MotionSensing;
#endif
}; // WiiMoteReal