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:
parent
e480ab2b10
commit
ca78d3639b
|
@ -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)
|
||||||
|
rptf_size = 0;
|
||||||
|
else
|
||||||
|
// use real-acks if an emu-extension isn't chosen
|
||||||
|
rptf_size = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
// accel
|
// use all status reports, after modification of the extension bit
|
||||||
// use real-accel data always i guess
|
case WM_STATUS_REPORT :
|
||||||
if (real_rptf.accel && rptf.accel)
|
//if (m_extension->switch_extension)
|
||||||
memcpy(data + rptf.accel, real_data + real_rptf.accel, sizeof(wm_accel));
|
//((wm_status_report*)(real_data + 2))->extension = (m_extension->active_extension > 0);
|
||||||
|
if (m_extension->active_extension)
|
||||||
// ir
|
((wm_status_report*)(real_data + 2))->extension = 1;
|
||||||
// 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)
|
|
||||||
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;
|
|
||||||
|
|
||||||
// use all read-data replies
|
}
|
||||||
case WM_READ_DATA_REPLY:
|
|
||||||
rptf_size = -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue