Implement Wii input recording.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7130 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
smelenchuk 2011-02-11 18:53:51 +00:00
parent e480ab2b10
commit ca78d3639b
3 changed files with 137 additions and 90 deletions

View File

@ -20,6 +20,8 @@ inline double round(double x) { return (x-floor(x))>0.5 ? ceil(x) : floor(x); }
#include "MatrixMath.h" #include "MatrixMath.h"
#include "../../OnFrame.h"
namespace WiimoteEmu namespace WiimoteEmu
{ {
@ -664,110 +666,124 @@ void Wiimote::Update()
u8 data[MAX_PAYLOAD]; u8 data[MAX_PAYLOAD];
memset(data, 0, sizeof(data)); memset(data, 0, sizeof(data));
data[0] = 0xA1;
data[1] = m_reporting_mode;
// figure out what data we need // figure out what data we need
const ReportFeatures& rptf = reporting_mode_features[m_reporting_mode - WM_REPORT_CORE]; s8 rptf_size = MAX_PAYLOAD;;
s8 rptf_size = rptf.size;
// core buttons if (Frame::IsPlayingInput())
if (rptf.core)
GetCoreData(data + rptf.core);
// acceleration
if (rptf.accel)
GetAccelData(data + rptf.accel, rptf.core?(data+rptf.core):NULL);
// IR
if (rptf.ir)
GetIRData(data + rptf.ir, (rptf.accel != 0));
// extension
if (rptf.ext)
GetExtData(data + rptf.ext);
// hybrid wiimote stuff
if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index])
{ {
using namespace WiimoteReal; Frame::PlayWiimote(data, rptf_size);
}
else
{
const ReportFeatures& rptf = reporting_mode_features[m_reporting_mode - WM_REPORT_CORE];
rptf_size = rptf.size;
g_refresh_critsec.Enter(); data[0] = 0xA1;
if (g_wiimotes[m_index]) data[1] = m_reporting_mode;
// core buttons
if (rptf.core)
GetCoreData(data + rptf.core);
// acceleration
if (rptf.accel)
GetAccelData(data + rptf.accel, rptf.core?(data+rptf.core):NULL);
// IR
if (rptf.ir)
GetIRData(data + rptf.ir, (rptf.accel != 0));
// extension
if (rptf.ext)
GetExtData(data + rptf.ext);
// hybrid wiimote stuff
if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index])
{ {
Report rpt = g_wiimotes[m_index]->ProcessReadQueue(); using namespace WiimoteReal;
const u8 *real_data = rpt.first;
if (real_data) g_refresh_critsec.Enter();
if (g_wiimotes[m_index])
{ {
switch (real_data[1]) Report rpt = g_wiimotes[m_index]->ProcessReadQueue();
const u8 *real_data = rpt.first;
if (real_data)
{ {
// use data reports switch (real_data[1])
default:
if (real_data[1] >= WM_REPORT_CORE)
{ {
const ReportFeatures& real_rptf = reporting_mode_features[real_data[1] - WM_REPORT_CORE]; // use data reports
default:
// force same report type from real-wiimote if (real_data[1] >= WM_REPORT_CORE)
if (&real_rptf != &rptf)
rptf_size = 0;
// core
// mix real-buttons with emu-buttons in the status struct, and in the report
if (real_rptf.core && rptf.core)
{ {
m_status.buttons |= *(wm_core*)(real_data + real_rptf.core); const ReportFeatures& real_rptf = reporting_mode_features[real_data[1] - WM_REPORT_CORE];
*(wm_core*)(data + rptf.core) = m_status.buttons;
// force same report type from real-wiimote
if (&real_rptf != &rptf)
rptf_size = 0;
// core
// mix real-buttons with emu-buttons in the status struct, and in the report
if (real_rptf.core && rptf.core)
{
m_status.buttons |= *(wm_core*)(real_data + real_rptf.core);
*(wm_core*)(data + rptf.core) = m_status.buttons;
}
// accel
// use real-accel data always i guess
if (real_rptf.accel && rptf.accel)
memcpy(data + rptf.accel, real_data + real_rptf.accel, sizeof(wm_accel));
// ir
// TODO
// ext
// use real-ext data if an emu-extention isn't chosen
if (real_rptf.ext && rptf.ext && (0 == m_extension->switch_extension))
memcpy(data + rptf.ext, real_data + real_rptf.ext, sizeof(wm_extension));
} }
else if (WM_ACK_DATA != real_data[1] || m_extension->active_extension > 0)
// accel rptf_size = 0;
// use real-accel data always i guess else
if (real_rptf.accel && rptf.accel) // use real-acks if an emu-extension isn't chosen
memcpy(data + rptf.accel, real_data + real_rptf.accel, sizeof(wm_accel)); rptf_size = -1;
break;
// ir
// TODO // use all status reports, after modification of the extension bit
case WM_STATUS_REPORT :
// ext //if (m_extension->switch_extension)
// use real-ext data if an emu-extention isn't chosen //((wm_status_report*)(real_data + 2))->extension = (m_extension->active_extension > 0);
if (real_rptf.ext && rptf.ext && (0 == m_extension->switch_extension)) if (m_extension->active_extension)
memcpy(data + rptf.ext, real_data + real_rptf.ext, sizeof(wm_extension)); ((wm_status_report*)(real_data + 2))->extension = 1;
}
else if (WM_ACK_DATA != real_data[1] || m_extension->active_extension > 0)
rptf_size = 0;
else
// use real-acks if an emu-extension isn't chosen
rptf_size = -1; rptf_size = -1;
break; break;
// use all status reports, after modification of the extension bit // use all read-data replies
case WM_STATUS_REPORT : case WM_READ_DATA_REPLY:
//if (m_extension->switch_extension) rptf_size = -1;
//((wm_status_report*)(real_data + 2))->extension = (m_extension->active_extension > 0); break;
if (m_extension->active_extension)
((wm_status_report*)(real_data + 2))->extension = 1; }
rptf_size = -1;
break; // copy over report from real-wiimote
if (-1 == rptf_size)
// use all read-data replies {
case WM_READ_DATA_REPLY: memcpy(data, real_data, rpt.second);
rptf_size = -1; rptf_size = rpt.second;
break; }
if (real_data != g_wiimotes[m_index]->\
m_last_data_report.first)
delete[] real_data;
} }
// copy over report from real-wiimote
if (-1 == rptf_size)
{
memcpy(data, real_data, rpt.second);
rptf_size = rpt.second;
}
if (real_data != g_wiimotes[m_index]->\
m_last_data_report.first)
delete[] real_data;
} }
g_refresh_critsec.Leave();
}
if (Frame::IsRecordingInput())
{
Frame::RecordWiimote(data, rptf_size);
} }
g_refresh_critsec.Leave();
} }
// don't send a data report if auto reporting is off // don't send a data report if auto reporting is off

View File

@ -217,6 +217,15 @@ void RecordInput(SPADStatus *PadStatus, int controllerID)
fwrite(&g_padState, sizeof(ControllerState), 1, g_recordfd); fwrite(&g_padState, sizeof(ControllerState), 1, g_recordfd);
} }
void RecordWiimote(u8 *data, s8 size)
{
if(!IsRecordingInput())
return;
fwrite(&size, 1, 1, g_recordfd);
fwrite(data, 1, size, g_recordfd);
}
bool PlayInput(const char *filename) bool PlayInput(const char *filename)
{ {
if(!filename || g_playMode != MODE_NONE || g_recordfd) if(!filename || g_playMode != MODE_NONE || g_recordfd)
@ -369,6 +378,26 @@ void PlayController(SPADStatus *PadStatus, int controllerID)
} }
} }
void PlayWiimote(u8 *data, s8 &size)
{
s8 count = 0;
if(!IsPlayingInput())
return;
fread(&count, 1, 1, g_recordfd);
size = (count > size) ? size : count;
fread(data, 1, size, g_recordfd);
// TODO: merge this with the above so that there's no duplicate code
if(feof(g_recordfd))
{
Core::DisplayMessage("Movie End", 2000);
// TODO: read-only mode
//EndPlayInput();
g_playMode = MODE_RECORDING;
}
}
void EndPlayInput() { void EndPlayInput() {
if (g_recordfd) if (g_recordfd)
fclose(g_recordfd); fclose(g_recordfd);

View File

@ -110,10 +110,12 @@ void FrameSkipping();
bool BeginRecordingInput(int controllers); bool BeginRecordingInput(int controllers);
void RecordInput(SPADStatus *PadStatus, int controllerID); void RecordInput(SPADStatus *PadStatus, int controllerID);
void RecordWiimote(u8* data, s8 size);
bool PlayInput(const char *filename); bool PlayInput(const char *filename);
void LoadInput(const char *filename); void LoadInput(const char *filename);
void PlayController(SPADStatus *PadStatus, int controllerID); void PlayController(SPADStatus *PadStatus, int controllerID);
void PlayWiimote(u8* data, s8 &size);
void EndPlayInput(); void EndPlayInput();
void SaveRecording(const char *filename); void SaveRecording(const char *filename);