mirror of https://github.com/PCSX2/pcsx2.git
recording: various formatting and review corrections
Squashed commit: [7955b42e3] recording: Throw errors on fread/fwrite errors. [5a2160f9e] recording: Remove function implementation from header files [f2937ab5f] recording: Fixed UndoCount metadata bug and will gracefully fail if savestate is missing [d7f4d43e5] recording: Refactored code-style to be consistent [0f77fbb71] recording: Refactor to use switch statements [28d7945f6] recording: Resolve CMake warnings and use tagged github links for cross-linking to LilyPad [7c01c6cb4] recording: corrected disparity between comment and code [17a8bd8d6] recording: Remove all usages of #define [3830f5a82] recording: Refactor enums and general cleanup [569ef7d67] recording: Completely disable new console log sources when recording is disabled
This commit is contained in:
parent
08d923ca6f
commit
506ea4c4d2
|
@ -46,6 +46,7 @@ Thumbs.db
|
||||||
|
|
||||||
Debug.txt
|
Debug.txt
|
||||||
install_log.txt
|
install_log.txt
|
||||||
|
padLog.txt
|
||||||
|
|
||||||
Debug
|
Debug
|
||||||
Release
|
Release
|
||||||
|
|
|
@ -82,7 +82,6 @@ GSwindow_OffsetXplus = Alt-Ctrl-RIGHT
|
||||||
GSwindow_OffsetReset = Alt-Ctrl-KP_DIVIDE
|
GSwindow_OffsetReset = Alt-Ctrl-KP_DIVIDE
|
||||||
|
|
||||||
# Recording Bindings
|
# Recording Bindings
|
||||||
# TODO: add to http://wiki.pcsx2.net/index.php/Hotkeys
|
|
||||||
FrameAdvance = SPACE
|
FrameAdvance = SPACE
|
||||||
TogglePause = Shift-P
|
TogglePause = Shift-P
|
||||||
InputRecordingModeToggle = Shift-R
|
InputRecordingModeToggle = Shift-R
|
||||||
|
|
|
@ -626,6 +626,7 @@ else()
|
||||||
set(pcsx2SSources "")
|
set(pcsx2SSources "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# common Sources
|
# common Sources
|
||||||
set(Common
|
set(Common
|
||||||
${pcsx2Sources}
|
${pcsx2Sources}
|
||||||
|
|
|
@ -455,7 +455,7 @@ struct Pcsx2Config
|
||||||
EnableCheats :1, // enables cheat detection and application
|
EnableCheats :1, // enables cheat detection and application
|
||||||
EnableWideScreenPatches :1,
|
EnableWideScreenPatches :1,
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
EnableRecordingTools : 1,
|
EnableRecordingTools :1,
|
||||||
#endif
|
#endif
|
||||||
// when enabled uses BOOT2 injection, skipping sony bios splashes
|
// when enabled uses BOOT2 injection, skipping sony bios splashes
|
||||||
UseBOOT2Injection :1,
|
UseBOOT2Injection :1,
|
||||||
|
|
|
@ -575,7 +575,7 @@ __fi void rcntUpdate_vSync()
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
{
|
{
|
||||||
g_RecordingControls.StopCheck();
|
g_RecordingControls.HandleFrameAdvanceAndStop();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -320,9 +320,9 @@ struct SysConsoleLogPack
|
||||||
ConsoleLogSource eeRecPerf;
|
ConsoleLogSource eeRecPerf;
|
||||||
ConsoleLogSource sysoutConsole;
|
ConsoleLogSource sysoutConsole;
|
||||||
|
|
||||||
ConsoleLogFromVM<Color_Cyan> eeConsole;
|
ConsoleLogFromVM<Color_Cyan> eeConsole;
|
||||||
ConsoleLogFromVM<Color_Yellow> iopConsole;
|
ConsoleLogFromVM<Color_Yellow> iopConsole;
|
||||||
ConsoleLogFromVM<Color_Cyan> deci2;
|
ConsoleLogFromVM<Color_Cyan> deci2;
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
ConsoleLogFromVM<Color_StrongMagenta> recordingConsole;
|
ConsoleLogFromVM<Color_StrongMagenta> recordingConsole;
|
||||||
|
|
|
@ -434,7 +434,7 @@ void Pcsx2Config::LoadSave( IniInterface& ini )
|
||||||
IniBitBool( EnableCheats );
|
IniBitBool( EnableCheats );
|
||||||
IniBitBool( EnableWideScreenPatches );
|
IniBitBool( EnableWideScreenPatches );
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
IniBitBool(EnableRecordingTools);
|
IniBitBool( EnableRecordingTools );
|
||||||
#endif
|
#endif
|
||||||
IniBitBool( ConsoleToStdio );
|
IniBitBool( ConsoleToStdio );
|
||||||
IniBitBool( HostFs );
|
IniBitBool( HostFs );
|
||||||
|
|
|
@ -22,130 +22,126 @@
|
||||||
#include "MemoryTypes.h"
|
#include "MemoryTypes.h"
|
||||||
#include "SaveState.h"
|
#include "SaveState.h"
|
||||||
|
|
||||||
#include "Recording/RecordingControls.h"
|
|
||||||
#include "InputRecording.h"
|
#include "InputRecording.h"
|
||||||
|
#include "Recording/RecordingControls.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
InputRecording g_InputRecording;
|
InputRecording g_InputRecording;
|
||||||
|
|
||||||
// --------------------------------
|
|
||||||
// Tag and save framecount along with savestate
|
// Tag and save framecount along with savestate
|
||||||
// --------------------------------
|
|
||||||
void SaveStateBase::InputRecordingFreeze()
|
void SaveStateBase::InputRecordingFreeze()
|
||||||
{
|
{
|
||||||
FreezeTag("InputRecording");
|
FreezeTag("InputRecording");
|
||||||
Freeze(g_FrameCount);
|
Freeze(g_FrameCount);
|
||||||
if (IsLoading()) {
|
|
||||||
g_InputRecordingData.addUndoCount();
|
if (g_FrameCount > 0 && IsLoading())
|
||||||
|
{
|
||||||
|
g_InputRecordingData.AddUndoCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------
|
|
||||||
// Main func for handling controller input data
|
// Main func for handling controller input data
|
||||||
// Called by Sio.cpp::sioWriteController
|
// - Called by Sio.cpp::sioWriteController
|
||||||
//----------------------------------
|
|
||||||
void InputRecording::ControllerInterrupt(u8 &data, u8 &port, u16 & bufCount, u8 buf[])
|
void InputRecording::ControllerInterrupt(u8 &data, u8 &port, u16 & bufCount, u8 buf[])
|
||||||
{
|
{
|
||||||
// TODO - Multi-Tap Support
|
// TODO - Multi-Tap Support
|
||||||
// Only examine controllers 1 / 2
|
// Only examine controllers 1 / 2
|
||||||
if (port < 0 || 1 < port)
|
if (port != 0 && port != 1)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================
|
/*
|
||||||
// This appears to try to ensure that we are only paying attention
|
This appears to try to ensure that we are only paying attention
|
||||||
// to the frames that matter, the ones that are reading from
|
to the frames that matter, the ones that are reading from
|
||||||
// the controller.
|
the controller.
|
||||||
//
|
|
||||||
// See - Lilypad.cpp:1254
|
See - Lilypad.cpp::PADpoll - https://github.com/PCSX2/pcsx2/blob/v1.5.0-dev/plugins/LilyPad/LilyPad.cpp#L1193
|
||||||
// 0x42 is the magic number for the default read query
|
0x42 is the magic number for the default read query
|
||||||
//
|
*/
|
||||||
// NOTE: this appears to break if you have logging enabled in LilyPad's config!
|
if (bufCount == 1)
|
||||||
//==========================
|
{
|
||||||
if (bufCount == 1) {
|
fInterruptFrame = data == 0x42;
|
||||||
if (data == 0x42)
|
if (!fInterruptFrame)
|
||||||
{
|
{
|
||||||
fInterruptFrame = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fInterruptFrame = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( bufCount == 2 ) {
|
else if ( bufCount == 2 )
|
||||||
// See - LilyPad.cpp:1255
|
{
|
||||||
// 0x5A is always the second byte in the buffer
|
/*
|
||||||
// when the normal READ_DATA_AND_VIBRRATE (0x42)
|
See - LilyPad.cpp::PADpoll - https://github.com/PCSX2/pcsx2/blob/v1.5.0-dev/plugins/LilyPad/LilyPad.cpp#L1194
|
||||||
// query is executed, this looks like a sanity check
|
0x5A is always the second byte in the buffer
|
||||||
if (buf[bufCount] != 0x5A) {
|
when the normal READ_DATA_AND_VIBRRATE (0x42)
|
||||||
|
query is executed, this looks like a sanity check
|
||||||
|
*/
|
||||||
|
if (buf[bufCount] != 0x5A)
|
||||||
|
{
|
||||||
fInterruptFrame = false;
|
fInterruptFrame = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fInterruptFrame)
|
if (!fInterruptFrame
|
||||||
|
|| state == INPUT_RECORDING_MODE_NONE
|
||||||
|
// We do not want to record or save the first two
|
||||||
|
// bytes in the data returned from LilyPad
|
||||||
|
|| bufCount < 3)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (state == NONE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// We do not want to record or save the first two
|
|
||||||
// bytes in the data returned from LilyPad
|
|
||||||
if (bufCount < 3)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//---------------
|
|
||||||
// Read or Write
|
// Read or Write
|
||||||
//---------------
|
|
||||||
const u8 &nowBuf = buf[bufCount];
|
const u8 &nowBuf = buf[bufCount];
|
||||||
if (state == RECORD)
|
if (state == INPUT_RECORDING_MODE_RECORD)
|
||||||
{
|
{
|
||||||
InputRecordingData.updateFrameMax(g_FrameCount);
|
InputRecordingData.UpdateFrameMax(g_FrameCount);
|
||||||
InputRecordingData.writeKeyBuf(g_FrameCount, port, bufCount - 3, nowBuf);
|
InputRecordingData.WriteKeyBuf(g_FrameCount, port, bufCount - 3, nowBuf);
|
||||||
}
|
}
|
||||||
else if (state == REPLAY)
|
else if (state == INPUT_RECORDING_MODE_REPLAY)
|
||||||
{
|
{
|
||||||
if (InputRecordingData.getMaxFrame() <= g_FrameCount)
|
if (InputRecordingData.GetMaxFrame() <= g_FrameCount)
|
||||||
{
|
{
|
||||||
// Pause the emulation but the movie is not closed
|
// Pause the emulation but the movie is not closed
|
||||||
g_RecordingControls.Pause();
|
g_RecordingControls.Pause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
u8 tmp = 0;
|
u8 tmp = 0;
|
||||||
if (InputRecordingData.readKeyBuf(tmp, g_FrameCount, port, bufCount - 3)) {
|
if (InputRecordingData.ReadKeyBuf(tmp, g_FrameCount, port, bufCount - 3))
|
||||||
|
{
|
||||||
buf[bufCount] = tmp;
|
buf[bufCount] = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------
|
// GUI Handler - Stop recording
|
||||||
// stop
|
void InputRecording::Stop()
|
||||||
//----------------------------------
|
{
|
||||||
void InputRecording::Stop() {
|
state = INPUT_RECORDING_MODE_NONE;
|
||||||
state = NONE;
|
if (InputRecordingData.Close())
|
||||||
if (InputRecordingData.Close()) {
|
{
|
||||||
recordingConLog(L"[REC]: InputRecording Recording Stopped.\n");
|
recordingConLog(L"[REC]: InputRecording Recording Stopped.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------
|
// GUI Handler - Start recording
|
||||||
// start
|
|
||||||
//----------------------------------
|
|
||||||
void InputRecording::Create(wxString FileName, bool fromSaveState, wxString authorName)
|
void InputRecording::Create(wxString FileName, bool fromSaveState, wxString authorName)
|
||||||
{
|
{
|
||||||
g_RecordingControls.Pause();
|
g_RecordingControls.Pause();
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
// create
|
// create
|
||||||
if (!InputRecordingData.Open(FileName, true, fromSaveState)) {
|
if (!InputRecordingData.Open(FileName, true, fromSaveState))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Set author name
|
// Set author name
|
||||||
if (!authorName.IsEmpty())
|
if (!authorName.IsEmpty())
|
||||||
{
|
{
|
||||||
InputRecordingData.getHeader().setAuthor(authorName);
|
InputRecordingData.GetHeader().SetAuthor(authorName);
|
||||||
}
|
}
|
||||||
// Set Game Name
|
// Set Game Name
|
||||||
// Code loosely taken from AppCoreThread.cpp to resolve the Game Name
|
// Code loosely taken from AppCoreThread.cpp to resolve the Game Name
|
||||||
|
@ -164,24 +160,27 @@ void InputRecording::Create(wxString FileName, bool fromSaveState, wxString auth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InputRecordingData.getHeader().setGameName(!gameName.IsEmpty() ? gameName : Path::GetFilename(g_Conf->CurrentIso));
|
InputRecordingData.GetHeader().SetGameName(!gameName.IsEmpty() ? gameName : Path::GetFilename(g_Conf->CurrentIso));
|
||||||
InputRecordingData.writeHeader();
|
InputRecordingData.WriteHeader();
|
||||||
state = RECORD;
|
state = INPUT_RECORDING_MODE_RECORD;
|
||||||
recordingConLog(wxString::Format(L"[REC]: Started new recording - [%s]\n", FileName));
|
recordingConLog(wxString::Format(L"[REC]: Started new recording - [%s]\n", FileName));
|
||||||
|
|
||||||
// In every case, we reset the g_FrameCount
|
// In every case, we reset the g_FrameCount
|
||||||
g_FrameCount = 0;
|
g_FrameCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GUI Handler - Play a recording
|
||||||
void InputRecording::Play(wxString FileName, bool fromSaveState)
|
void InputRecording::Play(wxString FileName, bool fromSaveState)
|
||||||
{
|
{
|
||||||
g_RecordingControls.Pause();
|
g_RecordingControls.Pause();
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
if (!InputRecordingData.Open(FileName, false, false)) {
|
if (!InputRecordingData.Open(FileName, false, false))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!InputRecordingData.readHeaderAndCheck()) {
|
if (!InputRecordingData.ReadHeaderAndCheck())
|
||||||
|
{
|
||||||
recordingConLog(L"[REC]: This file is not a correct InputRecording file.\n");
|
recordingConLog(L"[REC]: This file is not a correct InputRecording file.\n");
|
||||||
InputRecordingData.Close();
|
InputRecordingData.Close();
|
||||||
return;
|
return;
|
||||||
|
@ -189,32 +188,46 @@ void InputRecording::Play(wxString FileName, bool fromSaveState)
|
||||||
// Check author name
|
// Check author name
|
||||||
if (!g_Conf->CurrentIso.IsEmpty())
|
if (!g_Conf->CurrentIso.IsEmpty())
|
||||||
{
|
{
|
||||||
if (Path::GetFilename(g_Conf->CurrentIso) != InputRecordingData.getHeader().gameName) {
|
if (Path::GetFilename(g_Conf->CurrentIso) != InputRecordingData.GetHeader().gameName)
|
||||||
|
{
|
||||||
recordingConLog(L"[REC]: Information on CD in Movie file is Different.\n");
|
recordingConLog(L"[REC]: Information on CD in Movie file is Different.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state = REPLAY;
|
state = INPUT_RECORDING_MODE_REPLAY;
|
||||||
recordingConLog(wxString::Format(L"[REC]: Replaying movie - [%s]\n", FileName));
|
recordingConLog(wxString::Format(L"[REC]: Replaying movie - [%s]\n", FileName));
|
||||||
recordingConLog(wxString::Format(L"Recording File Version: %d\n", InputRecordingData.getHeader().version));
|
recordingConLog(wxString::Format(L"[REC]: Recording File Version: %d\n", InputRecordingData.GetHeader().version));
|
||||||
recordingConLog(wxString::Format(L"Associated Game Name / ISO Filename: %s\n", InputRecordingData.getHeader().gameName));
|
recordingConLog(wxString::Format(L"[REC]: Associated Game Name / ISO Filename: %s\n", InputRecordingData.GetHeader().gameName));
|
||||||
recordingConLog(wxString::Format(L"Author: %s\n", InputRecordingData.getHeader().author));
|
recordingConLog(wxString::Format(L"[REC]: Author: %s\n", InputRecordingData.GetHeader().author));
|
||||||
recordingConLog(wxString::Format(L"MaxFrame: %d\n", InputRecordingData.getMaxFrame()));
|
recordingConLog(wxString::Format(L"[REC]: MaxFrame: %d\n", InputRecordingData.GetMaxFrame()));
|
||||||
recordingConLog(wxString::Format(L"UndoCount: %d\n", InputRecordingData.getUndoCount()));
|
recordingConLog(wxString::Format(L"[REC]: UndoCount: %d\n", InputRecordingData.GetUndoCount()));
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------
|
// Keybind Handler - Toggle between recording input and not
|
||||||
// shortcut key
|
|
||||||
//----------------------------------
|
|
||||||
void InputRecording::RecordModeToggle()
|
void InputRecording::RecordModeToggle()
|
||||||
{
|
{
|
||||||
if (state == REPLAY) {
|
if (state == INPUT_RECORDING_MODE_REPLAY)
|
||||||
state = RECORD;
|
{
|
||||||
|
state = INPUT_RECORDING_MODE_RECORD;
|
||||||
recordingConLog("[REC]: Record mode ON.\n");
|
recordingConLog("[REC]: Record mode ON.\n");
|
||||||
}
|
}
|
||||||
else if (state == RECORD) {
|
else if (state == INPUT_RECORDING_MODE_RECORD)
|
||||||
state = REPLAY;
|
{
|
||||||
|
state = INPUT_RECORDING_MODE_REPLAY;
|
||||||
recordingConLog("[REC]: Replay mode ON.\n");
|
recordingConLog("[REC]: Replay mode ON.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INPUT_RECORDING_MODE InputRecording::GetModeState()
|
||||||
|
{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputRecordingFile & InputRecording::GetInputRecordingData()
|
||||||
|
{
|
||||||
|
return InputRecordingData;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputRecording::IsInterruptFrame()
|
||||||
|
{
|
||||||
|
return fInterruptFrame;
|
||||||
|
}
|
||||||
|
|
|
@ -18,46 +18,37 @@
|
||||||
#include "InputRecordingFile.h"
|
#include "InputRecordingFile.h"
|
||||||
|
|
||||||
|
|
||||||
//----------------------------
|
enum INPUT_RECORDING_MODE
|
||||||
// InputRecording
|
{
|
||||||
//----------------------------
|
INPUT_RECORDING_MODE_NONE,
|
||||||
class InputRecording {
|
INPUT_RECORDING_MODE_RECORD,
|
||||||
|
INPUT_RECORDING_MODE_REPLAY,
|
||||||
|
};
|
||||||
|
|
||||||
|
class InputRecording
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
InputRecording() {}
|
InputRecording() {}
|
||||||
~InputRecording(){}
|
~InputRecording(){}
|
||||||
public:
|
|
||||||
// controller
|
|
||||||
void ControllerInterrupt(u8 &data, u8 &port, u16 & BufCount, u8 buf[]);
|
void ControllerInterrupt(u8 &data, u8 &port, u16 & BufCount, u8 buf[]);
|
||||||
|
|
||||||
// menu bar
|
void RecordModeToggle();
|
||||||
|
|
||||||
|
INPUT_RECORDING_MODE GetModeState();
|
||||||
|
InputRecordingFile & GetInputRecordingData();
|
||||||
|
bool IsInterruptFrame();
|
||||||
|
|
||||||
void Stop();
|
void Stop();
|
||||||
void Create(wxString filename, bool fromSaveState, wxString authorName);
|
void Create(wxString filename, bool fromSaveState, wxString authorName);
|
||||||
void Play(wxString filename, bool fromSaveState);
|
void Play(wxString filename, bool fromSaveState);
|
||||||
|
|
||||||
// shortcut key
|
|
||||||
void RecordModeToggle();
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum KEY_MOVIE_MODE {
|
|
||||||
NONE,
|
|
||||||
RECORD,
|
|
||||||
REPLAY,
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// getter
|
|
||||||
KEY_MOVIE_MODE getModeState() { return state; }
|
|
||||||
InputRecordingFile & getInputRecordingData() {return InputRecordingData;}
|
|
||||||
bool isInterruptFrame() { return fInterruptFrame; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
InputRecordingFile InputRecordingData;
|
InputRecordingFile InputRecordingData;
|
||||||
KEY_MOVIE_MODE state = NONE;
|
INPUT_RECORDING_MODE state = INPUT_RECORDING_MODE_NONE;
|
||||||
bool fInterruptFrame = false;
|
bool fInterruptFrame = false;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern InputRecording g_InputRecording;
|
extern InputRecording g_InputRecording;
|
||||||
#define g_InputRecordingData (g_InputRecording.getInputRecordingData())
|
static InputRecordingFile& g_InputRecordingData = g_InputRecording.GetInputRecordingData();
|
||||||
#define g_InputRecordingHeader (g_InputRecording.getInputRecordingData().getHeader())
|
static InputRecordingHeader& g_InputRecordingHeader = g_InputRecording.GetInputRecordingData().GetHeader();
|
||||||
|
|
|
@ -23,25 +23,17 @@
|
||||||
|
|
||||||
#include "InputRecordingFile.h"
|
#include "InputRecordingFile.h"
|
||||||
|
|
||||||
#define HEADER_SIZE (sizeof(InputRecordingHeader)+4+4)
|
long InputRecordingFile::GetBlockSeekPoint(const long & frame)
|
||||||
#define SAVESTATE_HEADER_SIZE (sizeof(bool))
|
|
||||||
#define BLOCK_HEADER_SIZE (0)
|
|
||||||
#define BLOCK_DATA_SIZE (18*2)
|
|
||||||
#define BLOCK_SIZE (BLOCK_HEADER_SIZE+BLOCK_DATA_SIZE)
|
|
||||||
|
|
||||||
#define SEEKPOINT_FRAMEMAX (sizeof(InputRecordingHeader))
|
|
||||||
#define SEEKPOINT_UNDOCOUNT (sizeof(InputRecordingHeader)+4)
|
|
||||||
#define SEEKPOINT_SAVESTATE (SEEKPOINT_UNDOCOUNT+4)
|
|
||||||
|
|
||||||
long InputRecordingFile::_getBlockSeekPoint(const long & frame)
|
|
||||||
{
|
{
|
||||||
if (savestate.fromSavestate) {
|
if (savestate.fromSavestate)
|
||||||
return HEADER_SIZE
|
{
|
||||||
+ SAVESTATE_HEADER_SIZE
|
return RecordingHeaderSize
|
||||||
+ frame * BLOCK_SIZE;
|
+ RecordingSavestateHeaderSize
|
||||||
|
+ frame * RecordingBlockSize;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
return HEADER_SIZE + sizeof(bool) + (frame)*BLOCK_SIZE;
|
{
|
||||||
|
return RecordingHeaderSize + sizeof(bool) + (frame)*RecordingBlockSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,11 +42,12 @@ bool InputRecordingFile::Open(const wxString path, bool fNewOpen, bool fromSaveS
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
wxString mode = L"rb+";
|
wxString mode = L"rb+";
|
||||||
if (fNewOpen) {
|
if (fNewOpen)
|
||||||
|
{
|
||||||
mode = L"wb+";
|
mode = L"wb+";
|
||||||
MaxFrame = 0;
|
MaxFrame = 0;
|
||||||
UndoCount = 0;
|
UndoCount = 0;
|
||||||
header.init();
|
header.Init();
|
||||||
}
|
}
|
||||||
recordingFile = wxFopen(path, mode);
|
recordingFile = wxFopen(path, mode);
|
||||||
if ( recordingFile == NULL )
|
if ( recordingFile == NULL )
|
||||||
|
@ -64,98 +57,114 @@ bool InputRecordingFile::Open(const wxString path, bool fNewOpen, bool fromSaveS
|
||||||
}
|
}
|
||||||
filename = path;
|
filename = path;
|
||||||
|
|
||||||
// problems seem to be be based in how we are saving the savestate
|
if (fNewOpen)
|
||||||
if (fNewOpen) {
|
{
|
||||||
if (fromSaveState) {
|
if (fromSaveState)
|
||||||
|
{
|
||||||
savestate.fromSavestate = true;
|
savestate.fromSavestate = true;
|
||||||
// TODO - Return save-state data back into the movie file eventually.
|
|
||||||
FILE* ssFileCheck = wxFopen(path + "_SaveState.p2s", "r");
|
FILE* ssFileCheck = wxFopen(path + "_SaveState.p2s", "r");
|
||||||
if (ssFileCheck != NULL) {
|
if (ssFileCheck != NULL)
|
||||||
|
{
|
||||||
wxCopyFile(path + "_SaveState.p2s", path + "_SaveState.p2s.bak", false);
|
wxCopyFile(path + "_SaveState.p2s", path + "_SaveState.p2s.bak", false);
|
||||||
|
fclose(ssFileCheck);
|
||||||
}
|
}
|
||||||
fclose(ssFileCheck);
|
|
||||||
StateCopy_SaveToFile(path + "_SaveState.p2s");
|
StateCopy_SaveToFile(path + "_SaveState.p2s");
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
sApp.SysExecute();
|
sApp.SysExecute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gracefully close the current recording file
|
||||||
bool InputRecordingFile::Close()
|
bool InputRecordingFile::Close()
|
||||||
{
|
{
|
||||||
if (recordingFile == NULL)
|
if (recordingFile == NULL)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
writeHeader();
|
}
|
||||||
writeSaveState();
|
WriteHeader();
|
||||||
|
WriteSaveState();
|
||||||
fclose(recordingFile);
|
fclose(recordingFile);
|
||||||
recordingFile = NULL;
|
recordingFile = NULL;
|
||||||
filename = "";
|
filename = "";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputRecordingFile::writeSaveState() {
|
// Write savestate flag to file
|
||||||
|
bool InputRecordingFile::WriteSaveState() {
|
||||||
if (recordingFile == NULL)
|
if (recordingFile == NULL)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
fseek(recordingFile, SEEKPOINT_SAVESTATE, SEEK_SET);
|
fseek(recordingFile, RecordingSeekpointSaveState, SEEK_SET);
|
||||||
if (fwrite(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1)
|
if (fwrite(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------
|
// Write controller input buffer to file (per frame)
|
||||||
// write frame
|
bool InputRecordingFile::WriteKeyBuf(const uint & frame, const uint port, const uint bufIndex, const u8 & buf)
|
||||||
//----------------------------------
|
|
||||||
bool InputRecordingFile::writeKeyBuf(const uint & frame, const uint port, const uint bufIndex, const u8 & buf)
|
|
||||||
{
|
{
|
||||||
if (recordingFile == NULL)
|
if (recordingFile == NULL)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE + 18 * port + bufIndex;
|
long seek = GetBlockSeekPoint(frame) + RecordingBlockHeaderSize + 18 * port + bufIndex;
|
||||||
|
|
||||||
if (fseek(recordingFile, seek, SEEK_SET) != 0)
|
if (fseek(recordingFile, seek, SEEK_SET) != 0
|
||||||
return false;
|
|| fwrite(&buf, 1, 1, recordingFile) != 1)
|
||||||
if (fwrite(&buf, 1, 1, recordingFile) != 1)
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
fflush(recordingFile);
|
fflush(recordingFile);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------
|
// Read controller input buffer from file (per frame)
|
||||||
// read frame
|
bool InputRecordingFile::ReadKeyBuf(u8 & result,const uint & frame, const uint port, const uint bufIndex)
|
||||||
//----------------------------------
|
|
||||||
bool InputRecordingFile::readKeyBuf(u8 & result,const uint & frame, const uint port, const uint bufIndex)
|
|
||||||
{
|
{
|
||||||
if (recordingFile == NULL)
|
if (recordingFile == NULL)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE + 18 * port + bufIndex;
|
long seek = GetBlockSeekPoint(frame) + RecordingBlockHeaderSize + 18 * port + bufIndex;
|
||||||
if (fseek(recordingFile, seek, SEEK_SET) != 0)
|
if (fseek(recordingFile, seek, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (fread(&result, 1, 1, recordingFile) != 1)
|
if (fread(&result, 1, 1, recordingFile) != 1)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===================================
|
|
||||||
// pad
|
void InputRecordingFile::GetPadData(PadData & result, unsigned long frame)
|
||||||
//===================================
|
|
||||||
void InputRecordingFile::getPadData(PadData & result, unsigned long frame)
|
|
||||||
{
|
{
|
||||||
result.fExistKey = false;
|
result.fExistKey = false;
|
||||||
if (recordingFile == NULL)
|
if (recordingFile == NULL)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE;
|
long seek = GetBlockSeekPoint(frame) + RecordingBlockHeaderSize;
|
||||||
if (fseek(recordingFile, seek, SEEK_SET) != 0)
|
if (fseek(recordingFile, seek, SEEK_SET) != 0
|
||||||
return;
|
|| fread(result.buf, 1, RecordingBlockDataSize, recordingFile) == 0)
|
||||||
if (fread(result.buf, 1, BLOCK_DATA_SIZE, recordingFile) == 0)
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
result.fExistKey = true;
|
result.fExistKey = true;
|
||||||
}
|
}
|
||||||
|
@ -163,21 +172,33 @@ void InputRecordingFile::getPadData(PadData & result, unsigned long frame)
|
||||||
bool InputRecordingFile::DeletePadData(unsigned long frame)
|
bool InputRecordingFile::DeletePadData(unsigned long frame)
|
||||||
{
|
{
|
||||||
if (recordingFile == NULL)
|
if (recordingFile == NULL)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned long i = frame; i < MaxFrame - 1; i++)
|
for (unsigned long i = frame; i < MaxFrame - 1; i++)
|
||||||
{
|
{
|
||||||
long seek1 = _getBlockSeekPoint(i+1) + BLOCK_HEADER_SIZE;
|
long seek1 = GetBlockSeekPoint(i+1) + RecordingBlockHeaderSize;
|
||||||
long seek2 = _getBlockSeekPoint(i) + BLOCK_HEADER_SIZE;
|
long seek2 = GetBlockSeekPoint(i) + RecordingBlockHeaderSize;
|
||||||
|
|
||||||
u8 buf[2][18];
|
u8 buf[2][18];
|
||||||
fseek(recordingFile, seek1, SEEK_SET);
|
fseek(recordingFile, seek1, SEEK_SET);
|
||||||
fread(buf, 1, BLOCK_DATA_SIZE, recordingFile);
|
int rSize = fread(buf, 1, RecordingBlockDataSize, recordingFile);
|
||||||
|
if (rSize != RecordingBlockDataSize)
|
||||||
|
{
|
||||||
|
recordingConLog(wxString::Format("[REC]: Error encountered when reading from file: Expected %d bytes, read %d instead.\n", RecordingBlockDataSize, rSize));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
fseek(recordingFile, seek2, SEEK_SET);
|
fseek(recordingFile, seek2, SEEK_SET);
|
||||||
fwrite(buf,1, BLOCK_DATA_SIZE, recordingFile);
|
rSize = fwrite(buf, 1, RecordingBlockDataSize, recordingFile);
|
||||||
|
if (rSize != RecordingBlockDataSize)
|
||||||
|
{
|
||||||
|
recordingConLog(wxString::Format("[REC]: Error encountered when writing to file: Expected %d bytes, read %d instead.\n", RecordingBlockDataSize, rSize));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MaxFrame--;
|
MaxFrame--;
|
||||||
writeMaxFrame();
|
WriteMaxFrame();
|
||||||
fflush(recordingFile);
|
fflush(recordingFile);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -185,29 +206,42 @@ bool InputRecordingFile::DeletePadData(unsigned long frame)
|
||||||
|
|
||||||
bool InputRecordingFile::InsertPadData(unsigned long frame, const PadData& key)
|
bool InputRecordingFile::InsertPadData(unsigned long frame, const PadData& key)
|
||||||
{
|
{
|
||||||
if (recordingFile == NULL)
|
if (recordingFile == NULL || !key.fExistKey)
|
||||||
return false;
|
{
|
||||||
if (!key.fExistKey)
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned long i = MaxFrame - 1; i >= frame; i--)
|
for (unsigned long i = MaxFrame - 1; i >= frame; i--)
|
||||||
{
|
{
|
||||||
long seek1 = _getBlockSeekPoint(i) + BLOCK_HEADER_SIZE;
|
long seek1 = GetBlockSeekPoint(i) + RecordingBlockHeaderSize;
|
||||||
long seek2 = _getBlockSeekPoint(i+1) + BLOCK_HEADER_SIZE;
|
long seek2 = GetBlockSeekPoint(i+1) + RecordingBlockHeaderSize;
|
||||||
|
|
||||||
u8 buf[2][18];
|
u8 buf[2][18];
|
||||||
fseek(recordingFile, seek1, SEEK_SET);
|
fseek(recordingFile, seek1, SEEK_SET);
|
||||||
fread(buf, 1, BLOCK_DATA_SIZE, recordingFile);
|
int rSize = fread(buf, 1, RecordingBlockDataSize, recordingFile);
|
||||||
|
if (rSize != RecordingBlockDataSize)
|
||||||
|
{
|
||||||
|
recordingConLog(wxString::Format("[REC]: Error encountered when reading from file: Expected %d bytes, read %d instead.\n", RecordingBlockDataSize, rSize));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
fseek(recordingFile, seek2, SEEK_SET);
|
fseek(recordingFile, seek2, SEEK_SET);
|
||||||
fwrite(buf, 1, BLOCK_DATA_SIZE, recordingFile);
|
rSize = fwrite(buf, 1, RecordingBlockDataSize, recordingFile);
|
||||||
|
if (rSize != RecordingBlockDataSize)
|
||||||
|
{
|
||||||
|
recordingConLog(wxString::Format("[REC]: Error encountered when writing to file: Expected %d bytes, wrote %d instead.\n", RecordingBlockDataSize, rSize));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
long seek = GetBlockSeekPoint(frame) + RecordingBlockHeaderSize;
|
||||||
|
fseek(recordingFile, seek, SEEK_SET);
|
||||||
|
int rSize = fwrite(key.buf, 1, RecordingBlockDataSize, recordingFile);
|
||||||
|
if (rSize != RecordingBlockDataSize)
|
||||||
{
|
{
|
||||||
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE;
|
recordingConLog(wxString::Format("[REC]: Error encountered when writing to file: Expected %d bytes, wrote %d instead.\n", RecordingBlockDataSize, rSize));
|
||||||
fseek(recordingFile, seek, SEEK_SET);
|
return false;
|
||||||
fwrite(key.buf, 1, BLOCK_DATA_SIZE, recordingFile);
|
|
||||||
}
|
}
|
||||||
MaxFrame++;
|
MaxFrame++;
|
||||||
writeMaxFrame();
|
WriteMaxFrame();
|
||||||
fflush(recordingFile);
|
fflush(recordingFile);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -216,100 +250,149 @@ bool InputRecordingFile::InsertPadData(unsigned long frame, const PadData& key)
|
||||||
bool InputRecordingFile::UpdatePadData(unsigned long frame, const PadData& key)
|
bool InputRecordingFile::UpdatePadData(unsigned long frame, const PadData& key)
|
||||||
{
|
{
|
||||||
if (recordingFile == NULL)
|
if (recordingFile == NULL)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (!key.fExistKey)
|
if (!key.fExistKey)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE;
|
long seek = GetBlockSeekPoint(frame) + RecordingBlockHeaderSize;
|
||||||
fseek(recordingFile, seek, SEEK_SET);
|
fseek(recordingFile, seek, SEEK_SET);
|
||||||
if (fwrite(key.buf, 1, BLOCK_DATA_SIZE, recordingFile) == 0)
|
if (fwrite(key.buf, 1, RecordingBlockDataSize, recordingFile) == 0)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
fflush(recordingFile);
|
fflush(recordingFile);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify header of recording file
|
// Verify header of recording file
|
||||||
bool InputRecordingFile::readHeaderAndCheck()
|
bool InputRecordingFile::ReadHeaderAndCheck()
|
||||||
{
|
{
|
||||||
if (recordingFile == NULL) return false;
|
if (recordingFile == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
rewind(recordingFile);
|
rewind(recordingFile);
|
||||||
if (fread(&header, sizeof(InputRecordingHeader), 1, recordingFile) != 1) return false;
|
if (fread(&header, sizeof(InputRecordingHeader), 1, recordingFile) != 1
|
||||||
if (fread(&MaxFrame, 4, 1, recordingFile) != 1) return false;
|
|| fread(&MaxFrame, 4, 1, recordingFile) != 1
|
||||||
if (fread(&UndoCount, 4, 1, recordingFile) != 1) return false;
|
|| fread(&UndoCount, 4, 1, recordingFile) != 1
|
||||||
if (fread(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1) return false;
|
|| fread(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1)
|
||||||
if (savestate.fromSavestate) {
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (savestate.fromSavestate)
|
||||||
|
{
|
||||||
FILE* ssFileCheck = wxFopen(filename + "_SaveState.p2s", "r");
|
FILE* ssFileCheck = wxFopen(filename + "_SaveState.p2s", "r");
|
||||||
if (ssFileCheck = NULL) {
|
if (ssFileCheck == NULL)
|
||||||
|
{
|
||||||
recordingConLog(wxString::Format("[REC]: Could not locate savestate file at location - %s\n", filename + "_SaveState.p2s"));
|
recordingConLog(wxString::Format("[REC]: Could not locate savestate file at location - %s\n", filename + "_SaveState.p2s"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fclose(ssFileCheck);
|
fclose(ssFileCheck);
|
||||||
StateCopy_LoadFromFile(filename + "_SaveState.p2s");
|
StateCopy_LoadFromFile(filename + "_SaveState.p2s");
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
sApp.SysExecute();
|
sApp.SysExecute();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for current verison
|
// Check for current verison
|
||||||
if (header.version != 1) {
|
if (header.version != 1)
|
||||||
|
{
|
||||||
recordingConLog(wxString::Format("[REC]: Input recording file is not a supported version - %d\n", header.version));
|
recordingConLog(wxString::Format("[REC]: Input recording file is not a supported version - %d\n", header.version));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool InputRecordingFile::writeHeader()
|
bool InputRecordingFile::WriteHeader()
|
||||||
{
|
{
|
||||||
if (recordingFile == NULL) return false;
|
if (recordingFile == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
rewind(recordingFile);
|
rewind(recordingFile);
|
||||||
if (fwrite(&header, sizeof(InputRecordingHeader), 1, recordingFile) != 1) return false;
|
if (fwrite(&header, sizeof(InputRecordingHeader), 1, recordingFile) != 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputRecordingFile::writeMaxFrame()
|
bool InputRecordingFile::WriteMaxFrame()
|
||||||
{
|
{
|
||||||
if (recordingFile == NULL)return false;
|
if (recordingFile == NULL)
|
||||||
fseek(recordingFile, SEEKPOINT_FRAMEMAX, SEEK_SET);
|
{
|
||||||
if (fwrite(&MaxFrame, 4, 1, recordingFile) != 1) return false;
|
return false;
|
||||||
|
}
|
||||||
|
fseek(recordingFile, RecordingSeekpointFrameMax, SEEK_SET);
|
||||||
|
if (fwrite(&MaxFrame, 4, 1, recordingFile) != 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputRecordingFile::updateFrameMax(unsigned long frame)
|
void InputRecordingFile::UpdateFrameMax(unsigned long frame)
|
||||||
{
|
{
|
||||||
if (MaxFrame >= frame) {
|
if (recordingFile == NULL || MaxFrame >= frame)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MaxFrame = frame;
|
MaxFrame = frame;
|
||||||
if (recordingFile == NULL)return ;
|
fseek(recordingFile, RecordingSeekpointFrameMax, SEEK_SET);
|
||||||
fseek(recordingFile, SEEKPOINT_FRAMEMAX, SEEK_SET);
|
|
||||||
fwrite(&MaxFrame, 4, 1, recordingFile);
|
fwrite(&MaxFrame, 4, 1, recordingFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputRecordingFile::addUndoCount()
|
void InputRecordingFile::AddUndoCount()
|
||||||
{
|
{
|
||||||
UndoCount++;
|
UndoCount++;
|
||||||
if (recordingFile == NULL)
|
if (recordingFile == NULL)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
fseek(recordingFile, SEEKPOINT_UNDOCOUNT, SEEK_SET);
|
}
|
||||||
|
fseek(recordingFile, RecordingSeekpointUndoCount, SEEK_SET);
|
||||||
fwrite(&UndoCount, 4, 1, recordingFile);
|
fwrite(&UndoCount, 4, 1, recordingFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputRecordingHeader::setAuthor(wxString _author)
|
void InputRecordingHeader::SetAuthor(wxString _author)
|
||||||
{
|
{
|
||||||
int max = ArraySize(author) - 1;
|
int max = ArraySize(author) - 1;
|
||||||
strncpy(author, _author.c_str(), max);
|
strncpy(author, _author.c_str(), max);
|
||||||
author[max] = 0;
|
author[max] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputRecordingHeader::setGameName(wxString _gameName)
|
void InputRecordingHeader::SetGameName(wxString _gameName)
|
||||||
{
|
{
|
||||||
int max = ArraySize(gameName) - 1;
|
int max = ArraySize(gameName) - 1;
|
||||||
strncpy(gameName, _gameName.c_str(), max);
|
strncpy(gameName, _gameName.c_str(), max);
|
||||||
gameName[max] = 0;
|
gameName[max] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputRecordingHeader::init()
|
void InputRecordingHeader::Init()
|
||||||
{
|
{
|
||||||
memset(author, 0, ArraySize(author));
|
memset(author, 0, ArraySize(author));
|
||||||
memset(gameName, 0, ArraySize(gameName));
|
memset(gameName, 0, ArraySize(gameName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InputRecordingHeader& InputRecordingFile::GetHeader()
|
||||||
|
{
|
||||||
|
return header; }
|
||||||
|
|
||||||
|
unsigned long& InputRecordingFile::GetMaxFrame()
|
||||||
|
{
|
||||||
|
return MaxFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long& InputRecordingFile::GetUndoCount()
|
||||||
|
{
|
||||||
|
return UndoCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wxString & InputRecordingFile::GetFilename()
|
||||||
|
{
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "PadData.h"
|
#include "PadData.h"
|
||||||
#include "System.h"
|
#include "System.h"
|
||||||
|
|
||||||
|
|
||||||
struct InputRecordingHeader
|
struct InputRecordingHeader
|
||||||
{
|
{
|
||||||
u8 version = 1;
|
u8 version = 1;
|
||||||
|
@ -26,11 +27,13 @@ struct InputRecordingHeader
|
||||||
char gameName[255] = "";
|
char gameName[255] = "";
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setAuthor(wxString author);
|
void SetAuthor(wxString author);
|
||||||
void setGameName(wxString cdrom);
|
void SetGameName(wxString cdrom);
|
||||||
void init();
|
void Init();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const int RecordingHeaderSize = sizeof(InputRecordingHeader) + 4 + 4;
|
||||||
|
|
||||||
// Contains info about the starting point of the movie
|
// Contains info about the starting point of the movie
|
||||||
struct InputRecordingSavestate
|
struct InputRecordingSavestate
|
||||||
{
|
{
|
||||||
|
@ -38,8 +41,8 @@ struct InputRecordingSavestate
|
||||||
bool fromSavestate = false;
|
bool fromSavestate = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class InputRecordingFile
|
||||||
class InputRecordingFile {
|
{
|
||||||
public:
|
public:
|
||||||
InputRecordingFile() {}
|
InputRecordingFile() {}
|
||||||
~InputRecordingFile() { Close(); }
|
~InputRecordingFile() { Close(); }
|
||||||
|
@ -47,38 +50,46 @@ public:
|
||||||
// Movie File Manipulation
|
// Movie File Manipulation
|
||||||
bool Open(const wxString fn, bool fNewOpen, bool fromSaveState);
|
bool Open(const wxString fn, bool fNewOpen, bool fromSaveState);
|
||||||
bool Close();
|
bool Close();
|
||||||
bool writeKeyBuf(const uint & frame, const uint port, const uint bufIndex, const u8 & buf);
|
bool WriteKeyBuf(const uint & frame, const uint port, const uint bufIndex, const u8 & buf);
|
||||||
bool readKeyBuf(u8 & result, const uint & frame, const uint port, const uint bufIndex);
|
bool ReadKeyBuf(u8 & result, const uint & frame, const uint port, const uint bufIndex);
|
||||||
|
|
||||||
// Controller Data
|
// Controller Data
|
||||||
void getPadData(PadData & result_pad, unsigned long frame);
|
void GetPadData(PadData & result_pad, unsigned long frame);
|
||||||
bool DeletePadData(unsigned long frame);
|
bool DeletePadData(unsigned long frame);
|
||||||
bool InsertPadData(unsigned long frame, const PadData& key);
|
bool InsertPadData(unsigned long frame, const PadData& key);
|
||||||
bool UpdatePadData(unsigned long frame, const PadData& key);
|
bool UpdatePadData(unsigned long frame, const PadData& key);
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
InputRecordingHeader& getHeader() { return header; }
|
InputRecordingHeader& GetHeader();
|
||||||
unsigned long& getMaxFrame() { return MaxFrame; }
|
unsigned long& GetMaxFrame();
|
||||||
unsigned long& getUndoCount() { return UndoCount; }
|
unsigned long& GetUndoCount();
|
||||||
const wxString & getFilename() { return filename; }
|
const wxString & GetFilename();
|
||||||
|
|
||||||
bool writeHeader();
|
bool WriteHeader();
|
||||||
bool writeMaxFrame();
|
bool WriteMaxFrame();
|
||||||
bool writeSaveState();
|
bool WriteSaveState();
|
||||||
|
|
||||||
bool readHeaderAndCheck();
|
bool ReadHeaderAndCheck();
|
||||||
void updateFrameMax(unsigned long frame);
|
void UpdateFrameMax(unsigned long frame);
|
||||||
void addUndoCount();
|
void AddUndoCount();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static const int RecordingSavestateHeaderSize = sizeof(bool);
|
||||||
|
static const int RecordingBlockHeaderSize = 0;
|
||||||
|
static const int RecordingBlockDataSize = 18 * 2;
|
||||||
|
static const int RecordingBlockSize = RecordingBlockHeaderSize + RecordingBlockDataSize;
|
||||||
|
static const int RecordingSeekpointFrameMax = sizeof(InputRecordingHeader);
|
||||||
|
static const int RecordingSeekpointUndoCount = sizeof(InputRecordingHeader) + 4;
|
||||||
|
static const int RecordingSeekpointSaveState = RecordingSeekpointUndoCount + 4;
|
||||||
|
|
||||||
// Movie File
|
// Movie File
|
||||||
FILE * recordingFile = NULL;
|
FILE * recordingFile = NULL;
|
||||||
wxString filename = "";
|
wxString filename = "";
|
||||||
long _getBlockSeekPoint(const long & frame);
|
long GetBlockSeekPoint(const long & frame);
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
InputRecordingHeader header;
|
InputRecordingHeader header;
|
||||||
InputRecordingSavestate savestate;
|
InputRecordingSavestate savestate;
|
||||||
unsigned long MaxFrame = 0;
|
unsigned long MaxFrame = 0;
|
||||||
unsigned long UndoCount = 0;
|
unsigned long UndoCount = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2019 PCSX2 Dev Team
|
|
||||||
*
|
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
||||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
||||||
* ation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
|
||||||
|
|
||||||
#include "NewRecordingFrame.h"
|
|
||||||
|
|
||||||
enum {
|
|
||||||
File,
|
|
||||||
Author,
|
|
||||||
From
|
|
||||||
};
|
|
||||||
|
|
||||||
NewRecordingFrame::NewRecordingFrame(wxWindow *parent)
|
|
||||||
: wxDialog(parent, wxID_ANY, "New Input Recording", wxDefaultPosition, wxDefaultSize, wxSTAY_ON_TOP | wxCAPTION)
|
|
||||||
{
|
|
||||||
wxPanel *panel = new wxPanel(this, wxID_ANY,
|
|
||||||
wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _("panel"));
|
|
||||||
|
|
||||||
wxFlexGridSizer *fgs = new wxFlexGridSizer(4, 2, 20, 20);
|
|
||||||
wxBoxSizer *container = new wxBoxSizer(wxVERTICAL);
|
|
||||||
|
|
||||||
m_fileLabel = new wxStaticText(panel, wxID_ANY, _("File Path"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
|
||||||
m_authorLabel = new wxStaticText(panel, wxID_ANY, _("Author"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
|
||||||
m_fromLabel = new wxStaticText(panel, wxID_ANY, _("Record From"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
|
||||||
|
|
||||||
m_filePicker = new wxFilePickerCtrl(panel, File, wxEmptyString, "File", L"p2m2 file(*.p2m2)|*.p2m2", wxDefaultPosition, wxDefaultSize, wxFLP_SAVE | wxFLP_OVERWRITE_PROMPT | wxFLP_USE_TEXTCTRL);
|
|
||||||
m_authorInput = new wxTextCtrl(panel, Author, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
|
|
||||||
wxArrayString choices;
|
|
||||||
choices.Add("Current Frame");
|
|
||||||
choices.Add("Power-On");
|
|
||||||
m_fromChoice = new wxChoice(panel, From, wxDefaultPosition, wxDefaultSize, choices);
|
|
||||||
m_fromChoice->SetSelection(0);
|
|
||||||
|
|
||||||
m_startRecording = new wxButton(panel, wxID_OK, _("Ok"), wxDefaultPosition, wxDefaultSize);
|
|
||||||
m_cancelRecording = new wxButton(panel, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize);
|
|
||||||
|
|
||||||
fgs->Add(m_fileLabel, 1);
|
|
||||||
fgs->Add(m_filePicker, 1);
|
|
||||||
|
|
||||||
fgs->Add(m_authorLabel, 1);
|
|
||||||
fgs->Add(m_authorInput, 1, wxEXPAND);
|
|
||||||
|
|
||||||
fgs->Add(m_fromLabel, 1);
|
|
||||||
fgs->Add(m_fromChoice, 1, wxEXPAND);
|
|
||||||
|
|
||||||
fgs->Add(m_startRecording, 1);
|
|
||||||
fgs->Add(m_cancelRecording, 1);
|
|
||||||
|
|
||||||
container->Add(fgs, 1, wxALL | wxEXPAND, 15);
|
|
||||||
panel->SetSizer(container);
|
|
||||||
panel->GetSizer()->Fit(this);
|
|
||||||
Centre();
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString NewRecordingFrame::getFile() const
|
|
||||||
{
|
|
||||||
return m_filePicker->GetPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString NewRecordingFrame::getAuthor() const
|
|
||||||
{
|
|
||||||
return m_authorInput->GetValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
int NewRecordingFrame::getFrom() const
|
|
||||||
{
|
|
||||||
return m_fromChoice->GetSelection();
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2019 PCSX2 Dev Team
|
|
||||||
*
|
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
||||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
||||||
* ation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <wx/wx.h>
|
|
||||||
#include <wx/filepicker.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The Dialog to pop-up when recording a new movie
|
|
||||||
*/
|
|
||||||
class NewRecordingFrame : public wxDialog
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NewRecordingFrame(wxWindow *parent);
|
|
||||||
|
|
||||||
wxString getFile() const;
|
|
||||||
wxString getAuthor() const;
|
|
||||||
int getFrom() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
wxStaticText *m_fileLabel;
|
|
||||||
wxFilePickerCtrl *m_filePicker;
|
|
||||||
wxStaticText *m_authorLabel;
|
|
||||||
wxTextCtrl *m_authorInput;
|
|
||||||
wxStaticText *m_fromLabel;
|
|
||||||
wxChoice *m_fromChoice;
|
|
||||||
wxButton *m_startRecording;
|
|
||||||
wxButton *m_cancelRecording;
|
|
||||||
};
|
|
||||||
|
|
|
@ -17,17 +17,11 @@
|
||||||
|
|
||||||
#include "NewRecordingFrame.h"
|
#include "NewRecordingFrame.h"
|
||||||
|
|
||||||
enum {
|
|
||||||
File,
|
|
||||||
Author,
|
|
||||||
From
|
|
||||||
};
|
|
||||||
|
|
||||||
NewRecordingFrame::NewRecordingFrame(wxWindow *parent)
|
NewRecordingFrame::NewRecordingFrame(wxWindow *parent)
|
||||||
: wxDialog(parent, wxID_ANY, "New Input Recording", wxDefaultPosition, wxDefaultSize, wxSTAY_ON_TOP | wxCAPTION)
|
: wxDialog(parent, wxID_ANY, "New Input Recording", wxDefaultPosition, wxDefaultSize, wxSTAY_ON_TOP | wxCAPTION)
|
||||||
{
|
{
|
||||||
wxPanel *panel = new wxPanel(this, wxID_ANY,
|
wxPanel *panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _("panel"));
|
||||||
wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _("panel"));
|
|
||||||
|
|
||||||
wxFlexGridSizer *fgs = new wxFlexGridSizer(4, 2, 20, 20);
|
wxFlexGridSizer *fgs = new wxFlexGridSizer(4, 2, 20, 20);
|
||||||
wxBoxSizer *container = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer *container = new wxBoxSizer(wxVERTICAL);
|
||||||
|
@ -36,12 +30,12 @@ NewRecordingFrame::NewRecordingFrame(wxWindow *parent)
|
||||||
m_authorLabel = new wxStaticText(panel, wxID_ANY, _("Author"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
m_authorLabel = new wxStaticText(panel, wxID_ANY, _("Author"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
||||||
m_fromLabel = new wxStaticText(panel, wxID_ANY, _("Record From"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
m_fromLabel = new wxStaticText(panel, wxID_ANY, _("Record From"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
||||||
|
|
||||||
m_filePicker = new wxFilePickerCtrl(panel, File, wxEmptyString, "File", L"p2m2 file(*.p2m2)|*.p2m2", wxDefaultPosition, wxDefaultSize, wxFLP_SAVE | wxFLP_OVERWRITE_PROMPT | wxFLP_USE_TEXTCTRL);
|
m_filePicker = new wxFilePickerCtrl(panel, MenuIds_New_Recording_Frame_File, wxEmptyString, "File", L"p2m2 file(*.p2m2)|*.p2m2", wxDefaultPosition, wxDefaultSize, wxFLP_SAVE | wxFLP_OVERWRITE_PROMPT | wxFLP_USE_TEXTCTRL);
|
||||||
m_authorInput = new wxTextCtrl(panel, Author, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
|
m_authorInput = new wxTextCtrl(panel, MenuIds_New_Recording_Frame_Author, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
|
||||||
wxArrayString choices;
|
wxArrayString choices;
|
||||||
choices.Add("Current Frame");
|
choices.Add("Current Frame");
|
||||||
choices.Add("Power-On");
|
choices.Add("Power-On");
|
||||||
m_fromChoice = new wxChoice(panel, From, wxDefaultPosition, wxDefaultSize, choices);
|
m_fromChoice = new wxChoice(panel, MenuIds_New_Recording_Frame_From, wxDefaultPosition, wxDefaultSize, choices);
|
||||||
m_fromChoice->SetSelection(0);
|
m_fromChoice->SetSelection(0);
|
||||||
|
|
||||||
m_startRecording = new wxButton(panel, wxID_OK, _("Ok"), wxDefaultPosition, wxDefaultSize);
|
m_startRecording = new wxButton(panel, wxID_OK, _("Ok"), wxDefaultPosition, wxDefaultSize);
|
||||||
|
@ -65,17 +59,17 @@ NewRecordingFrame::NewRecordingFrame(wxWindow *parent)
|
||||||
Centre();
|
Centre();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString NewRecordingFrame::getFile() const
|
wxString NewRecordingFrame::GetFile() const
|
||||||
{
|
{
|
||||||
return m_filePicker->GetPath();
|
return m_filePicker->GetPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString NewRecordingFrame::getAuthor() const
|
wxString NewRecordingFrame::GetAuthor() const
|
||||||
{
|
{
|
||||||
return m_authorInput->GetValue();
|
return m_authorInput->GetValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
int NewRecordingFrame::getFrom() const
|
int NewRecordingFrame::GetFrom() const
|
||||||
{
|
{
|
||||||
return m_fromChoice->GetSelection();
|
return m_fromChoice->GetSelection();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,17 +18,23 @@
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
#include <wx/filepicker.h>
|
#include <wx/filepicker.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* The Dialog to pop-up when recording a new movie
|
enum MenuIds_New_Recording_Frame
|
||||||
*/
|
{
|
||||||
|
MenuIds_New_Recording_Frame_File = 0,
|
||||||
|
MenuIds_New_Recording_Frame_Author,
|
||||||
|
MenuIds_New_Recording_Frame_From
|
||||||
|
};
|
||||||
|
|
||||||
|
// The Dialog to pop-up when recording a new movie
|
||||||
class NewRecordingFrame : public wxDialog
|
class NewRecordingFrame : public wxDialog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NewRecordingFrame(wxWindow *parent);
|
NewRecordingFrame(wxWindow *parent);
|
||||||
|
|
||||||
wxString getFile() const;
|
wxString GetFile() const;
|
||||||
wxString getAuthor() const;
|
wxString GetAuthor() const;
|
||||||
int getFrom() const;
|
int GetFrom() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxStaticText *m_fileLabel;
|
wxStaticText *m_fileLabel;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "ConsoleLogger.h"
|
#include "ConsoleLogger.h"
|
||||||
#include "PadData.h"
|
#include "PadData.h"
|
||||||
|
|
||||||
|
|
||||||
PadData::PadData()
|
PadData::PadData()
|
||||||
{
|
{
|
||||||
// TODO - multi-tap support eventually?
|
// TODO - multi-tap support eventually?
|
||||||
|
@ -33,7 +34,7 @@ PadData::PadData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PadData::logPadData(u8 port, u16 bufCount, u8 buf[512]) {
|
void PadData::LogPadData(u8 port, u16 bufCount, u8 buf[512]) {
|
||||||
// skip first two bytes because they dont seem to matter
|
// skip first two bytes because they dont seem to matter
|
||||||
if (port == 0 && bufCount > 2)
|
if (port == 0 && bufCount > 2)
|
||||||
{
|
{
|
||||||
|
@ -54,30 +55,33 @@ void PadData::logPadData(u8 port, u16 bufCount, u8 buf[512]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int* PadData::getNormalButtons(int port) const
|
std::vector<int> PadData::GetNormalButtons(int port) const
|
||||||
{
|
{
|
||||||
int buttons[PadDataNormalButtonCount];
|
std::vector<int> buttons(PadDataNormalButtonCount);
|
||||||
for (int i = 0; i < PadDataNormalButtonCount; i++)
|
for (int i = 0; i < PadDataNormalButtonCount; i++)
|
||||||
{
|
{
|
||||||
buttons[i] = getNormalButton(port, PadDataNormalButton(i));
|
buttons[i] = GetNormalButton(port, PadData_NormalButton(i));
|
||||||
}
|
}
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
void PadData::setNormalButtons(int port, int* buttons)
|
|
||||||
|
void PadData::SetNormalButtons(int port, std::vector<int> buttons)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < PadDataNormalButtonCount; i++)
|
for (int i = 0; i < PadDataNormalButtonCount; i++)
|
||||||
{
|
{
|
||||||
setNormalButton(port, PadDataNormalButton(i), buttons[i]);
|
SetNormalButton(port, PadData_NormalButton(i), buttons[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PadData::setNormalButton(int port, PadDataNormalButton button, int fpushed)
|
void PadData::SetNormalButton(int port, PadData_NormalButton button, int fpushed)
|
||||||
{
|
{
|
||||||
if (port < 0 || 1 < port)
|
if (port < 0 || 1 < port)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
wxByte keybit[2];
|
wxByte keybit[2];
|
||||||
getKeyBit(keybit, button);
|
GetKeyBit(keybit, button);
|
||||||
int pressureByteIndex = getPressureByte(button);
|
int pressureByteIndex = GetPressureByte(button);
|
||||||
|
|
||||||
if (fpushed > 0)
|
if (fpushed > 0)
|
||||||
{
|
{
|
||||||
|
@ -104,13 +108,15 @@ void PadData::setNormalButton(int port, PadDataNormalButton button, int fpushed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int PadData::getNormalButton(int port, PadDataNormalButton button) const
|
int PadData::GetNormalButton(int port, PadData_NormalButton button) const
|
||||||
{
|
{
|
||||||
if (port < 0 || 1 < port)
|
if (port < 0 || 1 < port)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
wxByte keybit[2];
|
wxByte keybit[2];
|
||||||
getKeyBit(keybit, button);
|
GetKeyBit(keybit, button);
|
||||||
int pressureByteIndex = getPressureByte(button);
|
int pressureByteIndex = GetPressureByte(button);
|
||||||
|
|
||||||
// If the button is pressed on either controller
|
// If the button is pressed on either controller
|
||||||
bool f1 = (~buf[port][0] & keybit[0])>0;
|
bool f1 = (~buf[port][0] & keybit[0])>0;
|
||||||
|
@ -132,110 +138,195 @@ int PadData::getNormalButton(int port, PadDataNormalButton button) const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PadData::getKeyBit(wxByte keybit[2], PadDataNormalButton button) const
|
void PadData::GetKeyBit(wxByte keybit[2], PadData_NormalButton button) const
|
||||||
{
|
{
|
||||||
if (button == UP) { keybit[0] = 0b00010000; keybit[1] = 0b00000000; }
|
switch (button)
|
||||||
else if (button == LEFT) { keybit[0] = 0b10000000; keybit[1] = 0b00000000; }
|
{
|
||||||
else if (button == RIGHT) { keybit[0] = 0b00100000; keybit[1] = 0b00000000; }
|
case PadData_NormalButton_LEFT:
|
||||||
else if (button == DOWN) { keybit[0] = 0b01000000; keybit[1] = 0b00000000; }
|
keybit[0] = 0b10000000;
|
||||||
else if (button == START) { keybit[0] = 0b00001000; keybit[1] = 0b00000000; }
|
keybit[1] = 0b00000000;
|
||||||
else if (button == SELECT) { keybit[0] = 0b00000001; keybit[1] = 0b00000000; }
|
break;
|
||||||
else if (button == CROSS) { keybit[0] = 0b00000000; keybit[1] = 0b01000000; }
|
case PadData_NormalButton_DOWN:
|
||||||
else if (button == CIRCLE) { keybit[0] = 0b00000000; keybit[1] = 0b00100000; }
|
keybit[0] = 0b01000000;
|
||||||
else if (button == SQUARE) { keybit[0] = 0b00000000; keybit[1] = 0b10000000; }
|
keybit[1] = 0b00000000;
|
||||||
else if (button == TRIANGLE) { keybit[0] = 0b00000000; keybit[1] = 0b00010000; }
|
break;
|
||||||
else if (button == L1) { keybit[0] = 0b00000000; keybit[1] = 0b00000100; }
|
case PadData_NormalButton_RIGHT:
|
||||||
else if (button == L2) { keybit[0] = 0b00000000; keybit[1] = 0b00000001; }
|
keybit[0] = 0b00100000;
|
||||||
else if (button == L3) { keybit[0] = 0b00000010; keybit[1] = 0b00000000; }
|
keybit[1] = 0b00000000;
|
||||||
else if (button == R1) { keybit[0] = 0b00000000; keybit[1] = 0b00001000; }
|
break;
|
||||||
else if (button == R2) { keybit[0] = 0b00000000; keybit[1] = 0b00000010; }
|
case PadData_NormalButton_UP:
|
||||||
else if (button == R3) { keybit[0] = 0b00000100; keybit[1] = 0b00000000; }
|
keybit[0] = 0b00010000;
|
||||||
else { keybit[0] = 0; keybit[1] = 0; }
|
keybit[1] = 0b00000000;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_START:
|
||||||
|
keybit[0] = 0b00001000;
|
||||||
|
keybit[1] = 0b00000000;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_R3:
|
||||||
|
keybit[0] = 0b00000100;
|
||||||
|
keybit[1] = 0b00000000;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_L3:
|
||||||
|
keybit[0] = 0b00000010;
|
||||||
|
keybit[1] = 0b00000000;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_SELECT:
|
||||||
|
keybit[0] = 0b00000001;
|
||||||
|
keybit[1] = 0b00000000;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_SQUARE:
|
||||||
|
keybit[0] = 0b00000000;
|
||||||
|
keybit[1] = 0b10000000;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_CROSS:
|
||||||
|
keybit[0] = 0b00000000;
|
||||||
|
keybit[1] = 0b01000000;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_CIRCLE:
|
||||||
|
keybit[0] = 0b00000000;
|
||||||
|
keybit[1] = 0b00100000;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_TRIANGLE:
|
||||||
|
keybit[0] = 0b00000000;
|
||||||
|
keybit[1] = 0b00010000;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_R1:
|
||||||
|
keybit[0] = 0b00000000;
|
||||||
|
keybit[1] = 0b00001000;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_L1:
|
||||||
|
keybit[0] = 0b00000000;
|
||||||
|
keybit[1] = 0b00000100;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_R2:
|
||||||
|
keybit[0] = 0b00000000;
|
||||||
|
keybit[1] = 0b00000010;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_L2:
|
||||||
|
keybit[0] = 0b00000000;
|
||||||
|
keybit[1] = 0b00000001;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
keybit[0] = 0;
|
||||||
|
keybit[1] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an index for the buffer to set the pressure byte
|
// Returns an index for the buffer to set the pressure byte
|
||||||
// Returns -1 if it is a button that does not support pressure sensitivty
|
// Returns -1 if it is a button that does not support pressure sensitivty
|
||||||
int PadData::getPressureByte(PadDataNormalButton button) const
|
int PadData::GetPressureByte(PadData_NormalButton button) const
|
||||||
{
|
{
|
||||||
// Pressure Byte Order
|
// Pressure Byte Order
|
||||||
// R - L - U - D - Tri - Sqr - Circle - Cross - L1 - R1 - L2 - R2
|
// R - L - U - D - Tri - Circle - Cross - Sqr - L1 - R1 - L2 - R2
|
||||||
if (button == UP)
|
switch (button)
|
||||||
return 2;
|
{
|
||||||
else if (button == LEFT)
|
case PadData_NormalButton_RIGHT:
|
||||||
return 1;
|
return 0;
|
||||||
else if (button == RIGHT)
|
break;
|
||||||
return 0;
|
case PadData_NormalButton_LEFT:
|
||||||
else if (button == DOWN)
|
return 1;
|
||||||
return 3;
|
break;
|
||||||
else if (button == CROSS)
|
case PadData_NormalButton_UP:
|
||||||
return 6;
|
return 2;
|
||||||
else if (button == CIRCLE)
|
break;
|
||||||
return 5;
|
case PadData_NormalButton_DOWN:
|
||||||
else if (button == SQUARE)
|
return 3;
|
||||||
return 7;
|
break;
|
||||||
else if (button == TRIANGLE)
|
case PadData_NormalButton_TRIANGLE:
|
||||||
return 4;
|
return 4;
|
||||||
else if (button == L1)
|
break;
|
||||||
return 8;
|
case PadData_NormalButton_CIRCLE:
|
||||||
else if (button == L2)
|
return 5;
|
||||||
return 10;
|
break;
|
||||||
else if (button == R1)
|
case PadData_NormalButton_CROSS:
|
||||||
return 9;
|
return 6;
|
||||||
else if (button == R2)
|
break;
|
||||||
return 11;
|
case PadData_NormalButton_SQUARE:
|
||||||
else
|
return 7;
|
||||||
return -1;
|
break;
|
||||||
|
case PadData_NormalButton_L1:
|
||||||
|
return 8;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_R1:
|
||||||
|
return 9;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_L2:
|
||||||
|
return 10;
|
||||||
|
break;
|
||||||
|
case PadData_NormalButton_R2:
|
||||||
|
return 11;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int* PadData::getAnalogVectors(int port) const
|
std::vector<int> PadData::GetAnalogVectors(int port) const
|
||||||
{
|
{
|
||||||
int vectors[PadDataAnalogVectorCount];
|
std::vector<int> vectors(PadDataAnalogVectorCount);
|
||||||
for (int i = 0; i < PadDataAnalogVectorCount; i++)
|
for (int i = 0; i < PadDataAnalogVectorCount; i++)
|
||||||
{
|
{
|
||||||
vectors[i] = getAnalogVector(port, PadDataAnalogVector(i));
|
vectors[i] = GetAnalogVector(port, PadData_AnalogVector(i));
|
||||||
}
|
}
|
||||||
return vectors;
|
return vectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PadData::setAnalogVectors(int port, int* vectors)
|
void PadData::SetAnalogVectors(int port, std::vector<int> vectors)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < PadDataAnalogVectorCount; i++)
|
for (int i = 0; i < PadDataAnalogVectorCount; i++)
|
||||||
{
|
{
|
||||||
setAnalogVector(port, PadDataAnalogVector(i), vectors[i]);
|
SetAnalogVector(port, PadData_AnalogVector(i), vectors[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PadData::setAnalogVector(int port, PadDataAnalogVector vector, int val)
|
void PadData::SetAnalogVector(int port, PadData_AnalogVector vector, int val)
|
||||||
{
|
{
|
||||||
if (port < 0 || 1 < port)
|
if (port < 0 || 1 < port)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
|
{
|
||||||
val = 0;
|
val = 0;
|
||||||
|
}
|
||||||
else if (val > 255)
|
else if (val > 255)
|
||||||
|
{
|
||||||
val = 255;
|
val = 255;
|
||||||
|
}
|
||||||
|
|
||||||
buf[port][getAnalogVectorByte(vector)] = val;
|
buf[port][GetAnalogVectorByte(vector)] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PadData::getAnalogVector(int port, PadDataAnalogVector vector) const
|
int PadData::GetAnalogVector(int port, PadData_AnalogVector vector) const
|
||||||
{
|
{
|
||||||
if (port < 0 || 1 < port)
|
if (port < 0 || 1 < port)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return buf[port][getAnalogVectorByte(vector)];
|
return buf[port][GetAnalogVectorByte(vector)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an index for the buffer to set the analog's vector
|
// Returns an index for the buffer to set the analog's vector
|
||||||
int PadData::getAnalogVectorByte(PadDataAnalogVector vector) const
|
int PadData::GetAnalogVectorByte(PadData_AnalogVector vector) const
|
||||||
{
|
{
|
||||||
// Vector Byte Ordering
|
// Vector Byte Ordering
|
||||||
// RX - RY - LX - LY
|
// RX - RY - LX - LY
|
||||||
if (vector == LEFT_ANALOG_X)
|
switch (vector)
|
||||||
return 4;
|
{
|
||||||
else if (vector == LEFT_ANALOG_Y)
|
case PadData_AnalogVector_RIGHT_ANALOG_X:
|
||||||
return 5;
|
return 2;
|
||||||
else if (vector == RIGHT_ANALOG_X)
|
break;
|
||||||
return 2;
|
case PadData_AnalogVector_RIGHT_ANALOG_Y:
|
||||||
else
|
return 3;
|
||||||
return 3;
|
break;
|
||||||
|
case PadData_AnalogVector_LEFT_ANALOG_X:
|
||||||
|
return 4;
|
||||||
|
break;
|
||||||
|
case PadData_AnalogVector_LEFT_ANALOG_Y:
|
||||||
|
return 5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,35 +16,37 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#define PadDataNormalButtonCount 16
|
|
||||||
enum PadDataNormalButton
|
static const int PadDataNormalButtonCount = 16;
|
||||||
|
enum PadData_NormalButton
|
||||||
{
|
{
|
||||||
UP,
|
PadData_NormalButton_UP,
|
||||||
RIGHT,
|
PadData_NormalButton_RIGHT,
|
||||||
LEFT,
|
PadData_NormalButton_LEFT,
|
||||||
DOWN,
|
PadData_NormalButton_DOWN,
|
||||||
CROSS,
|
PadData_NormalButton_CROSS,
|
||||||
CIRCLE,
|
PadData_NormalButton_CIRCLE,
|
||||||
SQUARE,
|
PadData_NormalButton_SQUARE,
|
||||||
TRIANGLE,
|
PadData_NormalButton_TRIANGLE,
|
||||||
L1,
|
PadData_NormalButton_L1,
|
||||||
L2,
|
PadData_NormalButton_L2,
|
||||||
R1,
|
PadData_NormalButton_R1,
|
||||||
R2,
|
PadData_NormalButton_R2,
|
||||||
L3,
|
PadData_NormalButton_L3,
|
||||||
R3,
|
PadData_NormalButton_R3,
|
||||||
SELECT,
|
PadData_NormalButton_SELECT,
|
||||||
START
|
PadData_NormalButton_START
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PadDataAnalogVectorCount 4
|
static const int PadDataAnalogVectorCount = 4;
|
||||||
enum PadDataAnalogVector
|
enum PadData_AnalogVector
|
||||||
{
|
{
|
||||||
LEFT_ANALOG_X,
|
PadData_AnalogVector_LEFT_ANALOG_X,
|
||||||
LEFT_ANALOG_Y,
|
PadData_AnalogVector_LEFT_ANALOG_Y,
|
||||||
RIGHT_ANALOG_X,
|
PadData_AnalogVector_RIGHT_ANALOG_X,
|
||||||
RIGHT_ANALOG_Y
|
PadData_AnalogVector_RIGHT_ANALOG_Y
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PadData
|
struct PadData
|
||||||
|
@ -57,29 +59,29 @@ public:
|
||||||
u8 buf[2][18];
|
u8 buf[2][18];
|
||||||
|
|
||||||
// Prints controlller data every frame to the Controller Log filter, disabled by default
|
// Prints controlller data every frame to the Controller Log filter, disabled by default
|
||||||
static void logPadData(u8 port, u16 bufCount, u8 buf[512]);
|
static void LogPadData(u8 port, u16 bufCount, u8 buf[512]);
|
||||||
|
|
||||||
// Normal Buttons
|
// Normal Buttons
|
||||||
int* getNormalButtons(int port) const;
|
std::vector<int> GetNormalButtons(int port) const;
|
||||||
void setNormalButtons(int port, int* buttons);
|
void SetNormalButtons(int port, std::vector<int> buttons);
|
||||||
|
|
||||||
// Analog Vectors
|
// Analog Vectors
|
||||||
// max left/up : 0
|
// max left/up : 0
|
||||||
// neutral : 127
|
// neutral : 127
|
||||||
// max right/down : 255
|
// max right/down : 255
|
||||||
int* getAnalogVectors(int port) const;
|
std::vector<int> GetAnalogVectors(int port) const;
|
||||||
// max left/up : 0
|
// max left/up : 0
|
||||||
// neutral : 127
|
// neutral : 127
|
||||||
// max right/down : 255
|
// max right/down : 255
|
||||||
void setAnalogVectors(int port, int* vector);
|
void SetAnalogVectors(int port, std::vector<int> vector);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setNormalButton(int port, PadDataNormalButton button, int pressure);
|
void SetNormalButton(int port, PadData_NormalButton button, int pressure);
|
||||||
int getNormalButton(int port, PadDataNormalButton button) const;
|
int GetNormalButton(int port, PadData_NormalButton button) const;
|
||||||
void getKeyBit(wxByte keybit[2], PadDataNormalButton button) const;
|
void GetKeyBit(wxByte keybit[2], PadData_NormalButton button) const;
|
||||||
int getPressureByte(PadDataNormalButton button) const;
|
int GetPressureByte(PadData_NormalButton button) const;
|
||||||
|
|
||||||
void setAnalogVector(int port, PadDataAnalogVector vector, int val);
|
void SetAnalogVector(int port, PadData_AnalogVector vector, int val);
|
||||||
int getAnalogVector(int port, PadDataAnalogVector vector) const;
|
int GetAnalogVector(int port, PadData_AnalogVector vector) const;
|
||||||
int getAnalogVectorByte(PadDataAnalogVector vector) const;
|
int GetAnalogVectorByte(PadData_AnalogVector vector) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,32 +15,31 @@
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
#include "GSFrame.h"
|
|
||||||
|
|
||||||
#include "MemoryTypes.h"
|
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
#include "Counters.h"
|
#include "Counters.h"
|
||||||
|
#include "GSFrame.h"
|
||||||
|
#include "MemoryTypes.h"
|
||||||
|
|
||||||
#include "RecordingControls.h"
|
#include "RecordingControls.h"
|
||||||
|
|
||||||
|
|
||||||
RecordingControls g_RecordingControls;
|
RecordingControls g_RecordingControls;
|
||||||
|
|
||||||
// TODO - I think these functions could be named a lot better...
|
|
||||||
|
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
// Status on whether or not the current recording is stopped
|
// Status on whether or not the current recording is stopped
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
bool RecordingControls::isStop()
|
bool RecordingControls::HasRecordingStopped()
|
||||||
{
|
{
|
||||||
return (fPauseState && CoreThread.IsOpen() && CoreThread.IsPaused());
|
return (fPauseState && CoreThread.IsOpen() && CoreThread.IsPaused());
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
// Called after inputs are recorded for that frame, places lock on input recording, effectively releasing resources and resuming CoreThread.
|
// Called after inputs are recorded for that frame, places lock on input recording, effectively releasing resources and resuming CoreThread.
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
void RecordingControls::StartCheck()
|
void RecordingControls::ResumeCoreThreadIfStarted()
|
||||||
{
|
{
|
||||||
if (fStart && CoreThread.IsOpen() && CoreThread.IsPaused()) {
|
if (fStart && CoreThread.IsOpen() && CoreThread.IsPaused())
|
||||||
|
{
|
||||||
CoreThread.Resume();
|
CoreThread.Resume();
|
||||||
fStart = false;
|
fStart = false;
|
||||||
fPauseState = false;
|
fPauseState = false;
|
||||||
|
@ -51,10 +50,12 @@ void RecordingControls::StartCheck()
|
||||||
// Called at VSYNC End / VRender Begin, updates everything recording related for the next frame,
|
// Called at VSYNC End / VRender Begin, updates everything recording related for the next frame,
|
||||||
// toggles RecordingControl flags back to enable input recording for the next frame.
|
// toggles RecordingControl flags back to enable input recording for the next frame.
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
void RecordingControls::StopCheck()
|
void RecordingControls::HandleFrameAdvanceAndStop()
|
||||||
{
|
{
|
||||||
if (fFrameAdvance) {
|
if (fFrameAdvance)
|
||||||
if (stopFrameCount < g_FrameCount) {
|
{
|
||||||
|
if (stopFrameCount < g_FrameCount)
|
||||||
|
{
|
||||||
fFrameAdvance = false;
|
fFrameAdvance = false;
|
||||||
fStop = true;
|
fStop = true;
|
||||||
stopFrameCount = g_FrameCount;
|
stopFrameCount = g_FrameCount;
|
||||||
|
@ -80,11 +81,11 @@ void RecordingControls::StopCheck()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RecordingControls::GetStopFlag()
|
||||||
|
{
|
||||||
|
return (fStop || fFrameAdvance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------
|
|
||||||
// shortcut key
|
|
||||||
//----------------------------------
|
|
||||||
void RecordingControls::FrameAdvance()
|
void RecordingControls::FrameAdvance()
|
||||||
{
|
{
|
||||||
stopFrameCount = g_FrameCount;
|
stopFrameCount = g_FrameCount;
|
||||||
|
@ -92,22 +93,25 @@ void RecordingControls::FrameAdvance()
|
||||||
fStop = false;
|
fStop = false;
|
||||||
fStart = true;
|
fStart = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordingControls::TogglePause()
|
void RecordingControls::TogglePause()
|
||||||
{
|
{
|
||||||
fStop = !fStop;
|
fStop = !fStop;
|
||||||
if (fStop == false) {
|
if (fStop == false)
|
||||||
|
{
|
||||||
fStart = true;
|
fStart = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordingControls::Pause()
|
void RecordingControls::Pause()
|
||||||
{
|
{
|
||||||
fStop = true;
|
fStop = true;
|
||||||
fFrameAdvance = true;
|
fFrameAdvance = true;
|
||||||
}
|
}
|
||||||
void RecordingControls::UnPause()
|
|
||||||
|
void RecordingControls::Unpause()
|
||||||
{
|
{
|
||||||
fStop = false;
|
fStop = false;
|
||||||
fStart = true;
|
fStart = true;
|
||||||
fFrameAdvance = true;
|
fFrameAdvance = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
class RecordingControls {
|
class RecordingControls
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Movie controls main functions
|
// Movie controls main functions
|
||||||
bool isStop();
|
bool HasRecordingStopped();
|
||||||
void StartCheck();
|
void ResumeCoreThreadIfStarted();
|
||||||
void StopCheck();
|
void HandleFrameAdvanceAndStop();
|
||||||
|
|
||||||
// Shortcut Keys
|
// Shortcut Keys
|
||||||
void FrameAdvance();
|
void FrameAdvance();
|
||||||
|
@ -29,10 +30,10 @@ public:
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
void Pause();
|
void Pause();
|
||||||
void UnPause();
|
void Unpause();
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
bool getStopFlag() { return (fStop || fFrameAdvance); }
|
bool GetStopFlag();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint stopFrameCount = false;
|
uint stopFrameCount = false;
|
||||||
|
@ -43,4 +44,5 @@ private:
|
||||||
bool fPauseState = false;
|
bool fPauseState = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern RecordingControls g_RecordingControls;
|
extern RecordingControls g_RecordingControls;
|
||||||
|
|
|
@ -18,18 +18,23 @@
|
||||||
#include "RecordingInputManager.h"
|
#include "RecordingInputManager.h"
|
||||||
#include "InputRecording.h"
|
#include "InputRecording.h"
|
||||||
|
|
||||||
|
|
||||||
RecordingInputManager g_RecordingInput;
|
RecordingInputManager g_RecordingInput;
|
||||||
|
|
||||||
RecordingInputManager::RecordingInputManager()
|
RecordingInputManager::RecordingInputManager()
|
||||||
{
|
{
|
||||||
for (u8 i = 0; i < 2; i++)
|
for (u8 i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
virtualPad[i] = false;
|
virtualPad[i] = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordingInputManager::ControllerInterrupt(u8 & data, u8 & port, u16 & BufCount, u8 buf[])
|
void RecordingInputManager::ControllerInterrupt(u8 & data, u8 & port, u16 & BufCount, u8 buf[])
|
||||||
{
|
{
|
||||||
if (port >= 2)
|
if (port >= 2)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (virtualPad[port])
|
if (virtualPad[port])
|
||||||
{
|
{
|
||||||
|
@ -37,36 +42,44 @@ void RecordingInputManager::ControllerInterrupt(u8 & data, u8 & port, u16 & BufC
|
||||||
// first two bytes have nothing of interest in the buffer
|
// first two bytes have nothing of interest in the buffer
|
||||||
// already handled by InputRecording.cpp
|
// already handled by InputRecording.cpp
|
||||||
if (BufCount < 3)
|
if (BufCount < 3)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Normal keys
|
// Normal keys
|
||||||
// We want to perform an OR, but, since 255 means that no button is pressed and 0 that every button is pressed (and by De Morgan's Laws), we execute an AND.
|
// We want to perform an OR, but, since 255 means that no button is pressed and 0 that every button is pressed (and by De Morgan's Laws), we execute an AND.
|
||||||
if (BufCount <= 4)
|
if (BufCount <= 4)
|
||||||
buf[BufCount] = buf[BufCount] & pad.buf[port][BufCount - 3];
|
{
|
||||||
|
buf[BufCount] = buf[BufCount] & pad.buf[port][bufIndex];
|
||||||
|
}
|
||||||
// Analog keys (! overrides !)
|
// Analog keys (! overrides !)
|
||||||
else if ((BufCount > 4 && BufCount <= 6) && pad.buf[port][BufCount - 3] != 127)
|
else if ((BufCount > 4 && BufCount <= 6) && pad.buf[port][bufIndex] != 127)
|
||||||
buf[BufCount] = pad.buf[port][BufCount - 3];
|
{
|
||||||
|
buf[BufCount] = pad.buf[port][bufIndex];
|
||||||
|
}
|
||||||
// Pressure sensitivity bytes
|
// Pressure sensitivity bytes
|
||||||
else if (BufCount > 6)
|
else if (BufCount > 6)
|
||||||
buf[BufCount] = pad.buf[port][BufCount - 3];
|
{
|
||||||
|
buf[BufCount] = pad.buf[port][bufIndex];
|
||||||
|
}
|
||||||
|
|
||||||
// Updating movie file
|
// Updating movie file
|
||||||
g_InputRecording.ControllerInterrupt(data, port, BufCount, buf);
|
g_InputRecording.ControllerInterrupt(data, port, BufCount, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordingInputManager::SetButtonState(int port, PadDataNormalButton button, int pressure)
|
void RecordingInputManager::SetButtonState(int port, PadData_NormalButton button, int pressure)
|
||||||
{
|
{
|
||||||
int* buttons = pad.getNormalButtons(port);
|
std::vector<int> buttons = pad.GetNormalButtons(port);
|
||||||
buttons[button] = pressure;
|
buttons[button] = pressure;
|
||||||
pad.setNormalButtons(port, buttons);
|
pad.SetNormalButtons(port, buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordingInputManager::UpdateAnalog(int port, PadDataAnalogVector vector, int value)
|
void RecordingInputManager::UpdateAnalog(int port, PadData_AnalogVector vector, int value)
|
||||||
{
|
{
|
||||||
int* vectors = pad.getAnalogVectors(port);
|
std::vector<int> vectors = pad.GetAnalogVectors(port);
|
||||||
vectors[vector] = value;
|
vectors[vector] = value;
|
||||||
pad.setAnalogVectors(port, vectors);
|
pad.SetAnalogVectors(port, vectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordingInputManager::SetVirtualPadReading(int port, bool read)
|
void RecordingInputManager::SetVirtualPadReading(int port, bool read)
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "PadData.h"
|
#include "PadData.h"
|
||||||
|
|
||||||
|
|
||||||
class RecordingInputManager
|
class RecordingInputManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -24,9 +25,9 @@ public:
|
||||||
|
|
||||||
void ControllerInterrupt(u8 &data, u8 &port, u16 & BufCount, u8 buf[]);
|
void ControllerInterrupt(u8 &data, u8 &port, u16 & BufCount, u8 buf[]);
|
||||||
// Handles normal keys
|
// Handles normal keys
|
||||||
void SetButtonState(int port, PadDataNormalButton button, int pressure);
|
void SetButtonState(int port, PadData_NormalButton button, int pressure);
|
||||||
// Handles analog sticks
|
// Handles analog sticks
|
||||||
void UpdateAnalog(int port, PadDataAnalogVector vector, int value);
|
void UpdateAnalog(int port, PadData_AnalogVector vector, int value);
|
||||||
void SetVirtualPadReading(int port, bool read);
|
void SetVirtualPadReading(int port, bool read);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -125,10 +125,12 @@ VirtualPad::VirtualPad(wxWindow* parent, wxWindowID id, const wxString& title, i
|
||||||
|
|
||||||
void VirtualPad::SetProperties()
|
void VirtualPad::SetProperties()
|
||||||
{
|
{
|
||||||
if (controllerPort == 0) {
|
if (controllerPort == 0)
|
||||||
|
{
|
||||||
SetTitle(wxT("Virtual Pad - Port 1"));
|
SetTitle(wxT("Virtual Pad - Port 1"));
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
SetTitle(wxT("Virtual Pad - Port 2"));
|
SetTitle(wxT("Virtual Pad - Port 2"));
|
||||||
}
|
}
|
||||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||||
|
@ -137,9 +139,13 @@ void VirtualPad::SetProperties()
|
||||||
bool VirtualPad::Show(bool show)
|
bool VirtualPad::Show(bool show)
|
||||||
{
|
{
|
||||||
if (!wxFrame::Show(show))
|
if (!wxFrame::Show(show))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (show)
|
if (show)
|
||||||
|
{
|
||||||
g_RecordingInput.SetVirtualPadReading(controllerPort, true);
|
g_RecordingInput.SetVirtualPadReading(controllerPort, true);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +180,7 @@ void VirtualPad::OnButtonPress(wxCommandEvent & event)
|
||||||
pressure = 255;
|
pressure = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_RecordingInput.SetButtonState(controllerPort, PadDataNormalButton(buttonId), pressure);
|
g_RecordingInput.SetButtonState(controllerPort, PadData_NormalButton(buttonId), pressure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,10 +199,11 @@ void VirtualPad::OnPressureChange(wxSpinEvent & event)
|
||||||
if (spinnerId != -1)
|
if (spinnerId != -1)
|
||||||
{
|
{
|
||||||
u8 pressure = 0;
|
u8 pressure = 0;
|
||||||
if (event.IsChecked()) {
|
if (event.IsChecked())
|
||||||
|
{
|
||||||
pressure = buttonsPressure[spinnerId]->GetValue();
|
pressure = buttonsPressure[spinnerId]->GetValue();
|
||||||
}
|
}
|
||||||
g_RecordingInput.SetButtonState(controllerPort, PadDataNormalButton(spinnerId), pressure);
|
g_RecordingInput.SetButtonState(controllerPort, PadData_NormalButton(spinnerId), pressure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,11 +224,12 @@ void VirtualPad::OnAnalogSliderChange(wxCommandEvent & event)
|
||||||
{
|
{
|
||||||
analogVals[sliderId]->SetValue(event.GetInt());
|
analogVals[sliderId]->SetValue(event.GetInt());
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
analogVals[sliderId]->SetValue(event.GetInt() * -1);
|
analogVals[sliderId]->SetValue(event.GetInt() * -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_RecordingInput.UpdateAnalog(controllerPort, PadDataAnalogVector(sliderId), event.GetInt() + 127);
|
g_RecordingInput.UpdateAnalog(controllerPort, PadData_AnalogVector(sliderId), event.GetInt() + 127);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +247,7 @@ void VirtualPad::OnAnalogValChange(wxSpinEvent & event)
|
||||||
if (spinnerId != -1)
|
if (spinnerId != -1)
|
||||||
{
|
{
|
||||||
analogVals[spinnerId]->SetValue(event.GetInt());
|
analogVals[spinnerId]->SetValue(event.GetInt());
|
||||||
g_RecordingInput.UpdateAnalog(controllerPort, PadDataAnalogVector(spinnerId), event.GetInt() + 127);
|
g_RecordingInput.UpdateAnalog(controllerPort, PadData_AnalogVector(spinnerId), event.GetInt() + 127);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -219,15 +219,14 @@ SIO_WRITE sioWriteController(u8 data)
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
{
|
{
|
||||||
g_InputRecording.ControllerInterrupt(data, sio.port, sio.bufCount, sio.buf);
|
g_InputRecording.ControllerInterrupt(data, sio.port, sio.bufCount, sio.buf);
|
||||||
if (g_InputRecording.isInterruptFrame())
|
if (g_InputRecording.IsInterruptFrame())
|
||||||
{
|
{
|
||||||
g_RecordingInput.ControllerInterrupt(data, sio.port, sio.bufCount, sio.buf);
|
g_RecordingInput.ControllerInterrupt(data, sio.port, sio.bufCount, sio.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
PadData::logPadData(sio.port, sio.bufCount, sio.buf);
|
PadData::LogPadData(sio.port, sio.bufCount, sio.buf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//Console.WriteLn( "SIO: sent = %02X From pad data = %02X bufCnt %08X ", data, sio.buf[sio.bufCount], sio.bufCount);
|
//Console.WriteLn( "SIO: sent = %02X From pad data = %02X bufCnt %08X ", data, sio.buf[sio.bufCount], sio.bufCount);
|
||||||
|
|
|
@ -135,15 +135,15 @@ TLD_controlInfo = {
|
||||||
; // End init of TraceLogDescriptors
|
; // End init of TraceLogDescriptors
|
||||||
|
|
||||||
SysConsoleLogPack::SysConsoleLogPack()
|
SysConsoleLogPack::SysConsoleLogPack()
|
||||||
: ELF (&TLD_ELF, Color_Gray)
|
: ELF (&TLD_ELF, Color_Gray)
|
||||||
, eeRecPerf (&TLD_eeRecPerf, Color_Gray)
|
, eeRecPerf (&TLD_eeRecPerf, Color_Gray)
|
||||||
, sysoutConsole(&TLD_sysoutConsole, Color_Gray)
|
, sysoutConsole(&TLD_sysoutConsole, Color_Gray)
|
||||||
, eeConsole (&TLD_eeConsole)
|
, eeConsole (&TLD_eeConsole)
|
||||||
, iopConsole (&TLD_iopConsole)
|
, iopConsole (&TLD_iopConsole)
|
||||||
, deci2 (&TLD_deci2)
|
, deci2 (&TLD_deci2)
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
, recordingConsole(&TLD_recordingConsole)
|
, recordingConsole (&TLD_recordingConsole)
|
||||||
, controlInfo(&TLD_controlInfo)
|
, controlInfo (&TLD_controlInfo)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -763,11 +763,11 @@ Pcsx2App::Pcsx2App()
|
||||||
m_UseGUI = true;
|
m_UseGUI = true;
|
||||||
m_NoGuiExitPrompt = true;
|
m_NoGuiExitPrompt = true;
|
||||||
|
|
||||||
m_id_MainFrame = wxID_ANY;
|
m_id_MainFrame = wxID_ANY;
|
||||||
m_id_GsFrame = wxID_ANY;
|
m_id_GsFrame = wxID_ANY;
|
||||||
m_id_ProgramLogBox = wxID_ANY;
|
m_id_ProgramLogBox = wxID_ANY;
|
||||||
m_id_Disassembler = wxID_ANY;
|
m_id_Disassembler = wxID_ANY;
|
||||||
m_ptr_ProgramLog = NULL;
|
m_ptr_ProgramLog = NULL;
|
||||||
|
|
||||||
SetAppName( L"PCSX2" );
|
SetAppName( L"PCSX2" );
|
||||||
BuildCommandHash();
|
BuildCommandHash();
|
||||||
|
|
|
@ -617,7 +617,7 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
{
|
{
|
||||||
if (g_RecordingControls.isStop())
|
if (g_RecordingControls.HasRecordingStopped())
|
||||||
{
|
{
|
||||||
// While stopping, GSFrame key event also stops, so get key input from here
|
// While stopping, GSFrame key event also stops, so get key input from here
|
||||||
// Along with that, you can not use the shortcut keys set in GSFrame
|
// Along with that, you can not use the shortcut keys set in GSFrame
|
||||||
|
@ -631,7 +631,7 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_RecordingControls.StartCheck();
|
g_RecordingControls.ResumeCoreThreadIfStarted();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
(handler->*func)(event);
|
(handler->*func)(event);
|
||||||
|
|
|
@ -283,6 +283,22 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum MenuId_LogSources_Offset
|
||||||
|
{
|
||||||
|
MenuId_LogSources_Offset_eeConsole = 0,
|
||||||
|
MenuId_LogSources_Offset_iopConsole,
|
||||||
|
MenuId_LogSources_Offset_eeRecPerf,
|
||||||
|
|
||||||
|
MenuId_LogSources_Offset_ELF = 4,
|
||||||
|
|
||||||
|
MenuId_LogSources_Offset_Event = 6,
|
||||||
|
MenuId_LogSources_Offset_Thread,
|
||||||
|
MenuId_LogSources_Offset_sysoutConsole,
|
||||||
|
|
||||||
|
MenuId_LogSources_Offset_recordingConsole = 10,
|
||||||
|
MenuId_LogSources_Offset_controlInfo
|
||||||
|
};
|
||||||
|
|
||||||
// WARNING ConsoleLogSources & ConLogDefaults must have the same size
|
// WARNING ConsoleLogSources & ConLogDefaults must have the same size
|
||||||
static ConsoleLogSource* const ConLogSources[] =
|
static ConsoleLogSource* const ConLogSources[] =
|
||||||
{
|
{
|
||||||
|
@ -294,7 +310,7 @@ static ConsoleLogSource* const ConLogSources[] =
|
||||||
NULL,
|
NULL,
|
||||||
(ConsoleLogSource*)&pxConLog_Event,
|
(ConsoleLogSource*)&pxConLog_Event,
|
||||||
(ConsoleLogSource*)&pxConLog_Thread,
|
(ConsoleLogSource*)&pxConLog_Thread,
|
||||||
(ConsoleLogSource*)&SysConsole.sysoutConsole
|
(ConsoleLogSource*)&SysConsole.sysoutConsole,
|
||||||
NULL,
|
NULL,
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
(ConsoleLogSource*)&SysConsole.recordingConsole,
|
(ConsoleLogSource*)&SysConsole.recordingConsole,
|
||||||
|
@ -571,6 +587,10 @@ void ConsoleLogFrame::OnLoggingChanged()
|
||||||
{
|
{
|
||||||
GetMenuBar()->Check( MenuId_LogSource_Start+i, log->IsActive() );
|
GetMenuBar()->Check( MenuId_LogSource_Start+i, log->IsActive() );
|
||||||
}
|
}
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
GetMenuBar()->Enable( MenuId_LogSource_Start + MenuId_LogSources_Offset_recordingConsole, g_Conf->EmuOptions.EnableRecordingTools);
|
||||||
|
GetMenuBar()->Enable( MenuId_LogSource_Start + MenuId_LogSources_Offset_controlInfo, g_Conf->EmuOptions.EnableRecordingTools);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,8 +132,10 @@ GSPanel::GSPanel( wxWindow* parent )
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
// Retrieving FrameAdvance Key
|
// Retrieving FrameAdvance Key
|
||||||
for (auto itr = m_Accels->begin(); itr != m_Accels->end(); ++itr) {
|
for (auto itr = m_Accels->begin(); itr != m_Accels->end(); ++itr)
|
||||||
if (itr->second->Id == "FrameAdvance") {
|
{
|
||||||
|
if (itr->second->Id == "FrameAdvance")
|
||||||
|
{
|
||||||
m_frameAdvanceKey = itr->first;
|
m_frameAdvanceKey = itr->first;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -377,14 +379,16 @@ void GSPanel::OnKeyDownOrUp( wxKeyEvent& evt )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((PADopen != NULL) && CoreThread.IsOpen())
|
if ((PADopen != NULL) && CoreThread.IsOpen())
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
{
|
{
|
||||||
// TODO-Recording: This is to allow for repeated frame-advance while holding the key
|
// TODO-Recording: This is to allow for repeated frame-advance while holding the key
|
||||||
// However as per the explaination above, this event no longer seems to fire under normal
|
// However as per the explaination above, this event no longer seems to fire under normal
|
||||||
// circumstances and I'm unsure if there is a place to put this logic
|
// circumstances
|
||||||
if (evt.GetKeyCode() == m_frameAdvanceKey)
|
if (evt.GetKeyCode() == m_frameAdvanceKey)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -727,23 +731,24 @@ void GSFrame::OnUpdateTitle( wxTimerEvent& evt )
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
wxString title;
|
wxString title;
|
||||||
wxString movieMode;
|
wxString movieMode;
|
||||||
switch (g_InputRecording.getModeState()) {
|
switch (g_InputRecording.GetModeState())
|
||||||
case InputRecording::KEY_MOVIE_MODE::RECORD:
|
{
|
||||||
movieMode = "Recording";
|
case INPUT_RECORDING_MODE_RECORD:
|
||||||
title = templates.RecordingTemplate;
|
movieMode = "Recording";
|
||||||
break;
|
title = templates.RecordingTemplate;
|
||||||
case InputRecording::KEY_MOVIE_MODE::REPLAY:
|
break;
|
||||||
movieMode = "Replaying";
|
case INPUT_RECORDING_MODE_REPLAY:
|
||||||
title = templates.RecordingTemplate;
|
movieMode = "Replaying";
|
||||||
break;
|
title = templates.RecordingTemplate;
|
||||||
case InputRecording::KEY_MOVIE_MODE::NONE:
|
break;
|
||||||
movieMode = "No movie";
|
case INPUT_RECORDING_MODE_NONE:
|
||||||
title = templates.TitleTemplate;
|
movieMode = "No movie";
|
||||||
break;
|
title = templates.TitleTemplate;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
title.Replace(L"${frame}", pxsFmt(L"%d", g_FrameCount));
|
title.Replace(L"${frame}", pxsFmt(L"%d", g_FrameCount));
|
||||||
title.Replace(L"${maxFrame}", pxsFmt(L"%d", g_InputRecording.getInputRecordingData().getMaxFrame()));
|
title.Replace(L"${maxFrame}", pxsFmt(L"%d", g_InputRecording.GetInputRecordingData().GetMaxFrame()));
|
||||||
title.Replace(L"${mode}", movieMode);
|
title.Replace(L"${mode}", movieMode);
|
||||||
#else
|
#else
|
||||||
wxString title = templates.TitleTemplate;
|
wxString title = templates.TitleTemplate;
|
||||||
|
|
|
@ -18,10 +18,6 @@
|
||||||
|
|
||||||
#include "AppCommon.h"
|
#include "AppCommon.h"
|
||||||
#include "CpuUsageProvider.h"
|
#include "CpuUsageProvider.h"
|
||||||
|
|
||||||
#include "wx/dcbuffer.h"
|
|
||||||
#include "wx/dcgraph.h"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,10 +55,10 @@ public:
|
||||||
GSPanel( wxWindow* parent );
|
GSPanel( wxWindow* parent );
|
||||||
virtual ~GSPanel();
|
virtual ~GSPanel();
|
||||||
|
|
||||||
virtual void DoResize();
|
void DoResize();
|
||||||
void DoShowMouse();
|
void DoShowMouse();
|
||||||
void DirectKeyCommand( wxKeyEvent& evt );
|
void DirectKeyCommand( wxKeyEvent& evt );
|
||||||
virtual void DirectKeyCommand( const KeyAcceleratorCode& kac );
|
void DirectKeyCommand( const KeyAcceleratorCode& kac );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void AppStatusEvent_OnSettingsApplied();
|
void AppStatusEvent_OnSettingsApplied();
|
||||||
|
@ -83,6 +79,7 @@ protected:
|
||||||
void UpdateScreensaver();
|
void UpdateScreensaver();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// GSFrame
|
// GSFrame
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -467,48 +467,138 @@ namespace Implementations
|
||||||
void FrameAdvance()
|
void FrameAdvance()
|
||||||
{
|
{
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
|
{
|
||||||
g_RecordingControls.FrameAdvance();
|
g_RecordingControls.FrameAdvance();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TogglePause()
|
void TogglePause()
|
||||||
{
|
{
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
|
{
|
||||||
g_RecordingControls.TogglePause();
|
g_RecordingControls.TogglePause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputRecordingModeToggle()
|
void InputRecordingModeToggle()
|
||||||
{
|
{
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
|
{
|
||||||
g_InputRecording.RecordModeToggle();
|
g_InputRecording.RecordModeToggle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void States_SaveSlot(int slot)
|
void States_SaveSlot(int slot)
|
||||||
{
|
{
|
||||||
States_SetCurrentSlot(slot);
|
States_SetCurrentSlot(slot);
|
||||||
States_FreezeCurrentSlot();
|
States_FreezeCurrentSlot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void States_LoadSlot(int slot)
|
void States_LoadSlot(int slot)
|
||||||
{
|
{
|
||||||
States_SetCurrentSlot(slot);
|
States_SetCurrentSlot(slot);
|
||||||
States_DefrostCurrentSlot();
|
States_DefrostCurrentSlot();
|
||||||
}
|
}
|
||||||
void States_SaveSlot0() { States_SaveSlot(0); }
|
|
||||||
void States_SaveSlot1() { States_SaveSlot(1); }
|
void States_SaveSlot0()
|
||||||
void States_SaveSlot2() { States_SaveSlot(2); }
|
{
|
||||||
void States_SaveSlot3() { States_SaveSlot(3); }
|
States_SaveSlot(0);
|
||||||
void States_SaveSlot4() { States_SaveSlot(4); }
|
}
|
||||||
void States_SaveSlot5() { States_SaveSlot(5); }
|
|
||||||
void States_SaveSlot6() { States_SaveSlot(6); }
|
void States_SaveSlot1()
|
||||||
void States_SaveSlot7() { States_SaveSlot(7); }
|
{
|
||||||
void States_SaveSlot8() { States_SaveSlot(8); }
|
States_SaveSlot(1);
|
||||||
void States_SaveSlot9() { States_SaveSlot(9); }
|
}
|
||||||
void States_LoadSlot0() { States_LoadSlot(0); }
|
|
||||||
void States_LoadSlot1() { States_LoadSlot(1); }
|
void States_SaveSlot2()
|
||||||
void States_LoadSlot2() { States_LoadSlot(2); }
|
{
|
||||||
void States_LoadSlot3() { States_LoadSlot(3); }
|
States_SaveSlot(2);
|
||||||
void States_LoadSlot4() { States_LoadSlot(4); }
|
}
|
||||||
void States_LoadSlot5() { States_LoadSlot(5); }
|
|
||||||
void States_LoadSlot6() { States_LoadSlot(6); }
|
void States_SaveSlot3()
|
||||||
void States_LoadSlot7() { States_LoadSlot(7); }
|
{
|
||||||
void States_LoadSlot8() { States_LoadSlot(8); }
|
States_SaveSlot(3);
|
||||||
void States_LoadSlot9() { States_LoadSlot(9); }
|
}
|
||||||
|
|
||||||
|
void States_SaveSlot4()
|
||||||
|
{
|
||||||
|
States_SaveSlot(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_SaveSlot5()
|
||||||
|
{
|
||||||
|
States_SaveSlot(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_SaveSlot6()
|
||||||
|
{
|
||||||
|
States_SaveSlot(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_SaveSlot7()
|
||||||
|
{
|
||||||
|
States_SaveSlot(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_SaveSlot8()
|
||||||
|
{
|
||||||
|
States_SaveSlot(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_SaveSlot9()
|
||||||
|
{
|
||||||
|
States_SaveSlot(9);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_LoadSlot0()
|
||||||
|
{
|
||||||
|
States_LoadSlot(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_LoadSlot1()
|
||||||
|
{
|
||||||
|
States_LoadSlot(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_LoadSlot2()
|
||||||
|
{
|
||||||
|
States_LoadSlot(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_LoadSlot3()
|
||||||
|
{
|
||||||
|
States_LoadSlot(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_LoadSlot4()
|
||||||
|
{
|
||||||
|
States_LoadSlot(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_LoadSlot5()
|
||||||
|
{
|
||||||
|
States_LoadSlot(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_LoadSlot6()
|
||||||
|
{
|
||||||
|
States_LoadSlot(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_LoadSlot7()
|
||||||
|
{
|
||||||
|
States_LoadSlot(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_LoadSlot8()
|
||||||
|
{
|
||||||
|
States_LoadSlot(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void States_LoadSlot9()
|
||||||
|
{
|
||||||
|
States_LoadSlot(9);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -372,7 +372,7 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
|
||||||
SetMenuBar( &m_menubar );
|
SetMenuBar( &m_menubar );
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
// Append the Recording / Lua options if previous enabled and picked up from ini
|
// Append the Recording options if previously enabled and setting has been picked up from ini
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
{
|
{
|
||||||
m_menubar.Append(&m_menuRecording, _("&Recording"));
|
m_menubar.Append(&m_menuRecording, _("&Recording"));
|
||||||
|
|
|
@ -498,10 +498,12 @@ void MainEmuFrame::Menu_EnableRecordingTools_Click(wxCommandEvent&)
|
||||||
{
|
{
|
||||||
bool checked = GetMenuBar()->IsChecked(MenuId_EnableRecordingTools);
|
bool checked = GetMenuBar()->IsChecked(MenuId_EnableRecordingTools);
|
||||||
// Confirm with User
|
// Confirm with User
|
||||||
if (checked) {
|
if (checked)
|
||||||
|
{
|
||||||
if (!Msgbox::OkCancel(_("Please be aware that PCSX2's input recording features are still very much a work-in-progress.\n"
|
if (!Msgbox::OkCancel(_("Please be aware that PCSX2's input recording features are still very much a work-in-progress.\n"
|
||||||
"As a result, there may be unforeseen bugs, performance implications and instability with certain games.\n\n"
|
"As a result, there may be unforeseen bugs, performance implications and instability with certain games.\n\n"
|
||||||
"These tools are provided as-is and should be enabled under your own discretion."), "Enabling Recording Tools")) {
|
"These tools are provided as-is and should be enabled under your own discretion."), "Enabling Recording Tools"))
|
||||||
|
{
|
||||||
checked = false;
|
checked = false;
|
||||||
m_menuSys.FindChildItem(MenuId_EnableRecordingTools)->Check(false);
|
m_menuSys.FindChildItem(MenuId_EnableRecordingTools)->Check(false);
|
||||||
}
|
}
|
||||||
|
@ -515,12 +517,14 @@ void MainEmuFrame::Menu_EnableRecordingTools_Click(wxCommandEvent&)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GetMenuBar()->Remove(TopLevelMenu_Recording);
|
GetMenuBar()->Remove(TopLevelMenu_Recording);
|
||||||
|
// Always turn controller logs off, but never turn it on by default
|
||||||
|
SysConsole.controlInfo.Enabled = checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Conf->EmuOptions.EnableRecordingTools = checked;
|
g_Conf->EmuOptions.EnableRecordingTools = checked;
|
||||||
SysConsole.recordingConsole.Enabled = checked;
|
SysConsole.recordingConsole.Enabled = checked;
|
||||||
ConsoleLogFrame* proglog = wxGetApp().GetProgramLog();
|
ConsoleLogFrame* progLog = wxGetApp().GetProgramLog();
|
||||||
proglog->UpdateLogList();
|
progLog->UpdateLogList();
|
||||||
AppApplySettings();
|
AppApplySettings();
|
||||||
AppSaveSettings();
|
AppSaveSettings();
|
||||||
}
|
}
|
||||||
|
@ -568,11 +572,11 @@ void MainEmuFrame::Menu_LoadStateFromFile_Click(wxCommandEvent &event)
|
||||||
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
|
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
|
||||||
|
|
||||||
if (loadStateDialog.ShowModal() == wxID_CANCEL)
|
if (loadStateDialog.ShowModal() == wxID_CANCEL)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wxString path = loadStateDialog.GetPath();
|
wxString path = loadStateDialog.GetPath();
|
||||||
Console.WriteLn(path);
|
|
||||||
|
|
||||||
StateCopy_LoadFromFile(path);
|
StateCopy_LoadFromFile(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,11 +586,11 @@ void MainEmuFrame::Menu_SaveStateToFile_Click(wxCommandEvent &event)
|
||||||
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
|
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
|
||||||
|
|
||||||
if (saveStateDialog.ShowModal() == wxID_CANCEL)
|
if (saveStateDialog.ShowModal() == wxID_CANCEL)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wxString path = saveStateDialog.GetPath();
|
wxString path = saveStateDialog.GetPath();
|
||||||
Console.WriteLn(path);
|
|
||||||
|
|
||||||
StateCopy_SaveToFile(path);
|
StateCopy_SaveToFile(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,47 +710,70 @@ void MainEmuFrame::Menu_Capture_Video_Stop_Click(wxCommandEvent &event)
|
||||||
void MainEmuFrame::VideoCaptureUpdate()
|
void MainEmuFrame::VideoCaptureUpdate()
|
||||||
{
|
{
|
||||||
GetMTGS().WaitGS(); // make sure GS is in sync with the audio stream when we start.
|
GetMTGS().WaitGS(); // make sure GS is in sync with the audio stream when we start.
|
||||||
if (m_capturingVideo) {
|
if (m_capturingVideo)
|
||||||
|
{
|
||||||
// start recording
|
// start recording
|
||||||
|
|
||||||
// make the recording setup dialog[s] pseudo-modal also for the main PCSX2 window
|
// make the recording setup dialog[s] pseudo-modal also for the main PCSX2 window
|
||||||
// (the GSdx dialog is already properly modal for the GS window)
|
// (the GSdx dialog is already properly modal for the GS window)
|
||||||
bool needsMainFrameEnable = false;
|
bool needsMainFrameEnable = false;
|
||||||
if (GetMainFramePtr() && GetMainFramePtr()->IsEnabled()) {
|
if (GetMainFramePtr() && GetMainFramePtr()->IsEnabled())
|
||||||
|
{
|
||||||
needsMainFrameEnable = true;
|
needsMainFrameEnable = true;
|
||||||
GetMainFramePtr()->Disable();
|
GetMainFramePtr()->Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GSsetupRecording) {
|
if (GSsetupRecording)
|
||||||
|
{
|
||||||
// GSsetupRecording can be aborted/canceled by the user. Don't go on to record the audio if that happens.
|
// GSsetupRecording can be aborted/canceled by the user. Don't go on to record the audio if that happens.
|
||||||
if (GSsetupRecording(m_capturingVideo, NULL)) {
|
if (GSsetupRecording(m_capturingVideo, NULL))
|
||||||
if (SPU2setupRecording) SPU2setupRecording(m_capturingVideo, NULL);
|
{
|
||||||
|
if (SPU2setupRecording)
|
||||||
|
{
|
||||||
|
SPU2setupRecording(m_capturingVideo, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// recording dialog canceled by the user. align our state
|
// recording dialog canceled by the user. align our state
|
||||||
m_capturingVideo = false;
|
m_capturingVideo = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// the GS doesn't support recording.
|
// the GS doesn't support recording.
|
||||||
if (SPU2setupRecording) SPU2setupRecording(m_capturingVideo, NULL);
|
if (SPU2setupRecording)
|
||||||
|
{
|
||||||
|
SPU2setupRecording(m_capturingVideo, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetMainFramePtr() && needsMainFrameEnable)
|
if (GetMainFramePtr() && needsMainFrameEnable)
|
||||||
|
{
|
||||||
GetMainFramePtr()->Enable();
|
GetMainFramePtr()->Enable();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// stop recording
|
// stop recording
|
||||||
if (GSsetupRecording) GSsetupRecording(m_capturingVideo, NULL);
|
if (GSsetupRecording)
|
||||||
if (SPU2setupRecording) SPU2setupRecording(m_capturingVideo, NULL);
|
{
|
||||||
|
GSsetupRecording(m_capturingVideo, NULL);
|
||||||
|
}
|
||||||
|
if (SPU2setupRecording)
|
||||||
|
{
|
||||||
|
SPU2setupRecording(m_capturingVideo, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_capturingVideo) {
|
if (m_capturingVideo)
|
||||||
|
{
|
||||||
m_submenuVideoCapture.FindItem(MenuId_Capture_Video_Record)->Enable(false);
|
m_submenuVideoCapture.FindItem(MenuId_Capture_Video_Record)->Enable(false);
|
||||||
m_submenuVideoCapture.FindItem(MenuId_Capture_Video_Stop)->Enable(true);
|
m_submenuVideoCapture.FindItem(MenuId_Capture_Video_Stop)->Enable(true);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
m_submenuVideoCapture.FindItem(MenuId_Capture_Video_Record)->Enable(true);
|
m_submenuVideoCapture.FindItem(MenuId_Capture_Video_Record)->Enable(true);
|
||||||
m_submenuVideoCapture.FindItem(MenuId_Capture_Video_Stop)->Enable(false);
|
m_submenuVideoCapture.FindItem(MenuId_Capture_Video_Stop)->Enable(false);
|
||||||
}
|
}
|
||||||
|
@ -755,7 +782,9 @@ void MainEmuFrame::VideoCaptureUpdate()
|
||||||
void MainEmuFrame::Menu_Capture_Screenshot_Screenshot_Click(wxCommandEvent & event)
|
void MainEmuFrame::Menu_Capture_Screenshot_Screenshot_Click(wxCommandEvent & event)
|
||||||
{
|
{
|
||||||
if (!CoreThread.IsOpen())
|
if (!CoreThread.IsOpen())
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
GSmakeSnapshot(g_Conf->Folders.Snapshots.ToAscii());
|
GSmakeSnapshot(g_Conf->Folders.Snapshots.ToAscii());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,18 +801,19 @@ void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent &event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// From Current Frame
|
// From Current Frame
|
||||||
if (NewRecordingFrame->getFrom() == 0)
|
if (NewRecordingFrame->GetFrom() == 0)
|
||||||
{
|
{
|
||||||
if (!CoreThread.IsOpen()) {
|
if (!CoreThread.IsOpen())
|
||||||
|
{
|
||||||
recordingConLog(L"[REC]: Game is not open, aborting new input recording.\n");
|
recordingConLog(L"[REC]: Game is not open, aborting new input recording.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_InputRecording.Create(NewRecordingFrame->getFile(), true, NewRecordingFrame->getAuthor());
|
g_InputRecording.Create(NewRecordingFrame->GetFile(), true, NewRecordingFrame->GetAuthor());
|
||||||
}
|
}
|
||||||
// From Power-On
|
// From Power-On
|
||||||
else if (NewRecordingFrame->getFrom() == 1)
|
else if (NewRecordingFrame->GetFrom() == 1)
|
||||||
{
|
{
|
||||||
g_InputRecording.Create(NewRecordingFrame->getFile(), false, NewRecordingFrame->getAuthor());
|
g_InputRecording.Create(NewRecordingFrame->GetFile(), false, NewRecordingFrame->GetAuthor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(false);
|
m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(false);
|
||||||
|
@ -795,7 +825,10 @@ void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent &event)
|
||||||
g_InputRecording.Stop();
|
g_InputRecording.Stop();
|
||||||
wxFileDialog openFileDialog(this, _("Select P2M2 record file."), L"", L"",
|
wxFileDialog openFileDialog(this, _("Select P2M2 record file."), L"", L"",
|
||||||
L"p2m2 file(*.p2m2)|*.p2m2", wxFD_OPEN);
|
L"p2m2 file(*.p2m2)|*.p2m2", wxFD_OPEN);
|
||||||
if (openFileDialog.ShowModal() == wxID_CANCEL) return;
|
if (openFileDialog.ShowModal() == wxID_CANCEL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wxString path = openFileDialog.GetPath();
|
wxString path = openFileDialog.GetPath();
|
||||||
g_InputRecording.Play(path, true);
|
g_InputRecording.Play(path, true);
|
||||||
|
@ -812,12 +845,18 @@ void MainEmuFrame::Menu_Recording_Stop_Click(wxCommandEvent &event)
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Recording_VirtualPad_Open_Click(wxCommandEvent &event)
|
void MainEmuFrame::Menu_Recording_VirtualPad_Open_Click(wxCommandEvent &event)
|
||||||
{
|
{
|
||||||
VirtualPad *vp;
|
VirtualPad *vp = NULL;
|
||||||
if (event.GetId() == MenuId_Recording_VirtualPad_Port0)
|
if (event.GetId() == MenuId_Recording_VirtualPad_Port0)
|
||||||
|
{
|
||||||
vp = wxGetApp().GetVirtualPadPtr(0);
|
vp = wxGetApp().GetVirtualPadPtr(0);
|
||||||
|
}
|
||||||
else if (event.GetId() == MenuId_Recording_VirtualPad_Port1)
|
else if (event.GetId() == MenuId_Recording_VirtualPad_Port1)
|
||||||
|
{
|
||||||
vp = wxGetApp().GetVirtualPadPtr(1);
|
vp = wxGetApp().GetVirtualPadPtr(1);
|
||||||
if (vp)
|
}
|
||||||
|
if (vp != NULL)
|
||||||
|
{
|
||||||
vp->Show();
|
vp->Show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue