PadSimple: Added rerecording option in that the input saving counter it saved with the save state and rewinded when a saved state is loaded
Core: Tried to a address a semi-frequent hanging that would occur in single core mode and render to main frame git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2191 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
ec71298b06
commit
72424eeadc
|
@ -45,7 +45,10 @@ struct LinkedListItem : public T
|
|||
class PointerWrap
|
||||
{
|
||||
public:
|
||||
enum Mode // also defined in pluginspecs.h. Didn't want to couple them.
|
||||
/* READ is when we read from the save state file, WRITE is when we write to the
|
||||
save state file. This enumareted list is also defined in pluginspecs.h. Didn't
|
||||
want to couple them. */
|
||||
enum Mode
|
||||
{
|
||||
MODE_READ = 1,
|
||||
MODE_WRITE,
|
||||
|
|
|
@ -437,15 +437,30 @@ THREAD_RETURN EmuThread(void *pArg)
|
|||
Plugins.GetVideo()->Video_EnterLoop();
|
||||
}
|
||||
|
||||
// Wait for CPU thread to exit - it should have been signaled to do so by now
|
||||
if (cpuThread)
|
||||
cpuThread->WaitForDeath();
|
||||
if (g_pUpdateFPSDisplay != NULL)
|
||||
g_pUpdateFPSDisplay("Stopping...");
|
||||
|
||||
|
||||
// We have now exited the Video Loop and will shut down
|
||||
|
||||
|
||||
/* Check if we are using single core and are rendering to the main window. In that case we must avoid the WaitForSingleObject()
|
||||
loop in the cpu thread thread, because it will hang on occation, perhaps one time in three or so. I had this problem in the Wiimote plugin, what happened was that if I entered the
|
||||
WaitForSingleObject loop or any loop at all in the main thread, the separate thread would halt at a place where it called a function in
|
||||
the wxDialog class. The solution was to wait for the thread to stop with a timer from the wxDialog, and the proceed to shutdown.
|
||||
Perhaps something like that can be done here to? I just don't exactly how since in single core mode there should only be one
|
||||
thread right? So how can WaitForSingleObject() hang in it? */
|
||||
bool bRenderToMainSingleCore = false;
|
||||
if (GetParent((HWND)g_pWindowHandle) == NULL || _CoreParameter.bUseDualCore) bRenderToMainSingleCore = true;
|
||||
|
||||
|
||||
/* Wait for CPU thread to exit - it should have been signaled to do so by now. On the other hand this will be called by
|
||||
delete cpuThread to. So now we call it twice right? */
|
||||
if(!bRenderToMainSingleCore) if (cpuThread) cpuThread->WaitForDeath();
|
||||
// Write message
|
||||
if (g_pUpdateFPSDisplay != NULL) g_pUpdateFPSDisplay("Stopping...");
|
||||
|
||||
if (cpuThread)
|
||||
{
|
||||
delete cpuThread; // This joins the cpu thread.
|
||||
// This joins the cpu thread.
|
||||
if(!bRenderToMainSingleCore) delete cpuThread;
|
||||
// Returns after game exited
|
||||
cpuThread = NULL;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ void DoState(PointerWrap &p)
|
|||
CPluginManager &pm = CPluginManager::GetInstance();
|
||||
pm.GetVideo()->DoState(p.GetPPtr(), p.GetMode());
|
||||
pm.GetDSP()->DoState(p.GetPPtr(), p.GetMode());
|
||||
pm.GetPad(0)->DoState(p.GetPPtr(), p.GetMode());
|
||||
PowerPC::DoState(p);
|
||||
HW::DoState(p);
|
||||
CoreTiming::DoState(p);
|
||||
|
|
|
@ -184,6 +184,7 @@ Global
|
|||
{9A183B48-ECC2-4121-876A-9B3793686073}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9A183B48-ECC2-4121-876A-9B3793686073}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9A183B48-ECC2-4121-876A-9B3793686073}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
|
||||
{9A183B48-ECC2-4121-876A-9B3793686073}.DebugFast|Win32.Build.0 = DebugFast|Win32
|
||||
{9A183B48-ECC2-4121-876A-9B3793686073}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{9A183B48-ECC2-4121-876A-9B3793686073}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9A183B48-ECC2-4121-876A-9B3793686073}.Release|Win32.Build.0 = Release|Win32
|
||||
|
|
|
@ -39,6 +39,7 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
|
|||
//Recording
|
||||
EVT_CHECKBOX(ID_RECORDING,ConfigDialog::ControllerSettingsChanged)
|
||||
EVT_CHECKBOX(ID_PLAYBACK,ConfigDialog::ControllerSettingsChanged)
|
||||
EVT_BUTTON(ID_SAVE_RECORDING,ConfigDialog::ControllerSettingsChanged)
|
||||
|
||||
EVT_BUTTON(CTL_A,ConfigDialog::OnButtonClick)
|
||||
EVT_BUTTON(CTL_B,ConfigDialog::OnButtonClick)
|
||||
|
@ -177,11 +178,19 @@ void ConfigDialog::CreateGUIControls()
|
|||
m_SizeRecording[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Input Recording"));
|
||||
m_CheckRecording[i] = new wxCheckBox(m_Controller[i], ID_RECORDING, wxT("Record input"));
|
||||
m_CheckPlayback[i] = new wxCheckBox(m_Controller[i], ID_PLAYBACK, wxT("Play back input"));
|
||||
m_BtnSaveRecording[i] = new wxButton(m_Controller[i], ID_SAVE_RECORDING, wxT("Save recording"), wxDefaultPosition, wxDefaultSize);
|
||||
|
||||
// Tool tips
|
||||
m_CheckRecording[i]->SetToolTip(wxT("Your recording will be saved to pad-record.bin in the Dolphin dir when you stop the game"));
|
||||
m_CheckPlayback[i]->SetToolTip(wxT("Play back the pad-record.bin file from the Dolphin dir"));
|
||||
|
||||
m_BtnSaveRecording[i]->SetToolTip(wxT(
|
||||
"This will save the current recording to pad-record.bin. Your recording will\n"
|
||||
"also be automatically saved every 60 * 10 frames. And when you shut down the\n"
|
||||
"game."));
|
||||
|
||||
m_SizeRecording[i]->Add(m_CheckRecording[i], 0, wxEXPAND | wxALL, 1);
|
||||
m_SizeRecording[i]->Add(m_CheckPlayback[i], 0, wxEXPAND | wxALL, 1);
|
||||
m_SizeRecording[i]->Add(m_BtnSaveRecording[i], 0, wxEXPAND | wxALL, 1);
|
||||
|
||||
// Set values
|
||||
m_Attached[i]->SetValue(pad[i].bAttached);
|
||||
|
@ -189,9 +198,12 @@ void ConfigDialog::CreateGUIControls()
|
|||
m_CheckRecording[i]->SetValue(pad[i].bRecording);
|
||||
m_CheckPlayback[i]->SetValue(pad[i].bPlayback);
|
||||
|
||||
// Disable
|
||||
// Only enable these options for pad 3
|
||||
m_CheckRecording[i]->Enable(false); m_CheckRecording[0]->Enable(true);
|
||||
m_CheckPlayback[i]->Enable(false); m_CheckPlayback[0]->Enable(true);
|
||||
m_BtnSaveRecording[i]->Enable(false); m_BtnSaveRecording[0]->Enable(true);
|
||||
// Don't allow saving when we are not recording
|
||||
m_BtnSaveRecording[i]->Enable(g_EmulatorRunning && pad[0].bRecording);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Check if any XInput pad was found
|
||||
|
@ -365,6 +377,11 @@ void ConfigDialog::ControllerSettingsChanged(wxCommandEvent& event)
|
|||
// Turn off the other option
|
||||
pad[page].bRecording = false; m_CheckRecording[page]->SetValue(false);
|
||||
break;
|
||||
case ID_SAVE_RECORDING:
|
||||
// Double check again that we are still running a game
|
||||
if (g_EmulatorRunning) SaveRecord();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ class ConfigDialog : public wxDialog
|
|||
// Recording
|
||||
wxCheckBox *m_CheckRecording[4];
|
||||
wxCheckBox *m_CheckPlayback[4];
|
||||
wxButton *m_BtnSaveRecording[4];
|
||||
|
||||
wxButton *m_ButtonA[4];
|
||||
wxButton *m_ButtonB[4];
|
||||
|
@ -111,6 +112,7 @@ class ConfigDialog : public wxDialog
|
|||
// Input recording
|
||||
ID_RECORDING,
|
||||
ID_PLAYBACK,
|
||||
ID_SAVE_RECORDING,
|
||||
|
||||
// General settings
|
||||
ID_ATTACHED,
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "IniFile.h"
|
||||
#include "ConsoleWindow.h"
|
||||
#include "StringUtil.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
#include "GUI/ConfigDlg.h"
|
||||
|
@ -67,6 +68,7 @@ SPADInitialize g_PADInitialize;
|
|||
////////////////////////////////
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input Recording
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
|
@ -79,9 +81,14 @@ SPADInitialize g_PADInitialize;
|
|||
#define RECORD_SIZE (1024 * 128)
|
||||
SPADStatus recordBuffer[RECORD_SIZE];
|
||||
int count = 0;
|
||||
bool g_EmulatorRunning = false;
|
||||
////////////////////////////////
|
||||
|
||||
|
||||
void __Log(int log, const char *format, ...) {}
|
||||
void __Logv(int log, int v, const char *format, ...) {}
|
||||
|
||||
|
||||
//******************************************************************************
|
||||
// Supporting functions
|
||||
//******************************************************************************
|
||||
|
@ -94,11 +101,17 @@ void RecordInput(const SPADStatus& _rPADStatus)
|
|||
// Logging
|
||||
//u8 TmpData[sizeof(SPADStatus)];
|
||||
//memcpy(TmpData, &recordBuffer[count - 1], sizeof(SPADStatus));
|
||||
//Console::Print("RecordInput(): %s\n", ArrayToString(TmpData, sizeof(SPADStatus), 0, 30).c_str());
|
||||
//Console::Print("RecordInput(%i): %s\n", count, ArrayToString(TmpData, sizeof(SPADStatus), 0, 30).c_str());
|
||||
|
||||
// Auto save every ten seconds
|
||||
if (count % (60 * 10) == 0) SaveRecord();
|
||||
}
|
||||
|
||||
const SPADStatus& PlayRecord()
|
||||
{
|
||||
// Logging
|
||||
//Console::Print("PlayRecord(%i)\n", count);
|
||||
|
||||
if (count >= RECORD_SIZE)
|
||||
{
|
||||
// Todo: Make the recording size unlimited?
|
||||
|
@ -124,10 +137,13 @@ void LoadRecord()
|
|||
{
|
||||
PanicAlert("SimplePad: Could not open pad-record.bin");
|
||||
}
|
||||
|
||||
//Console::Print("LoadRecord()");
|
||||
}
|
||||
|
||||
void SaveRecord()
|
||||
{
|
||||
// Open the file in a way that clears all old data
|
||||
FILE* pStream = fopen("pad-record.bin", "wb");
|
||||
|
||||
if (pStream != NULL)
|
||||
|
@ -139,9 +155,8 @@ void SaveRecord()
|
|||
{
|
||||
PanicAlert("SimplePad: Could not save pad-record.bin");
|
||||
}
|
||||
|
||||
// Reset the counter
|
||||
count = 0;
|
||||
//PanicAlert("SaveRecord()");
|
||||
//Console::Print("SaveRecord()");
|
||||
}
|
||||
|
||||
|
||||
|
@ -239,93 +254,10 @@ void ScaleStickValues(unsigned char* outx,
|
|||
*outy = 0x80 + iy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//******************************************************************************
|
||||
// Plugin specification functions
|
||||
// Input
|
||||
//******************************************************************************
|
||||
|
||||
|
||||
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
|
||||
{
|
||||
_PluginInfo->Version = 0x0100;
|
||||
_PluginInfo->Type = PLUGIN_TYPE_PAD;
|
||||
|
||||
#ifdef DEBUGFAST
|
||||
sprintf(_PluginInfo->Name, "Dolphin KB/X360pad (DebugFast)");
|
||||
#else
|
||||
#ifndef _DEBUG
|
||||
sprintf(_PluginInfo->Name, "Dolphin KB/X360pad");
|
||||
#else
|
||||
sprintf(_PluginInfo->Name, "Dolphin KB/X360pad (Debug)");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals) {}
|
||||
|
||||
void DllConfig(HWND _hParent)
|
||||
{
|
||||
LoadConfig();
|
||||
#ifdef _WIN32
|
||||
wxWindow win;
|
||||
win.SetHWND(_hParent);
|
||||
ConfigDialog frame(&win);
|
||||
frame.ShowModal();
|
||||
win.SetHWND(0);
|
||||
#elif defined(HAVE_WX) && HAVE_WX
|
||||
ConfigDialog frame(NULL);
|
||||
frame.ShowModal();
|
||||
#endif
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
void DllDebugger(HWND _hParent, bool Show) {}
|
||||
|
||||
void Initialize(void *init)
|
||||
{
|
||||
//Console::Open(70, 5000);
|
||||
|
||||
// Load configuration
|
||||
LoadConfig();
|
||||
|
||||
// Load recorded input
|
||||
if (pad[0].bPlayback) LoadRecord();
|
||||
|
||||
g_PADInitialize = *(SPADInitialize*)init;
|
||||
|
||||
#ifdef _WIN32
|
||||
dinput.Init((HWND)g_PADInitialize.hWnd);
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
GXdsp = (Display*)g_PADInitialize.hWnd;
|
||||
#elif defined(HAVE_COCOA) && HAVE_COCOA
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void DoState(unsigned char **ptr, int mode) {
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
// Save recording
|
||||
if (pad[0].bRecording) SaveRecord();
|
||||
|
||||
#ifdef _WIN32
|
||||
dinput.Free();
|
||||
// Kill xpad rumble
|
||||
XINPUT_VIBRATION vib;
|
||||
vib.wLeftMotorSpeed = 0;
|
||||
vib.wRightMotorSpeed = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
if (pad[i].bRumble)
|
||||
XInputSetState(pad[i].XPadPlayer, &vib);
|
||||
#endif
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
void DInput_Read(int _numPAD, SPADStatus* _pPADStatus)
|
||||
{
|
||||
|
@ -657,6 +589,106 @@ void cocoa_Read(int _numPAD, SPADStatus* _pPADStatus)
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//******************************************************************************
|
||||
// Plugin specification functions
|
||||
//******************************************************************************
|
||||
|
||||
|
||||
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
|
||||
{
|
||||
_PluginInfo->Version = 0x0100;
|
||||
_PluginInfo->Type = PLUGIN_TYPE_PAD;
|
||||
|
||||
#ifdef DEBUGFAST
|
||||
sprintf(_PluginInfo->Name, "Dolphin KB/X360pad (DebugFast)");
|
||||
#else
|
||||
#ifndef _DEBUG
|
||||
sprintf(_PluginInfo->Name, "Dolphin KB/X360pad");
|
||||
#else
|
||||
sprintf(_PluginInfo->Name, "Dolphin KB/X360pad (Debug)");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals) {}
|
||||
|
||||
void DllConfig(HWND _hParent)
|
||||
{
|
||||
LoadConfig();
|
||||
#ifdef _WIN32
|
||||
wxWindow win;
|
||||
win.SetHWND(_hParent);
|
||||
ConfigDialog frame(&win);
|
||||
frame.ShowModal();
|
||||
win.SetHWND(0);
|
||||
#elif defined(HAVE_WX) && HAVE_WX
|
||||
ConfigDialog frame(NULL);
|
||||
frame.ShowModal();
|
||||
#endif
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
void DllDebugger(HWND _hParent, bool Show) {}
|
||||
|
||||
void Initialize(void *init)
|
||||
{
|
||||
//Console::Open(70, 5000);
|
||||
|
||||
// We are now running a game
|
||||
g_EmulatorRunning = true;
|
||||
|
||||
// Load configuration
|
||||
LoadConfig();
|
||||
|
||||
// Load recorded input if we are to play it back, otherwise begin with a blank recording
|
||||
if (pad[0].bPlayback) LoadRecord();
|
||||
|
||||
g_PADInitialize = *(SPADInitialize*)init;
|
||||
|
||||
#ifdef _WIN32
|
||||
dinput.Init((HWND)g_PADInitialize.hWnd);
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
GXdsp = (Display*)g_PADInitialize.hWnd;
|
||||
#elif defined(HAVE_COCOA) && HAVE_COCOA
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void DoState(unsigned char **ptr, int mode)
|
||||
{
|
||||
// Load or save the counter
|
||||
PointerWrap p(ptr, mode);
|
||||
p.Do(count);
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
//Console::Print("ShutDown()\n");
|
||||
|
||||
// Save recording
|
||||
if (pad[0].bRecording) SaveRecord();
|
||||
// Reset the counter
|
||||
count = 0;
|
||||
// We have stopped the game
|
||||
g_EmulatorRunning = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
dinput.Free();
|
||||
// Kill xpad rumble
|
||||
XINPUT_VIBRATION vib;
|
||||
vib.wLeftMotorSpeed = 0;
|
||||
vib.wRightMotorSpeed = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
if (pad[i].bRumble)
|
||||
XInputSetState(pad[i].XPadPlayer, &vib);
|
||||
#endif
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
|
||||
// Set buttons status from wxWidgets in the main application
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
void PAD_Input(u16 _Key, u8 _UpDown) {}
|
||||
|
|
|
@ -86,9 +86,13 @@ struct SPads
|
|||
};
|
||||
|
||||
extern SPads pad[];
|
||||
extern bool g_EmulatorRunning;
|
||||
|
||||
void LoadConfig();
|
||||
void SaveConfig();
|
||||
bool IsFocus();
|
||||
|
||||
// Input Recording
|
||||
void SaveRecord();
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue