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:
Tyler Wilding 2018-11-30 00:13:30 -05:00 committed by lightningterror
parent 08d923ca6f
commit 506ea4c4d2
32 changed files with 867 additions and 620 deletions

1
.gitignore vendored
View File

@ -46,6 +46,7 @@ Thumbs.db
Debug.txt
install_log.txt
padLog.txt
Debug
Release

View File

@ -82,7 +82,6 @@ GSwindow_OffsetXplus = Alt-Ctrl-RIGHT
GSwindow_OffsetReset = Alt-Ctrl-KP_DIVIDE
# Recording Bindings
# TODO: add to http://wiki.pcsx2.net/index.php/Hotkeys
FrameAdvance = SPACE
TogglePause = Shift-P
InputRecordingModeToggle = Shift-R

View File

@ -626,6 +626,7 @@ else()
set(pcsx2SSources "")
endif()
# common Sources
set(Common
${pcsx2Sources}

View File

@ -455,7 +455,7 @@ struct Pcsx2Config
EnableCheats :1, // enables cheat detection and application
EnableWideScreenPatches :1,
#ifndef DISABLE_RECORDING
EnableRecordingTools : 1,
EnableRecordingTools :1,
#endif
// when enabled uses BOOT2 injection, skipping sony bios splashes
UseBOOT2Injection :1,

View File

@ -575,7 +575,7 @@ __fi void rcntUpdate_vSync()
#ifndef DISABLE_RECORDING
if (g_Conf->EmuOptions.EnableRecordingTools)
{
g_RecordingControls.StopCheck();
g_RecordingControls.HandleFrameAdvanceAndStop();
}
#endif

View File

@ -434,7 +434,7 @@ void Pcsx2Config::LoadSave( IniInterface& ini )
IniBitBool( EnableCheats );
IniBitBool( EnableWideScreenPatches );
#ifndef DISABLE_RECORDING
IniBitBool(EnableRecordingTools);
IniBitBool( EnableRecordingTools );
#endif
IniBitBool( ConsoleToStdio );
IniBitBool( HostFs );

View File

@ -22,130 +22,126 @@
#include "MemoryTypes.h"
#include "SaveState.h"
#include "Recording/RecordingControls.h"
#include "InputRecording.h"
#include "Recording/RecordingControls.h"
#include <vector>
InputRecording g_InputRecording;
// --------------------------------
// Tag and save framecount along with savestate
// --------------------------------
void SaveStateBase::InputRecordingFreeze()
{
FreezeTag("InputRecording");
Freeze(g_FrameCount);
if (IsLoading()) {
g_InputRecordingData.addUndoCount();
if (g_FrameCount > 0 && IsLoading())
{
g_InputRecordingData.AddUndoCount();
}
}
//----------------------------------
// 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[])
{
// TODO - Multi-Tap Support
// Only examine controllers 1 / 2
if (port < 0 || 1 < port)
return;
//==========================
// This appears to try to ensure that we are only paying attention
// to the frames that matter, the ones that are reading from
// the controller.
//
// See - Lilypad.cpp:1254
// 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 (data == 0x42)
if (port != 0 && port != 1)
{
fInterruptFrame = true;
}
else {
fInterruptFrame = false;
return;
}
}
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)
// query is executed, this looks like a sanity check
if (buf[bufCount] != 0x5A) {
fInterruptFrame = false;
return;
}
}
/*
This appears to try to ensure that we are only paying attention
to the frames that matter, the ones that are reading from
the controller.
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
*/
if (bufCount == 1)
{
fInterruptFrame = data == 0x42;
if (!fInterruptFrame)
{
return;
if (state == NONE)
}
}
else if ( bufCount == 2 )
{
/*
See - LilyPad.cpp::PADpoll - https://github.com/PCSX2/pcsx2/blob/v1.5.0-dev/plugins/LilyPad/LilyPad.cpp#L1194
0x5A is always the second byte in the buffer
when the normal READ_DATA_AND_VIBRRATE (0x42)
query is executed, this looks like a sanity check
*/
if (buf[bufCount] != 0x5A)
{
fInterruptFrame = false;
return;
}
}
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
if (bufCount < 3)
|| bufCount < 3)
{
return;
//---------------
// Read or Write
//---------------
const u8 &nowBuf = buf[bufCount];
if (state == RECORD)
{
InputRecordingData.updateFrameMax(g_FrameCount);
InputRecordingData.writeKeyBuf(g_FrameCount, port, bufCount - 3, nowBuf);
}
else if (state == REPLAY)
// Read or Write
const u8 &nowBuf = buf[bufCount];
if (state == INPUT_RECORDING_MODE_RECORD)
{
if (InputRecordingData.getMaxFrame() <= g_FrameCount)
InputRecordingData.UpdateFrameMax(g_FrameCount);
InputRecordingData.WriteKeyBuf(g_FrameCount, port, bufCount - 3, nowBuf);
}
else if (state == INPUT_RECORDING_MODE_REPLAY)
{
if (InputRecordingData.GetMaxFrame() <= g_FrameCount)
{
// Pause the emulation but the movie is not closed
g_RecordingControls.Pause();
return;
}
u8 tmp = 0;
if (InputRecordingData.readKeyBuf(tmp, g_FrameCount, port, bufCount - 3)) {
if (InputRecordingData.ReadKeyBuf(tmp, g_FrameCount, port, bufCount - 3))
{
buf[bufCount] = tmp;
}
}
}
//----------------------------------
// stop
//----------------------------------
void InputRecording::Stop() {
state = NONE;
if (InputRecordingData.Close()) {
// GUI Handler - Stop recording
void InputRecording::Stop()
{
state = INPUT_RECORDING_MODE_NONE;
if (InputRecordingData.Close())
{
recordingConLog(L"[REC]: InputRecording Recording Stopped.\n");
}
}
//----------------------------------
// start
//----------------------------------
// GUI Handler - Start recording
void InputRecording::Create(wxString FileName, bool fromSaveState, wxString authorName)
{
g_RecordingControls.Pause();
Stop();
// create
if (!InputRecordingData.Open(FileName, true, fromSaveState)) {
if (!InputRecordingData.Open(FileName, true, fromSaveState))
{
return;
}
// Set author name
if (!authorName.IsEmpty())
{
InputRecordingData.getHeader().setAuthor(authorName);
InputRecordingData.GetHeader().SetAuthor(authorName);
}
// Set 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.writeHeader();
state = RECORD;
InputRecordingData.GetHeader().SetGameName(!gameName.IsEmpty() ? gameName : Path::GetFilename(g_Conf->CurrentIso));
InputRecordingData.WriteHeader();
state = INPUT_RECORDING_MODE_RECORD;
recordingConLog(wxString::Format(L"[REC]: Started new recording - [%s]\n", FileName));
// In every case, we reset the g_FrameCount
g_FrameCount = 0;
}
// GUI Handler - Play a recording
void InputRecording::Play(wxString FileName, bool fromSaveState)
{
g_RecordingControls.Pause();
Stop();
if (!InputRecordingData.Open(FileName, false, false)) {
if (!InputRecordingData.Open(FileName, false, false))
{
return;
}
if (!InputRecordingData.readHeaderAndCheck()) {
if (!InputRecordingData.ReadHeaderAndCheck())
{
recordingConLog(L"[REC]: This file is not a correct InputRecording file.\n");
InputRecordingData.Close();
return;
@ -189,32 +188,46 @@ void InputRecording::Play(wxString FileName, bool fromSaveState)
// Check author name
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");
}
}
state = REPLAY;
state = INPUT_RECORDING_MODE_REPLAY;
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"Associated Game Name / ISO Filename: %s\n", InputRecordingData.getHeader().gameName));
recordingConLog(wxString::Format(L"Author: %s\n", InputRecordingData.getHeader().author));
recordingConLog(wxString::Format(L"MaxFrame: %d\n", InputRecordingData.getMaxFrame()));
recordingConLog(wxString::Format(L"UndoCount: %d\n", InputRecordingData.getUndoCount()));
recordingConLog(wxString::Format(L"[REC]: Recording File Version: %d\n", InputRecordingData.GetHeader().version));
recordingConLog(wxString::Format(L"[REC]: Associated Game Name / ISO Filename: %s\n", InputRecordingData.GetHeader().gameName));
recordingConLog(wxString::Format(L"[REC]: Author: %s\n", InputRecordingData.GetHeader().author));
recordingConLog(wxString::Format(L"[REC]: MaxFrame: %d\n", InputRecordingData.GetMaxFrame()));
recordingConLog(wxString::Format(L"[REC]: UndoCount: %d\n", InputRecordingData.GetUndoCount()));
}
//----------------------------------
// shortcut key
//----------------------------------
// Keybind Handler - Toggle between recording input and not
void InputRecording::RecordModeToggle()
{
if (state == REPLAY) {
state = RECORD;
if (state == INPUT_RECORDING_MODE_REPLAY)
{
state = INPUT_RECORDING_MODE_RECORD;
recordingConLog("[REC]: Record mode ON.\n");
}
else if (state == RECORD) {
state = REPLAY;
else if (state == INPUT_RECORDING_MODE_RECORD)
{
state = INPUT_RECORDING_MODE_REPLAY;
recordingConLog("[REC]: Replay mode ON.\n");
}
}
INPUT_RECORDING_MODE InputRecording::GetModeState()
{
return state;
}
InputRecordingFile & InputRecording::GetInputRecordingData()
{
return InputRecordingData;
}
bool InputRecording::IsInterruptFrame()
{
return fInterruptFrame;
}

View File

@ -18,46 +18,37 @@
#include "InputRecordingFile.h"
//----------------------------
// InputRecording
//----------------------------
class InputRecording {
enum INPUT_RECORDING_MODE
{
INPUT_RECORDING_MODE_NONE,
INPUT_RECORDING_MODE_RECORD,
INPUT_RECORDING_MODE_REPLAY,
};
class InputRecording
{
public:
InputRecording() {}
~InputRecording(){}
public:
// controller
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 Create(wxString filename, bool fromSaveState, wxString authorName);
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:
InputRecordingFile InputRecordingData;
KEY_MOVIE_MODE state = NONE;
INPUT_RECORDING_MODE state = INPUT_RECORDING_MODE_NONE;
bool fInterruptFrame = false;
};
extern InputRecording g_InputRecording;
#define g_InputRecordingData (g_InputRecording.getInputRecordingData())
#define g_InputRecordingHeader (g_InputRecording.getInputRecordingData().getHeader())
static InputRecordingFile& g_InputRecordingData = g_InputRecording.GetInputRecordingData();
static InputRecordingHeader& g_InputRecordingHeader = g_InputRecording.GetInputRecordingData().GetHeader();

View File

@ -23,25 +23,17 @@
#include "InputRecordingFile.h"
#define HEADER_SIZE (sizeof(InputRecordingHeader)+4+4)
#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)
long InputRecordingFile::GetBlockSeekPoint(const long & frame)
{
if (savestate.fromSavestate) {
return HEADER_SIZE
+ SAVESTATE_HEADER_SIZE
+ frame * BLOCK_SIZE;
if (savestate.fromSavestate)
{
return RecordingHeaderSize
+ RecordingSavestateHeaderSize
+ frame * RecordingBlockSize;
}
else {
return HEADER_SIZE + sizeof(bool) + (frame)*BLOCK_SIZE;
else
{
return RecordingHeaderSize + sizeof(bool) + (frame)*RecordingBlockSize;
}
}
@ -50,11 +42,12 @@ bool InputRecordingFile::Open(const wxString path, bool fNewOpen, bool fromSaveS
{
Close();
wxString mode = L"rb+";
if (fNewOpen) {
if (fNewOpen)
{
mode = L"wb+";
MaxFrame = 0;
UndoCount = 0;
header.init();
header.Init();
}
recordingFile = wxFopen(path, mode);
if ( recordingFile == NULL )
@ -64,98 +57,114 @@ bool InputRecordingFile::Open(const wxString path, bool fNewOpen, bool fromSaveS
}
filename = path;
// problems seem to be be based in how we are saving the savestate
if (fNewOpen) {
if (fromSaveState) {
if (fNewOpen)
{
if (fromSaveState)
{
savestate.fromSavestate = true;
// TODO - Return save-state data back into the movie file eventually.
FILE* ssFileCheck = wxFopen(path + "_SaveState.p2s", "r");
if (ssFileCheck != NULL) {
if (ssFileCheck != NULL)
{
wxCopyFile(path + "_SaveState.p2s", path + "_SaveState.p2s.bak", false);
}
fclose(ssFileCheck);
}
StateCopy_SaveToFile(path + "_SaveState.p2s");
}
else {
else
{
sApp.SysExecute();
}
}
return true;
}
// Gracefully close the current recording file
bool InputRecordingFile::Close()
{
if (recordingFile == NULL)
{
return false;
writeHeader();
writeSaveState();
}
WriteHeader();
WriteSaveState();
fclose(recordingFile);
recordingFile = NULL;
filename = "";
return true;
}
bool InputRecordingFile::writeSaveState() {
// Write savestate flag to file
bool InputRecordingFile::WriteSaveState() {
if (recordingFile == NULL)
{
return false;
}
fseek(recordingFile, SEEKPOINT_SAVESTATE, SEEK_SET);
fseek(recordingFile, RecordingSeekpointSaveState, SEEK_SET);
if (fwrite(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1)
{
return false;
}
return true;
}
//----------------------------------
// write frame
//----------------------------------
bool InputRecordingFile::writeKeyBuf(const uint & frame, const uint port, const uint bufIndex, const u8 & buf)
// Write controller input buffer to file (per frame)
bool InputRecordingFile::WriteKeyBuf(const uint & frame, const uint port, const uint bufIndex, const u8 & buf)
{
if (recordingFile == NULL)
{
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)
return false;
if (fwrite(&buf, 1, 1, recordingFile) != 1)
if (fseek(recordingFile, seek, SEEK_SET) != 0
|| fwrite(&buf, 1, 1, recordingFile) != 1)
{
return false;
}
fflush(recordingFile);
return true;
}
//----------------------------------
// read frame
//----------------------------------
bool InputRecordingFile::readKeyBuf(u8 & result,const uint & frame, const uint port, const uint bufIndex)
// Read controller input buffer from file (per frame)
bool InputRecordingFile::ReadKeyBuf(u8 & result,const uint & frame, const uint port, const uint bufIndex)
{
if (recordingFile == NULL)
{
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)
{
return false;
}
if (fread(&result, 1, 1, recordingFile) != 1)
{
return false;
}
return true;
}
//===================================
// pad
//===================================
void InputRecordingFile::getPadData(PadData & result, unsigned long frame)
void InputRecordingFile::GetPadData(PadData & result, unsigned long frame)
{
result.fExistKey = false;
if (recordingFile == NULL)
{
return;
}
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE;
if (fseek(recordingFile, seek, SEEK_SET) != 0)
return;
if (fread(result.buf, 1, BLOCK_DATA_SIZE, recordingFile) == 0)
long seek = GetBlockSeekPoint(frame) + RecordingBlockHeaderSize;
if (fseek(recordingFile, seek, SEEK_SET) != 0
|| fread(result.buf, 1, RecordingBlockDataSize, recordingFile) == 0)
{
return;
}
result.fExistKey = true;
}
@ -163,21 +172,33 @@ void InputRecordingFile::getPadData(PadData & result, unsigned long frame)
bool InputRecordingFile::DeletePadData(unsigned long frame)
{
if (recordingFile == NULL)
{
return false;
}
for (unsigned long i = frame; i < MaxFrame - 1; i++)
{
long seek1 = _getBlockSeekPoint(i+1) + BLOCK_HEADER_SIZE;
long seek2 = _getBlockSeekPoint(i) + BLOCK_HEADER_SIZE;
long seek1 = GetBlockSeekPoint(i+1) + RecordingBlockHeaderSize;
long seek2 = GetBlockSeekPoint(i) + RecordingBlockHeaderSize;
u8 buf[2][18];
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);
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--;
writeMaxFrame();
WriteMaxFrame();
fflush(recordingFile);
return true;
@ -185,29 +206,42 @@ bool InputRecordingFile::DeletePadData(unsigned long frame)
bool InputRecordingFile::InsertPadData(unsigned long frame, const PadData& key)
{
if (recordingFile == NULL)
return false;
if (!key.fExistKey)
if (recordingFile == NULL || !key.fExistKey)
{
return false;
}
for (unsigned long i = MaxFrame - 1; i >= frame; i--)
{
long seek1 = _getBlockSeekPoint(i) + BLOCK_HEADER_SIZE;
long seek2 = _getBlockSeekPoint(i+1) + BLOCK_HEADER_SIZE;
long seek1 = GetBlockSeekPoint(i) + RecordingBlockHeaderSize;
long seek2 = GetBlockSeekPoint(i+1) + RecordingBlockHeaderSize;
u8 buf[2][18];
fseek(recordingFile, seek1, SEEK_SET);
fread(buf, 1, BLOCK_DATA_SIZE, recordingFile);
fseek(recordingFile, seek2, SEEK_SET);
fwrite(buf, 1, BLOCK_DATA_SIZE, recordingFile);
}
int rSize = fread(buf, 1, RecordingBlockDataSize, recordingFile);
if (rSize != RecordingBlockDataSize)
{
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE;
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);
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);
fwrite(key.buf, 1, BLOCK_DATA_SIZE, recordingFile);
int rSize = fwrite(key.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;
}
MaxFrame++;
writeMaxFrame();
WriteMaxFrame();
fflush(recordingFile);
return true;
@ -216,100 +250,149 @@ bool InputRecordingFile::InsertPadData(unsigned long frame, const PadData& key)
bool InputRecordingFile::UpdatePadData(unsigned long frame, const PadData& key)
{
if (recordingFile == NULL)
{
return false;
}
if (!key.fExistKey)
{
return false;
}
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE;
long seek = GetBlockSeekPoint(frame) + RecordingBlockHeaderSize;
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;
}
fflush(recordingFile);
return true;
}
// Verify header of recording file
bool InputRecordingFile::readHeaderAndCheck()
bool InputRecordingFile::ReadHeaderAndCheck()
{
if (recordingFile == NULL) return false;
if (recordingFile == NULL)
{
return false;
}
rewind(recordingFile);
if (fread(&header, sizeof(InputRecordingHeader), 1, recordingFile) != 1) return false;
if (fread(&MaxFrame, 4, 1, recordingFile) != 1) return false;
if (fread(&UndoCount, 4, 1, recordingFile) != 1) return false;
if (fread(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1) return false;
if (savestate.fromSavestate) {
if (fread(&header, sizeof(InputRecordingHeader), 1, recordingFile) != 1
|| fread(&MaxFrame, 4, 1, recordingFile) != 1
|| fread(&UndoCount, 4, 1, recordingFile) != 1
|| fread(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1)
{
return false;
}
if (savestate.fromSavestate)
{
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"));
return false;
}
fclose(ssFileCheck);
StateCopy_LoadFromFile(filename + "_SaveState.p2s");
}
else {
else
{
sApp.SysExecute();
}
// 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));
return false;
}
return true;
}
bool InputRecordingFile::writeHeader()
bool InputRecordingFile::WriteHeader()
{
if (recordingFile == NULL) return false;
if (recordingFile == NULL)
{
return false;
}
rewind(recordingFile);
if (fwrite(&header, sizeof(InputRecordingHeader), 1, recordingFile) != 1) return false;
if (fwrite(&header, sizeof(InputRecordingHeader), 1, recordingFile) != 1)
{
return false;
}
return true;
}
bool InputRecordingFile::writeMaxFrame()
bool InputRecordingFile::WriteMaxFrame()
{
if (recordingFile == NULL)return false;
fseek(recordingFile, SEEKPOINT_FRAMEMAX, SEEK_SET);
if (fwrite(&MaxFrame, 4, 1, recordingFile) != 1) return false;
if (recordingFile == NULL)
{
return false;
}
fseek(recordingFile, RecordingSeekpointFrameMax, SEEK_SET);
if (fwrite(&MaxFrame, 4, 1, recordingFile) != 1)
{
return false;
}
return true;
}
void InputRecordingFile::updateFrameMax(unsigned long frame)
void InputRecordingFile::UpdateFrameMax(unsigned long frame)
{
if (MaxFrame >= frame) {
if (recordingFile == NULL || MaxFrame >= frame)
{
return;
}
MaxFrame = frame;
if (recordingFile == NULL)return ;
fseek(recordingFile, SEEKPOINT_FRAMEMAX, SEEK_SET);
fseek(recordingFile, RecordingSeekpointFrameMax, SEEK_SET);
fwrite(&MaxFrame, 4, 1, recordingFile);
}
void InputRecordingFile::addUndoCount()
void InputRecordingFile::AddUndoCount()
{
UndoCount++;
if (recordingFile == NULL)
{
return;
fseek(recordingFile, SEEKPOINT_UNDOCOUNT, SEEK_SET);
}
fseek(recordingFile, RecordingSeekpointUndoCount, SEEK_SET);
fwrite(&UndoCount, 4, 1, recordingFile);
}
void InputRecordingHeader::setAuthor(wxString _author)
void InputRecordingHeader::SetAuthor(wxString _author)
{
int max = ArraySize(author) - 1;
strncpy(author, _author.c_str(), max);
author[max] = 0;
}
void InputRecordingHeader::setGameName(wxString _gameName)
void InputRecordingHeader::SetGameName(wxString _gameName)
{
int max = ArraySize(gameName) - 1;
strncpy(gameName, _gameName.c_str(), max);
gameName[max] = 0;
}
void InputRecordingHeader::init()
void InputRecordingHeader::Init()
{
memset(author, 0, ArraySize(author));
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;
}

View File

@ -18,6 +18,7 @@
#include "PadData.h"
#include "System.h"
struct InputRecordingHeader
{
u8 version = 1;
@ -26,11 +27,13 @@ struct InputRecordingHeader
char gameName[255] = "";
public:
void setAuthor(wxString author);
void setGameName(wxString cdrom);
void init();
void SetAuthor(wxString author);
void SetGameName(wxString cdrom);
void Init();
};
static const int RecordingHeaderSize = sizeof(InputRecordingHeader) + 4 + 4;
// Contains info about the starting point of the movie
struct InputRecordingSavestate
{
@ -38,8 +41,8 @@ struct InputRecordingSavestate
bool fromSavestate = false;
};
class InputRecordingFile {
class InputRecordingFile
{
public:
InputRecordingFile() {}
~InputRecordingFile() { Close(); }
@ -47,34 +50,42 @@ public:
// Movie File Manipulation
bool Open(const wxString fn, bool fNewOpen, bool fromSaveState);
bool Close();
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 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);
// Controller Data
void getPadData(PadData & result_pad, unsigned long frame);
void GetPadData(PadData & result_pad, unsigned long frame);
bool DeletePadData(unsigned long frame);
bool InsertPadData(unsigned long frame, const PadData& key);
bool UpdatePadData(unsigned long frame, const PadData& key);
// Header
InputRecordingHeader& getHeader() { return header; }
unsigned long& getMaxFrame() { return MaxFrame; }
unsigned long& getUndoCount() { return UndoCount; }
const wxString & getFilename() { return filename; }
InputRecordingHeader& GetHeader();
unsigned long& GetMaxFrame();
unsigned long& GetUndoCount();
const wxString & GetFilename();
bool writeHeader();
bool writeMaxFrame();
bool writeSaveState();
bool WriteHeader();
bool WriteMaxFrame();
bool WriteSaveState();
bool readHeaderAndCheck();
void updateFrameMax(unsigned long frame);
void addUndoCount();
bool ReadHeaderAndCheck();
void UpdateFrameMax(unsigned long frame);
void AddUndoCount();
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
FILE * recordingFile = NULL;
wxString filename = "";
long _getBlockSeekPoint(const long & frame);
long GetBlockSeekPoint(const long & frame);
// Header
InputRecordingHeader header;

View File

@ -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();
}

View File

@ -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;
};

View File

@ -17,17 +17,11 @@
#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"));
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);
@ -36,12 +30,12 @@ NewRecordingFrame::NewRecordingFrame(wxWindow *parent)
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);
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, MenuIds_New_Recording_Frame_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 = new wxChoice(panel, MenuIds_New_Recording_Frame_From, wxDefaultPosition, wxDefaultSize, choices);
m_fromChoice->SetSelection(0);
m_startRecording = new wxButton(panel, wxID_OK, _("Ok"), wxDefaultPosition, wxDefaultSize);
@ -65,17 +59,17 @@ NewRecordingFrame::NewRecordingFrame(wxWindow *parent)
Centre();
}
wxString NewRecordingFrame::getFile() const
wxString NewRecordingFrame::GetFile() const
{
return m_filePicker->GetPath();
}
wxString NewRecordingFrame::getAuthor() const
wxString NewRecordingFrame::GetAuthor() const
{
return m_authorInput->GetValue();
}
int NewRecordingFrame::getFrom() const
int NewRecordingFrame::GetFrom() const
{
return m_fromChoice->GetSelection();
}

View File

@ -18,17 +18,23 @@
#include <wx/wx.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
{
public:
NewRecordingFrame(wxWindow *parent);
wxString getFile() const;
wxString getAuthor() const;
int getFrom() const;
wxString GetFile() const;
wxString GetAuthor() const;
int GetFrom() const;
private:
wxStaticText *m_fileLabel;

View File

@ -19,6 +19,7 @@
#include "ConsoleLogger.h"
#include "PadData.h"
PadData::PadData()
{
// 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
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++)
{
buttons[i] = getNormalButton(port, PadDataNormalButton(i));
buttons[i] = GetNormalButton(port, PadData_NormalButton(i));
}
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++)
{
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)
{
return;
}
wxByte keybit[2];
getKeyBit(keybit, button);
int pressureByteIndex = getPressureByte(button);
GetKeyBit(keybit, button);
int pressureByteIndex = GetPressureByte(button);
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)
{
return false;
}
wxByte keybit[2];
getKeyBit(keybit, button);
int pressureByteIndex = getPressureByte(button);
GetKeyBit(keybit, button);
int pressureByteIndex = GetPressureByte(button);
// If the button is pressed on either controller
bool f1 = (~buf[port][0] & keybit[0])>0;
@ -132,110 +138,195 @@ int PadData::getNormalButton(int port, PadDataNormalButton button) const
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; }
else if (button == LEFT) { keybit[0] = 0b10000000; keybit[1] = 0b00000000; }
else if (button == RIGHT) { keybit[0] = 0b00100000; keybit[1] = 0b00000000; }
else if (button == DOWN) { keybit[0] = 0b01000000; keybit[1] = 0b00000000; }
else if (button == START) { keybit[0] = 0b00001000; keybit[1] = 0b00000000; }
else if (button == SELECT) { keybit[0] = 0b00000001; keybit[1] = 0b00000000; }
else if (button == CROSS) { keybit[0] = 0b00000000; keybit[1] = 0b01000000; }
else if (button == CIRCLE) { keybit[0] = 0b00000000; keybit[1] = 0b00100000; }
else if (button == SQUARE) { keybit[0] = 0b00000000; keybit[1] = 0b10000000; }
else if (button == TRIANGLE) { keybit[0] = 0b00000000; keybit[1] = 0b00010000; }
else if (button == L1) { keybit[0] = 0b00000000; keybit[1] = 0b00000100; }
else if (button == L2) { keybit[0] = 0b00000000; keybit[1] = 0b00000001; }
else if (button == L3) { keybit[0] = 0b00000010; keybit[1] = 0b00000000; }
else if (button == R1) { keybit[0] = 0b00000000; keybit[1] = 0b00001000; }
else if (button == R2) { keybit[0] = 0b00000000; keybit[1] = 0b00000010; }
else if (button == R3) { keybit[0] = 0b00000100; keybit[1] = 0b00000000; }
else { keybit[0] = 0; keybit[1] = 0; }
switch (button)
{
case PadData_NormalButton_LEFT:
keybit[0] = 0b10000000;
keybit[1] = 0b00000000;
break;
case PadData_NormalButton_DOWN:
keybit[0] = 0b01000000;
keybit[1] = 0b00000000;
break;
case PadData_NormalButton_RIGHT:
keybit[0] = 0b00100000;
keybit[1] = 0b00000000;
break;
case PadData_NormalButton_UP:
keybit[0] = 0b00010000;
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 -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
// R - L - U - D - Tri - Sqr - Circle - Cross - L1 - R1 - L2 - R2
if (button == UP)
return 2;
else if (button == LEFT)
return 1;
else if (button == RIGHT)
// R - L - U - D - Tri - Circle - Cross - Sqr - L1 - R1 - L2 - R2
switch (button)
{
case PadData_NormalButton_RIGHT:
return 0;
else if (button == DOWN)
break;
case PadData_NormalButton_LEFT:
return 1;
break;
case PadData_NormalButton_UP:
return 2;
break;
case PadData_NormalButton_DOWN:
return 3;
else if (button == CROSS)
return 6;
else if (button == CIRCLE)
return 5;
else if (button == SQUARE)
return 7;
else if (button == TRIANGLE)
break;
case PadData_NormalButton_TRIANGLE:
return 4;
else if (button == L1)
break;
case PadData_NormalButton_CIRCLE:
return 5;
break;
case PadData_NormalButton_CROSS:
return 6;
break;
case PadData_NormalButton_SQUARE:
return 7;
break;
case PadData_NormalButton_L1:
return 8;
else if (button == L2)
return 10;
else if (button == R1)
break;
case PadData_NormalButton_R1:
return 9;
else if (button == R2)
break;
case PadData_NormalButton_L2:
return 10;
break;
case PadData_NormalButton_R2:
return 11;
else
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++)
{
vectors[i] = getAnalogVector(port, PadDataAnalogVector(i));
vectors[i] = GetAnalogVector(port, PadData_AnalogVector(i));
}
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++)
{
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)
{
return;
}
if (val < 0)
{
val = 0;
}
else if (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)
{
return 0;
}
return buf[port][getAnalogVectorByte(vector)];
return buf[port][GetAnalogVectorByte(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
// RX - RY - LX - LY
if (vector == LEFT_ANALOG_X)
return 4;
else if (vector == LEFT_ANALOG_Y)
return 5;
else if (vector == RIGHT_ANALOG_X)
switch (vector)
{
case PadData_AnalogVector_RIGHT_ANALOG_X:
return 2;
else
break;
case PadData_AnalogVector_RIGHT_ANALOG_Y:
return 3;
break;
case PadData_AnalogVector_LEFT_ANALOG_X:
return 4;
break;
case PadData_AnalogVector_LEFT_ANALOG_Y:
return 5;
break;
default:
return -1;
}
}

View File

@ -16,35 +16,37 @@
#pragma once
#include <map>
#include <vector>
#define PadDataNormalButtonCount 16
enum PadDataNormalButton
static const int PadDataNormalButtonCount = 16;
enum PadData_NormalButton
{
UP,
RIGHT,
LEFT,
DOWN,
CROSS,
CIRCLE,
SQUARE,
TRIANGLE,
L1,
L2,
R1,
R2,
L3,
R3,
SELECT,
START
PadData_NormalButton_UP,
PadData_NormalButton_RIGHT,
PadData_NormalButton_LEFT,
PadData_NormalButton_DOWN,
PadData_NormalButton_CROSS,
PadData_NormalButton_CIRCLE,
PadData_NormalButton_SQUARE,
PadData_NormalButton_TRIANGLE,
PadData_NormalButton_L1,
PadData_NormalButton_L2,
PadData_NormalButton_R1,
PadData_NormalButton_R2,
PadData_NormalButton_L3,
PadData_NormalButton_R3,
PadData_NormalButton_SELECT,
PadData_NormalButton_START
};
#define PadDataAnalogVectorCount 4
enum PadDataAnalogVector
static const int PadDataAnalogVectorCount = 4;
enum PadData_AnalogVector
{
LEFT_ANALOG_X,
LEFT_ANALOG_Y,
RIGHT_ANALOG_X,
RIGHT_ANALOG_Y
PadData_AnalogVector_LEFT_ANALOG_X,
PadData_AnalogVector_LEFT_ANALOG_Y,
PadData_AnalogVector_RIGHT_ANALOG_X,
PadData_AnalogVector_RIGHT_ANALOG_Y
};
struct PadData
@ -57,29 +59,29 @@ public:
u8 buf[2][18];
// 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
int* getNormalButtons(int port) const;
void setNormalButtons(int port, int* buttons);
std::vector<int> GetNormalButtons(int port) const;
void SetNormalButtons(int port, std::vector<int> buttons);
// Analog Vectors
// max left/up : 0
// neutral : 127
// max right/down : 255
int* getAnalogVectors(int port) const;
std::vector<int> GetAnalogVectors(int port) const;
// max left/up : 0
// neutral : 127
// max right/down : 255
void setAnalogVectors(int port, int* vector);
void SetAnalogVectors(int port, std::vector<int> vector);
private:
void setNormalButton(int port, PadDataNormalButton button, int pressure);
int getNormalButton(int port, PadDataNormalButton button) const;
void getKeyBit(wxByte keybit[2], PadDataNormalButton button) const;
int getPressureByte(PadDataNormalButton button) const;
void SetNormalButton(int port, PadData_NormalButton button, int pressure);
int GetNormalButton(int port, PadData_NormalButton button) const;
void GetKeyBit(wxByte keybit[2], PadData_NormalButton button) const;
int GetPressureByte(PadData_NormalButton button) const;
void setAnalogVector(int port, PadDataAnalogVector vector, int val);
int getAnalogVector(int port, PadDataAnalogVector vector) const;
int getAnalogVectorByte(PadDataAnalogVector vector) const;
void SetAnalogVector(int port, PadData_AnalogVector vector, int val);
int GetAnalogVector(int port, PadData_AnalogVector vector) const;
int GetAnalogVectorByte(PadData_AnalogVector vector) const;
};

View File

@ -15,32 +15,31 @@
#include "PrecompiledHeader.h"
#include "GSFrame.h"
#include "MemoryTypes.h"
#include "App.h"
#include "Counters.h"
#include "GSFrame.h"
#include "MemoryTypes.h"
#include "RecordingControls.h"
RecordingControls g_RecordingControls;
// TODO - I think these functions could be named a lot better...
//-----------------------------------------------
// Status on whether or not the current recording is stopped
//-----------------------------------------------
bool RecordingControls::isStop()
bool RecordingControls::HasRecordingStopped()
{
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.
//-----------------------------------------------
void RecordingControls::StartCheck()
void RecordingControls::ResumeCoreThreadIfStarted()
{
if (fStart && CoreThread.IsOpen() && CoreThread.IsPaused()) {
if (fStart && CoreThread.IsOpen() && CoreThread.IsPaused())
{
CoreThread.Resume();
fStart = false;
fPauseState = false;
@ -51,10 +50,12 @@ void RecordingControls::StartCheck()
// 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.
//-----------------------------------------------
void RecordingControls::StopCheck()
void RecordingControls::HandleFrameAdvanceAndStop()
{
if (fFrameAdvance) {
if (stopFrameCount < g_FrameCount) {
if (fFrameAdvance)
{
if (stopFrameCount < g_FrameCount)
{
fFrameAdvance = false;
fStop = true;
stopFrameCount = g_FrameCount;
@ -80,11 +81,11 @@ void RecordingControls::StopCheck()
}
}
bool RecordingControls::GetStopFlag()
{
return (fStop || fFrameAdvance);
}
//----------------------------------
// shortcut key
//----------------------------------
void RecordingControls::FrameAdvance()
{
stopFrameCount = g_FrameCount;
@ -92,22 +93,25 @@ void RecordingControls::FrameAdvance()
fStop = false;
fStart = true;
}
void RecordingControls::TogglePause()
{
fStop = !fStop;
if (fStop == false) {
if (fStop == false)
{
fStart = true;
}
}
void RecordingControls::Pause()
{
fStop = true;
fFrameAdvance = true;
}
void RecordingControls::UnPause()
void RecordingControls::Unpause()
{
fStop = false;
fStart = true;
fFrameAdvance = true;
}

View File

@ -15,13 +15,14 @@
#pragma once
class RecordingControls {
class RecordingControls
{
public:
// Movie controls main functions
bool isStop();
void StartCheck();
void StopCheck();
bool HasRecordingStopped();
void ResumeCoreThreadIfStarted();
void HandleFrameAdvanceAndStop();
// Shortcut Keys
void FrameAdvance();
@ -29,10 +30,10 @@ public:
// Setters
void Pause();
void UnPause();
void Unpause();
// Getters
bool getStopFlag() { return (fStop || fFrameAdvance); }
bool GetStopFlag();
private:
uint stopFrameCount = false;
@ -43,4 +44,5 @@ private:
bool fPauseState = false;
};
extern RecordingControls g_RecordingControls;

View File

@ -18,18 +18,23 @@
#include "RecordingInputManager.h"
#include "InputRecording.h"
RecordingInputManager g_RecordingInput;
RecordingInputManager::RecordingInputManager()
{
for (u8 i = 0; i < 2; i++)
{
virtualPad[i] = false;
}
}
void RecordingInputManager::ControllerInterrupt(u8 & data, u8 & port, u16 & BufCount, u8 buf[])
{
if (port >= 2)
{
return;
}
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
// already handled by InputRecording.cpp
if (BufCount < 3)
{
return;
}
// 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.
if (BufCount <= 4)
buf[BufCount] = buf[BufCount] & pad.buf[port][BufCount - 3];
{
buf[BufCount] = buf[BufCount] & pad.buf[port][bufIndex];
}
// Analog keys (! overrides !)
else if ((BufCount > 4 && BufCount <= 6) && pad.buf[port][BufCount - 3] != 127)
buf[BufCount] = pad.buf[port][BufCount - 3];
else if ((BufCount > 4 && BufCount <= 6) && pad.buf[port][bufIndex] != 127)
{
buf[BufCount] = pad.buf[port][bufIndex];
}
// Pressure sensitivity bytes
else if (BufCount > 6)
buf[BufCount] = pad.buf[port][BufCount - 3];
{
buf[BufCount] = pad.buf[port][bufIndex];
}
// Updating movie file
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;
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;
pad.setAnalogVectors(port, vectors);
pad.SetAnalogVectors(port, vectors);
}
void RecordingInputManager::SetVirtualPadReading(int port, bool read)

View File

@ -17,6 +17,7 @@
#include "PadData.h"
class RecordingInputManager
{
public:
@ -24,9 +25,9 @@ public:
void ControllerInterrupt(u8 &data, u8 &port, u16 & BufCount, u8 buf[]);
// Handles normal keys
void SetButtonState(int port, PadDataNormalButton button, int pressure);
void SetButtonState(int port, PadData_NormalButton button, int pressure);
// 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);
protected:

View File

@ -125,10 +125,12 @@ VirtualPad::VirtualPad(wxWindow* parent, wxWindowID id, const wxString& title, i
void VirtualPad::SetProperties()
{
if (controllerPort == 0) {
if (controllerPort == 0)
{
SetTitle(wxT("Virtual Pad - Port 1"));
}
else {
else
{
SetTitle(wxT("Virtual Pad - Port 2"));
}
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
@ -137,9 +139,13 @@ void VirtualPad::SetProperties()
bool VirtualPad::Show(bool show)
{
if (!wxFrame::Show(show))
{
return false;
}
if (show)
{
g_RecordingInput.SetVirtualPadReading(controllerPort, true);
}
return true;
}
@ -174,7 +180,7 @@ void VirtualPad::OnButtonPress(wxCommandEvent & event)
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)
{
u8 pressure = 0;
if (event.IsChecked()) {
if (event.IsChecked())
{
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());
}
else {
else
{
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)
{
analogVals[spinnerId]->SetValue(event.GetInt());
g_RecordingInput.UpdateAnalog(controllerPort, PadDataAnalogVector(spinnerId), event.GetInt() + 127);
g_RecordingInput.UpdateAnalog(controllerPort, PadData_AnalogVector(spinnerId), event.GetInt() + 127);
}
}

View File

@ -219,15 +219,14 @@ SIO_WRITE sioWriteController(u8 data)
if (g_Conf->EmuOptions.EnableRecordingTools)
{
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);
}
PadData::logPadData(sio.port, sio.bufCount, sio.buf);
PadData::LogPadData(sio.port, sio.bufCount, sio.buf);
}
#endif
break;
}
//Console.WriteLn( "SIO: sent = %02X From pad data = %02X bufCnt %08X ", data, sio.buf[sio.bufCount], sio.bufCount);

View File

@ -142,8 +142,8 @@ SysConsoleLogPack::SysConsoleLogPack()
, iopConsole (&TLD_iopConsole)
, deci2 (&TLD_deci2)
#ifndef DISABLE_RECORDING
, recordingConsole(&TLD_recordingConsole)
, controlInfo(&TLD_controlInfo)
, recordingConsole (&TLD_recordingConsole)
, controlInfo (&TLD_controlInfo)
#endif
{
}

View File

@ -617,7 +617,7 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
#ifndef DISABLE_RECORDING
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
// 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
(handler->*func)(event);

View File

@ -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
static ConsoleLogSource* const ConLogSources[] =
{
@ -294,7 +310,7 @@ static ConsoleLogSource* const ConLogSources[] =
NULL,
(ConsoleLogSource*)&pxConLog_Event,
(ConsoleLogSource*)&pxConLog_Thread,
(ConsoleLogSource*)&SysConsole.sysoutConsole
(ConsoleLogSource*)&SysConsole.sysoutConsole,
NULL,
#ifndef DISABLE_RECORDING
(ConsoleLogSource*)&SysConsole.recordingConsole,
@ -571,6 +587,10 @@ void ConsoleLogFrame::OnLoggingChanged()
{
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
}
}

View File

@ -132,8 +132,10 @@ GSPanel::GSPanel( wxWindow* parent )
#ifndef DISABLE_RECORDING
// Retrieving FrameAdvance Key
for (auto itr = m_Accels->begin(); itr != m_Accels->end(); ++itr) {
if (itr->second->Id == "FrameAdvance") {
for (auto itr = m_Accels->begin(); itr != m_Accels->end(); ++itr)
{
if (itr->second->Id == "FrameAdvance")
{
m_frameAdvanceKey = itr->first;
break;
}
@ -377,14 +379,16 @@ void GSPanel::OnKeyDownOrUp( wxKeyEvent& evt )
#endif
if ((PADopen != NULL) && CoreThread.IsOpen())
{
return;
}
#ifndef DISABLE_RECORDING
if (g_Conf->EmuOptions.EnableRecordingTools)
{
// 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
// circumstances and I'm unsure if there is a place to put this logic
// circumstances
if (evt.GetKeyCode() == m_frameAdvanceKey)
{
return;
@ -727,23 +731,24 @@ void GSFrame::OnUpdateTitle( wxTimerEvent& evt )
#ifndef DISABLE_RECORDING
wxString title;
wxString movieMode;
switch (g_InputRecording.getModeState()) {
case InputRecording::KEY_MOVIE_MODE::RECORD:
switch (g_InputRecording.GetModeState())
{
case INPUT_RECORDING_MODE_RECORD:
movieMode = "Recording";
title = templates.RecordingTemplate;
break;
case InputRecording::KEY_MOVIE_MODE::REPLAY:
case INPUT_RECORDING_MODE_REPLAY:
movieMode = "Replaying";
title = templates.RecordingTemplate;
break;
case InputRecording::KEY_MOVIE_MODE::NONE:
case INPUT_RECORDING_MODE_NONE:
movieMode = "No movie";
title = templates.TitleTemplate;
break;
}
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);
#else
wxString title = templates.TitleTemplate;

View File

@ -18,10 +18,6 @@
#include "AppCommon.h"
#include "CpuUsageProvider.h"
#include "wx/dcbuffer.h"
#include "wx/dcgraph.h"
#include <memory>
@ -59,10 +55,10 @@ public:
GSPanel( wxWindow* parent );
virtual ~GSPanel();
virtual void DoResize();
void DoResize();
void DoShowMouse();
void DirectKeyCommand( wxKeyEvent& evt );
virtual void DirectKeyCommand( const KeyAcceleratorCode& kac );
void DirectKeyCommand( const KeyAcceleratorCode& kac );
protected:
void AppStatusEvent_OnSettingsApplied();
@ -83,6 +79,7 @@ protected:
void UpdateScreensaver();
};
// --------------------------------------------------------------------------------------
// GSFrame
// --------------------------------------------------------------------------------------

View File

@ -467,48 +467,138 @@ namespace Implementations
void FrameAdvance()
{
if (g_Conf->EmuOptions.EnableRecordingTools)
{
g_RecordingControls.FrameAdvance();
}
}
void TogglePause()
{
if (g_Conf->EmuOptions.EnableRecordingTools)
{
g_RecordingControls.TogglePause();
}
}
void InputRecordingModeToggle()
{
if (g_Conf->EmuOptions.EnableRecordingTools)
{
g_InputRecording.RecordModeToggle();
}
}
void States_SaveSlot(int slot)
{
States_SetCurrentSlot(slot);
States_FreezeCurrentSlot();
}
void States_LoadSlot(int slot)
{
States_SetCurrentSlot(slot);
States_DefrostCurrentSlot();
}
void States_SaveSlot0() { States_SaveSlot(0); }
void States_SaveSlot1() { States_SaveSlot(1); }
void States_SaveSlot2() { States_SaveSlot(2); }
void States_SaveSlot3() { States_SaveSlot(3); }
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); }
void States_SaveSlot0()
{
States_SaveSlot(0);
}
void States_SaveSlot1()
{
States_SaveSlot(1);
}
void States_SaveSlot2()
{
States_SaveSlot(2);
}
void States_SaveSlot3()
{
States_SaveSlot(3);
}
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
}

View File

@ -372,7 +372,7 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
SetMenuBar( &m_menubar );
#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)
{
m_menubar.Append(&m_menuRecording, _("&Recording"));

View File

@ -498,10 +498,12 @@ void MainEmuFrame::Menu_EnableRecordingTools_Click(wxCommandEvent&)
{
bool checked = GetMenuBar()->IsChecked(MenuId_EnableRecordingTools);
// 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"
"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;
m_menuSys.FindChildItem(MenuId_EnableRecordingTools)->Check(false);
}
@ -515,12 +517,14 @@ void MainEmuFrame::Menu_EnableRecordingTools_Click(wxCommandEvent&)
else
{
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;
SysConsole.recordingConsole.Enabled = checked;
ConsoleLogFrame* proglog = wxGetApp().GetProgramLog();
proglog->UpdateLogList();
ConsoleLogFrame* progLog = wxGetApp().GetProgramLog();
progLog->UpdateLogList();
AppApplySettings();
AppSaveSettings();
}
@ -568,11 +572,11 @@ void MainEmuFrame::Menu_LoadStateFromFile_Click(wxCommandEvent &event)
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
if (loadStateDialog.ShowModal() == wxID_CANCEL)
{
return;
}
wxString path = loadStateDialog.GetPath();
Console.WriteLn(path);
StateCopy_LoadFromFile(path);
}
@ -582,11 +586,11 @@ void MainEmuFrame::Menu_SaveStateToFile_Click(wxCommandEvent &event)
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
if (saveStateDialog.ShowModal() == wxID_CANCEL)
{
return;
}
wxString path = saveStateDialog.GetPath();
Console.WriteLn(path);
StateCopy_SaveToFile(path);
}
@ -706,47 +710,70 @@ void MainEmuFrame::Menu_Capture_Video_Stop_Click(wxCommandEvent &event)
void MainEmuFrame::VideoCaptureUpdate()
{
GetMTGS().WaitGS(); // make sure GS is in sync with the audio stream when we start.
if (m_capturingVideo) {
if (m_capturingVideo)
{
// start recording
// 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)
bool needsMainFrameEnable = false;
if (GetMainFramePtr() && GetMainFramePtr()->IsEnabled()) {
if (GetMainFramePtr() && GetMainFramePtr()->IsEnabled())
{
needsMainFrameEnable = true;
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.
if (GSsetupRecording(m_capturingVideo, NULL)) {
if (SPU2setupRecording) SPU2setupRecording(m_capturingVideo, NULL);
if (GSsetupRecording(m_capturingVideo, NULL))
{
if (SPU2setupRecording)
{
SPU2setupRecording(m_capturingVideo, NULL);
}
else {
}
else
{
// recording dialog canceled by the user. align our state
m_capturingVideo = false;
}
}
else {
else
{
// the GS doesn't support recording.
if (SPU2setupRecording) SPU2setupRecording(m_capturingVideo, NULL);
if (SPU2setupRecording)
{
SPU2setupRecording(m_capturingVideo, NULL);
}
}
if (GetMainFramePtr() && needsMainFrameEnable)
{
GetMainFramePtr()->Enable();
}
}
else {
else
{
// stop recording
if (GSsetupRecording) GSsetupRecording(m_capturingVideo, NULL);
if (SPU2setupRecording) SPU2setupRecording(m_capturingVideo, NULL);
if (GSsetupRecording)
{
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_Stop)->Enable(true);
}
else {
else
{
m_submenuVideoCapture.FindItem(MenuId_Capture_Video_Record)->Enable(true);
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)
{
if (!CoreThread.IsOpen())
{
return;
}
GSmakeSnapshot(g_Conf->Folders.Snapshots.ToAscii());
}
@ -772,18 +801,19 @@ void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent &event)
return;
}
// 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");
return;
}
g_InputRecording.Create(NewRecordingFrame->getFile(), true, NewRecordingFrame->getAuthor());
g_InputRecording.Create(NewRecordingFrame->GetFile(), true, NewRecordingFrame->GetAuthor());
}
// 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);
@ -795,7 +825,10 @@ void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent &event)
g_InputRecording.Stop();
wxFileDialog openFileDialog(this, _("Select P2M2 record file."), L"", L"",
L"p2m2 file(*.p2m2)|*.p2m2", wxFD_OPEN);
if (openFileDialog.ShowModal() == wxID_CANCEL) return;
if (openFileDialog.ShowModal() == wxID_CANCEL)
{
return;
}
wxString path = openFileDialog.GetPath();
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)
{
VirtualPad *vp;
VirtualPad *vp = NULL;
if (event.GetId() == MenuId_Recording_VirtualPad_Port0)
{
vp = wxGetApp().GetVirtualPadPtr(0);
}
else if (event.GetId() == MenuId_Recording_VirtualPad_Port1)
{
vp = wxGetApp().GetVirtualPadPtr(1);
if (vp)
}
if (vp != NULL)
{
vp->Show();
}
}
#endif