input-rec: remove input recording code from wx-related source
|
@ -841,10 +841,9 @@ void cdvdReset()
|
||||||
|
|
||||||
// If we are recording, always use the same RTC setting
|
// If we are recording, always use the same RTC setting
|
||||||
// for games that use the RTC to seed their RNG -- this is very important to be the same everytime!
|
// for games that use the RTC to seed their RNG -- this is very important to be the same everytime!
|
||||||
#ifndef PCSX2_CORE
|
bool input_recording_active = false;
|
||||||
const bool input_recording_active = g_InputRecording.IsActive();
|
#ifdef PCSX2_CORE
|
||||||
#else
|
input_recording_active = g_InputRecording.isActive();
|
||||||
const bool input_recording_active = g_InputRecording.isActive();
|
|
||||||
#endif
|
#endif
|
||||||
if (input_recording_active)
|
if (input_recording_active)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1390,12 +1390,8 @@ set(pcsx2RecordingSources
|
||||||
${rec_src}/InputRecording.cpp
|
${rec_src}/InputRecording.cpp
|
||||||
${rec_src}/InputRecordingControls.cpp
|
${rec_src}/InputRecordingControls.cpp
|
||||||
${rec_src}/InputRecordingFile.cpp
|
${rec_src}/InputRecordingFile.cpp
|
||||||
${rec_src}/NewRecordingFrame.cpp
|
|
||||||
${rec_src}/PadData.cpp
|
${rec_src}/PadData.cpp
|
||||||
${rec_src}/Utilities/InputRecordingLogger.cpp
|
${rec_src}/Utilities/InputRecordingLogger.cpp
|
||||||
${rec_vp_src}/VirtualPad.cpp
|
|
||||||
${rec_vp_src}/VirtualPadData.cpp
|
|
||||||
${rec_vp_src}/VirtualPadResources.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Recording headers
|
# Recording headers
|
||||||
|
@ -1403,38 +1399,8 @@ set(pcsx2RecordingHeaders
|
||||||
${rec_src}/InputRecording.h
|
${rec_src}/InputRecording.h
|
||||||
${rec_src}/InputRecordingControls.h
|
${rec_src}/InputRecordingControls.h
|
||||||
${rec_src}/InputRecordingFile.h
|
${rec_src}/InputRecordingFile.h
|
||||||
${rec_src}/NewRecordingFrame.h
|
|
||||||
${rec_src}/PadData.h
|
${rec_src}/PadData.h
|
||||||
${rec_src}/Utilities/InputRecordingLogger.h
|
${rec_src}/Utilities/InputRecordingLogger.h
|
||||||
${rec_vp_src}/VirtualPad.h
|
|
||||||
${rec_vp_src}/VirtualPadData.h
|
|
||||||
${rec_vp_src}/VirtualPadResources.h
|
|
||||||
)
|
|
||||||
|
|
||||||
# Warning: the declaration of the .h are mandatory in case of resources files. It will ensure the creation
|
|
||||||
# from the bin2cpp tools at the right moment (ie .h must be created before the pcsx2 compilation)
|
|
||||||
# Recording - VirtualPad resources headers
|
|
||||||
set(res_rec_vp_src "${CMAKE_SOURCE_DIR}/pcsx2/Recording/VirtualPad/img")
|
|
||||||
set(pcsx2RecordingVirtualPadResources
|
|
||||||
${res_rec_vp_src}/circlePressed.h
|
|
||||||
${res_rec_vp_src}/controllerFull.h
|
|
||||||
${res_rec_vp_src}/controllerHalf.h
|
|
||||||
${res_rec_vp_src}/controllerThreeQuarters.h
|
|
||||||
${res_rec_vp_src}/crossPressed.h
|
|
||||||
${res_rec_vp_src}/downPressed.h
|
|
||||||
${res_rec_vp_src}/l1Pressed.h
|
|
||||||
${res_rec_vp_src}/l2Pressed.h
|
|
||||||
${res_rec_vp_src}/l3Pressed.h
|
|
||||||
${res_rec_vp_src}/leftPressed.h
|
|
||||||
${res_rec_vp_src}/r1Pressed.h
|
|
||||||
${res_rec_vp_src}/r2Pressed.h
|
|
||||||
${res_rec_vp_src}/r3Pressed.h
|
|
||||||
${res_rec_vp_src}/rightPressed.h
|
|
||||||
${res_rec_vp_src}/selectPressed.h
|
|
||||||
${res_rec_vp_src}/squarePressed.h
|
|
||||||
${res_rec_vp_src}/startPressed.h
|
|
||||||
${res_rec_vp_src}/trianglePressed.h
|
|
||||||
${res_rec_vp_src}/upPressed.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# System headers
|
# System headers
|
||||||
|
@ -1737,18 +1703,6 @@ if(NOT PCSX2_CORE)
|
||||||
COMMAND ${BIN2CPP} "${res_src}/${res_file}.png" "${res_bin}/${res_file}"
|
COMMAND ${BIN2CPP} "${res_src}/${res_file}.png" "${res_bin}/${res_file}"
|
||||||
)
|
)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
### Generate Recording resource files
|
|
||||||
### Drop them into the folder alongside the png files
|
|
||||||
foreach(res_file IN ITEMS
|
|
||||||
circlePressed controllerFull controllerHalf controllerThreeQuarters crossPressed downPressed l1Pressed l2Pressed l3Pressed leftPressed
|
|
||||||
r1Pressed r2Pressed r3Pressed rightPressed selectPressed squarePressed startPressed trianglePressed upPressed)
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT "${res_rec_vp_src}/${res_file}.h"
|
|
||||||
DEPENDS ${BIN2CPPDEP} "${res_rec_vp_src}/${res_file}.png"
|
|
||||||
COMMAND ${BIN2CPP} "${res_rec_vp_src}/${res_file}.png" "${res_rec_vp_src}/${res_file}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# additonal include directories
|
# additonal include directories
|
||||||
|
|
|
@ -608,15 +608,6 @@ static __fi void frameLimit()
|
||||||
|
|
||||||
static __fi void VSyncStart(u32 sCycle)
|
static __fi void VSyncStart(u32 sCycle)
|
||||||
{
|
{
|
||||||
if (EmuConfig.EnableRecordingTools)
|
|
||||||
{
|
|
||||||
// It is imperative that any frame locking that must happen occurs before Vsync is started
|
|
||||||
// Not doing so would sacrifice a frame of a savestate-based recording when loading any savestate
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
g_InputRecordingControls.HandlePausingAndLocking();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef PCSX2_CORE
|
#ifdef PCSX2_CORE
|
||||||
// Update vibration at the end of a frame.
|
// Update vibration at the end of a frame.
|
||||||
PAD::Update();
|
PAD::Update();
|
||||||
|
@ -676,13 +667,6 @@ static __fi void GSVSync()
|
||||||
|
|
||||||
static __fi void VSyncEnd(u32 sCycle)
|
static __fi void VSyncEnd(u32 sCycle)
|
||||||
{
|
{
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
if (EmuConfig.EnableRecordingTools)
|
|
||||||
{
|
|
||||||
g_InputRecordingControls.CheckPauseStatus();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(EmuConfig.Trace.Enabled && EmuConfig.Trace.EE.m_EnableAll)
|
if(EmuConfig.Trace.Enabled && EmuConfig.Trace.EE.m_EnableAll)
|
||||||
SysTrace.EE.Counters.Write( " ================ EE COUNTER VSYNC END (frame: %d) ================", g_FrameCount );
|
SysTrace.EE.Counters.Write( " ================ EE COUNTER VSYNC END (frame: %d) ================", g_FrameCount );
|
||||||
|
|
||||||
|
|
|
@ -15,24 +15,8 @@
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
// TODO - Vaser - kill with wxWidgets
|
|
||||||
|
|
||||||
#include "common/StringUtil.h"
|
|
||||||
#include "SaveState.h"
|
#include "SaveState.h"
|
||||||
#include "Counters.h"
|
#include "Counters.h"
|
||||||
#include "SaveState.h"
|
|
||||||
|
|
||||||
#include "gui/App.h"
|
|
||||||
#include "gui/AppSaveStates.h"
|
|
||||||
#include "DebugTools/Debug.h"
|
|
||||||
#include "GameDatabase.h"
|
|
||||||
|
|
||||||
#include "InputRecording.h"
|
|
||||||
#include "InputRecordingControls.h"
|
|
||||||
#include "Utilities/InputRecordingLogger.h"
|
|
||||||
|
|
||||||
#include <fmt/format.h>
|
|
||||||
|
|
||||||
void SaveStateBase::InputRecordingFreeze()
|
void SaveStateBase::InputRecordingFreeze()
|
||||||
{
|
{
|
||||||
|
@ -40,430 +24,9 @@ void SaveStateBase::InputRecordingFreeze()
|
||||||
// CHANGING THIS WILL BREAK BACKWARDS COMPATIBILITY ON SAVESTATES
|
// CHANGING THIS WILL BREAK BACKWARDS COMPATIBILITY ON SAVESTATES
|
||||||
FreezeTag("InputRecording");
|
FreezeTag("InputRecording");
|
||||||
Freeze(g_FrameCount);
|
Freeze(g_FrameCount);
|
||||||
|
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
|
||||||
{
|
|
||||||
// Loading a save-state is an asynchronous task. If we are playing a recording
|
|
||||||
// that starts from a savestate (not power-on) and the starting (pcsx2 internal) frame
|
|
||||||
// marker has not been set (which comes from the save-state), we initialize it.
|
|
||||||
if (g_InputRecording.IsInitialLoad())
|
|
||||||
g_InputRecording.SetupInitialState(g_FrameCount);
|
|
||||||
else if (g_InputRecording.IsActive() && IsLoading())
|
|
||||||
g_InputRecording.SetFrameCounter(g_FrameCount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputRecording g_InputRecording;
|
#ifdef PCSX2_CORE
|
||||||
|
|
||||||
InputRecording::InputRecordingPad::InputRecordingPad()
|
|
||||||
{
|
|
||||||
padData = new PadData;
|
|
||||||
}
|
|
||||||
|
|
||||||
InputRecording::InputRecordingPad::~InputRecordingPad()
|
|
||||||
{
|
|
||||||
delete padData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::InitVirtualPadWindows(wxWindow* parent)
|
|
||||||
{
|
|
||||||
for (int port = 0; port < 2; ++port)
|
|
||||||
if (!pads[port].virtualPad)
|
|
||||||
pads[port].virtualPad = new VirtualPad(parent, port, g_Conf->inputRecording);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::ShowVirtualPad(const int port)
|
|
||||||
{
|
|
||||||
pads[port].virtualPad->Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::RecordingReset()
|
|
||||||
{
|
|
||||||
// Booting is an asynchronous task. If we are playing a recording
|
|
||||||
// that starts from power-on and the starting (pcsx2 internal) frame
|
|
||||||
// marker has not been set, we initialize it.
|
|
||||||
if (g_InputRecording.IsInitialLoad())
|
|
||||||
g_InputRecording.SetupInitialState(0);
|
|
||||||
else if (g_InputRecording.IsActive())
|
|
||||||
{
|
|
||||||
g_InputRecording.SetFrameCounter(0);
|
|
||||||
g_InputRecordingControls.Lock(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
g_InputRecordingControls.Resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::ControllerInterrupt(u8 port, size_t fifoSize, u8 dataIn, u8 dataOut)
|
|
||||||
{
|
|
||||||
// TODO - Multi-Tap Support
|
|
||||||
|
|
||||||
if (fifoSize == 1)
|
|
||||||
fInterruptFrame = dataIn == READ_DATA_AND_VIBRATE_FIRST_BYTE;
|
|
||||||
else if (fifoSize == 2)
|
|
||||||
{
|
|
||||||
if (dataOut != READ_DATA_AND_VIBRATE_SECOND_BYTE)
|
|
||||||
fInterruptFrame = false;
|
|
||||||
}
|
|
||||||
else if (fInterruptFrame)
|
|
||||||
{
|
|
||||||
u8& bufVal = dataOut;
|
|
||||||
const u16 bufIndex = fifoSize - 3;
|
|
||||||
if (state == InputRecordingMode::Replaying)
|
|
||||||
{
|
|
||||||
if (frameCounter >= 0 && frameCounter < INT_MAX)
|
|
||||||
{
|
|
||||||
if (!inputRecordingData.ReadKeyBuffer(bufVal, frameCounter, port, bufIndex))
|
|
||||||
InputRec::consoleLog(fmt::format("Failed to read input data at frame {}", frameCounter));
|
|
||||||
|
|
||||||
// Update controller data state for future VirtualPad / logging usage.
|
|
||||||
pads[port].padData->UpdateControllerData(bufIndex, bufVal);
|
|
||||||
|
|
||||||
if (pads[port].virtualPad->IsShown())
|
|
||||||
pads[port].virtualPad->UpdateControllerData(bufIndex, pads[port].padData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Update controller data state for future VirtualPad / logging usage.
|
|
||||||
pads[port].padData->UpdateControllerData(bufIndex, bufVal);
|
|
||||||
|
|
||||||
// Commit the byte to the movie file if we are recording
|
|
||||||
if (state == InputRecordingMode::Recording)
|
|
||||||
{
|
|
||||||
if (frameCounter >= 0)
|
|
||||||
{
|
|
||||||
// If the VirtualPad updated the PadData, we have to update the buffer
|
|
||||||
// before committing it to the recording / sending it to the game
|
|
||||||
if (pads[port].virtualPad->IsShown() && pads[port].virtualPad->UpdateControllerData(bufIndex, pads[port].padData))
|
|
||||||
bufVal = pads[port].padData->PollControllerData(bufIndex);
|
|
||||||
|
|
||||||
if (incrementUndo)
|
|
||||||
{
|
|
||||||
inputRecordingData.IncrementUndoCount();
|
|
||||||
incrementUndo = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frameCounter < INT_MAX && !inputRecordingData.WriteKeyBuffer(frameCounter, port, bufIndex, bufVal))
|
|
||||||
InputRec::consoleLog(fmt::format("Failed to write input data at frame {}", frameCounter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the VirtualPad updated the PadData, we have to update the buffer
|
|
||||||
// before sending it to the game
|
|
||||||
else if (pads[port].virtualPad && pads[port].virtualPad->IsShown() && pads[port].virtualPad->UpdateControllerData(bufIndex, pads[port].padData))
|
|
||||||
bufVal = pads[port].padData->PollControllerData(bufIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 InputRecording::GetFrameCounter()
|
|
||||||
{
|
|
||||||
return frameCounter;
|
|
||||||
}
|
|
||||||
|
|
||||||
InputRecordingFile& InputRecording::GetInputRecordingData()
|
|
||||||
{
|
|
||||||
return inputRecordingData;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 InputRecording::GetStartingFrame()
|
|
||||||
{
|
|
||||||
return startingFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::IncrementFrameCounter()
|
|
||||||
{
|
|
||||||
if (frameCounter < INT_MAX)
|
|
||||||
{
|
|
||||||
frameCounter++;
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case InputRecordingMode::Recording:
|
|
||||||
inputRecordingData.SetTotalFrames(frameCounter);
|
|
||||||
[[fallthrough]];
|
|
||||||
case InputRecordingMode::Replaying:
|
|
||||||
if (frameCounter == inputRecordingData.GetTotalFrames())
|
|
||||||
incrementUndo = false;
|
|
||||||
break;
|
|
||||||
case InputRecordingMode::NotActive: // Does nothing but keep GCC happy.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::LogAndRedraw()
|
|
||||||
{
|
|
||||||
for (u8 port = 0; port < 2; port++)
|
|
||||||
{
|
|
||||||
pads[port].padData->LogPadData(port);
|
|
||||||
// As well as re-render the virtual pad UI, if applicable
|
|
||||||
// - Don't render if it's minimized
|
|
||||||
if (pads[port].virtualPad->IsShown() && !pads[port].virtualPad->IsIconized())
|
|
||||||
pads[port].virtualPad->Redraw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecording::IsInterruptFrame()
|
|
||||||
{
|
|
||||||
return fInterruptFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecording::IsActive()
|
|
||||||
{
|
|
||||||
return state != InputRecordingMode::NotActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecording::IsInitialLoad()
|
|
||||||
{
|
|
||||||
return initialLoad;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecording::IsReplaying()
|
|
||||||
{
|
|
||||||
return state == InputRecordingMode::Replaying;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecording::IsRecording()
|
|
||||||
{
|
|
||||||
return state == InputRecordingMode::Recording;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString InputRecording::RecordingModeTitleSegment()
|
|
||||||
{
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case InputRecordingMode::Recording:
|
|
||||||
return wxString("Recording");
|
|
||||||
case InputRecordingMode::Replaying:
|
|
||||||
return wxString("Replaying");
|
|
||||||
default:
|
|
||||||
return wxString("No Movie");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::SetToRecordMode()
|
|
||||||
{
|
|
||||||
state = InputRecordingMode::Recording;
|
|
||||||
pads[CONTROLLER_PORT_ONE].virtualPad->SetReadOnlyMode(false);
|
|
||||||
pads[CONTROLLER_PORT_TWO].virtualPad->SetReadOnlyMode(false);
|
|
||||||
InputRec::log("Record mode ON");
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::SetToReplayMode()
|
|
||||||
{
|
|
||||||
state = InputRecordingMode::Replaying;
|
|
||||||
pads[CONTROLLER_PORT_ONE].virtualPad->SetReadOnlyMode(true);
|
|
||||||
pads[CONTROLLER_PORT_TWO].virtualPad->SetReadOnlyMode(true);
|
|
||||||
InputRec::log("Replay mode ON");
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::SetFrameCounter(u32 newGFrameCount)
|
|
||||||
{
|
|
||||||
if (newGFrameCount > startingFrame + (u32)inputRecordingData.GetTotalFrames())
|
|
||||||
{
|
|
||||||
InputRec::consoleLog("Warning, you've loaded PCSX2 emulation to a point after the end of the original recording. This should be avoided.");
|
|
||||||
InputRec::consoleLog("Savestate's framecount has been ignored.");
|
|
||||||
frameCounter = inputRecordingData.GetTotalFrames();
|
|
||||||
if (state == InputRecordingMode::Replaying)
|
|
||||||
SetToRecordMode();
|
|
||||||
incrementUndo = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (newGFrameCount < startingFrame)
|
|
||||||
{
|
|
||||||
InputRec::consoleLog("Warning, you've loaded PCSX2 emulation to a point before the start of the original recording. This should be avoided.");
|
|
||||||
if (state == InputRecordingMode::Recording)
|
|
||||||
SetToReplayMode();
|
|
||||||
}
|
|
||||||
else if (newGFrameCount == 0 && state == InputRecordingMode::Recording)
|
|
||||||
SetToReplayMode();
|
|
||||||
frameCounter = newGFrameCount - (s32)startingFrame;
|
|
||||||
incrementUndo = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::SetupInitialState(u32 newStartingFrame)
|
|
||||||
{
|
|
||||||
startingFrame = newStartingFrame;
|
|
||||||
if (state != InputRecordingMode::Replaying)
|
|
||||||
{
|
|
||||||
InputRec::log("Started new input recording");
|
|
||||||
InputRec::consoleLog(fmt::format("Filename {}", inputRecordingData.GetFilename().ToUTF8()));
|
|
||||||
SetToRecordMode();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Check if the current game matches with the one used to make the original recording
|
|
||||||
if (!g_Conf->CurrentIso.IsEmpty())
|
|
||||||
if (resolveGameName() != inputRecordingData.GetHeader().gameName)
|
|
||||||
InputRec::consoleLog("Input recording was possibly constructed for a different game.");
|
|
||||||
|
|
||||||
incrementUndo = true;
|
|
||||||
InputRec::log("Replaying input recording");
|
|
||||||
InputRec::consoleMultiLog({fmt::format("File: {}", inputRecordingData.GetFilename().ToUTF8()),
|
|
||||||
fmt::format("PCSX2 Version Used: {}", std::string(inputRecordingData.GetHeader().emu)),
|
|
||||||
fmt::format("Recording File Version: {}", inputRecordingData.GetHeader().version),
|
|
||||||
fmt::format("Associated Game Name or ISO Filename: {}", std::string(inputRecordingData.GetHeader().gameName)),
|
|
||||||
fmt::format("Author: {}", inputRecordingData.GetHeader().author),
|
|
||||||
fmt::format("Total Frames: {}", inputRecordingData.GetTotalFrames()),
|
|
||||||
fmt::format("Undo Count: {}", inputRecordingData.GetUndoCount())});
|
|
||||||
SetToReplayMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputRecordingData.FromSaveState())
|
|
||||||
InputRec::consoleLog(fmt::format("Internal Starting Frame: {}", startingFrame));
|
|
||||||
frameCounter = 0;
|
|
||||||
initialLoad = false;
|
|
||||||
g_InputRecordingControls.Lock(startingFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::FailedSavestate()
|
|
||||||
{
|
|
||||||
InputRec::consoleLog(fmt::format("{} is not compatible with this version of PCSX2", savestate.ToUTF8()));
|
|
||||||
InputRec::consoleLog(fmt::format("Original PCSX2 version used: {}", inputRecordingData.GetHeader().emu));
|
|
||||||
inputRecordingData.Close();
|
|
||||||
initialLoad = false;
|
|
||||||
state = InputRecordingMode::NotActive;
|
|
||||||
g_InputRecordingControls.Resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::Stop()
|
|
||||||
{
|
|
||||||
state = InputRecordingMode::NotActive;
|
|
||||||
pads[CONTROLLER_PORT_ONE].virtualPad->SetReadOnlyMode(false);
|
|
||||||
pads[CONTROLLER_PORT_TWO].virtualPad->SetReadOnlyMode(false);
|
|
||||||
incrementUndo = false;
|
|
||||||
if (inputRecordingData.Close())
|
|
||||||
InputRec::log("Input recording stopped");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecording::Create(wxString fileName, const bool fromSaveState, wxString authorName)
|
|
||||||
{
|
|
||||||
if (!inputRecordingData.OpenNew(fileName, fromSaveState))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
initialLoad = true;
|
|
||||||
state = InputRecordingMode::Recording;
|
|
||||||
if (fromSaveState)
|
|
||||||
{
|
|
||||||
savestate = fileName + "_SaveState.p2s";
|
|
||||||
if (wxFileExists(savestate))
|
|
||||||
wxCopyFile(savestate, savestate + ".bak", true);
|
|
||||||
StateCopy_SaveToFile(savestate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sApp.SysExecute(g_Conf->CdvdSource);
|
|
||||||
|
|
||||||
// Set emulator version
|
|
||||||
inputRecordingData.GetHeader().SetEmulatorVersion();
|
|
||||||
|
|
||||||
// Set author name
|
|
||||||
if (!authorName.IsEmpty())
|
|
||||||
inputRecordingData.GetHeader().SetAuthor(authorName);
|
|
||||||
|
|
||||||
// Set Game Name
|
|
||||||
inputRecordingData.GetHeader().SetGameName(resolveGameName());
|
|
||||||
// Write header contents
|
|
||||||
inputRecordingData.WriteHeader();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecording::Play(wxWindow* parent, wxString filename)
|
|
||||||
{
|
|
||||||
if (!inputRecordingData.OpenExisting(filename))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Either load the savestate, or restart the game
|
|
||||||
if (inputRecordingData.FromSaveState())
|
|
||||||
{
|
|
||||||
if (!GetCoreThread().IsOpen())
|
|
||||||
{
|
|
||||||
InputRec::consoleLog("Game is not open, aborting playing input recording which starts on a save-state.");
|
|
||||||
inputRecordingData.Close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
savestate = inputRecordingData.GetFilename() + "_SaveState.p2s";
|
|
||||||
if (!wxFileExists(savestate))
|
|
||||||
{
|
|
||||||
wxFileDialog loadStateDialog(parent, _("Select the savestate that will accompany this recording"), L"", L"",
|
|
||||||
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
|
|
||||||
if (loadStateDialog.ShowModal() == wxID_CANCEL)
|
|
||||||
{
|
|
||||||
InputRec::consoleLog(fmt::format("Could not locate savestate file at location - {}", savestate.ToUTF8()));
|
|
||||||
InputRec::log("Savestate load failed");
|
|
||||||
inputRecordingData.Close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
savestate = loadStateDialog.GetPath();
|
|
||||||
InputRec::consoleLog(fmt::format("Base savestate set to {}", savestate.ToUTF8()));
|
|
||||||
}
|
|
||||||
state = InputRecordingMode::Replaying;
|
|
||||||
initialLoad = true;
|
|
||||||
StateCopy_LoadFromFile(savestate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state = InputRecordingMode::Replaying;
|
|
||||||
initialLoad = true;
|
|
||||||
sApp.SysExecute(g_Conf->CdvdSource);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecording::GoToFirstFrame(wxWindow* parent)
|
|
||||||
{
|
|
||||||
if (inputRecordingData.FromSaveState())
|
|
||||||
{
|
|
||||||
if (!wxFileExists(savestate))
|
|
||||||
{
|
|
||||||
const bool initiallyPaused = g_InputRecordingControls.IsPaused();
|
|
||||||
|
|
||||||
if (!initiallyPaused)
|
|
||||||
g_InputRecordingControls.PauseImmediately();
|
|
||||||
|
|
||||||
InputRec::consoleLog(fmt::format("Could not locate savestate file at location - {}\n", savestate.ToUTF8()));
|
|
||||||
wxFileDialog loadStateDialog(parent, _("Select a savestate to accompany the recording with"), L"", L"",
|
|
||||||
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
|
|
||||||
int result = loadStateDialog.ShowModal();
|
|
||||||
if (!initiallyPaused)
|
|
||||||
g_InputRecordingControls.Resume();
|
|
||||||
|
|
||||||
if (result == wxID_CANCEL)
|
|
||||||
{
|
|
||||||
InputRec::log("Savestate load cancelled");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
savestate = loadStateDialog.GetPath();
|
|
||||||
InputRec::consoleLog(fmt::format("Base savestate swapped to {}", savestate.ToUTF8()));
|
|
||||||
}
|
|
||||||
StateCopy_LoadFromFile(savestate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sApp.SysExecute(g_Conf->CdvdSource);
|
|
||||||
|
|
||||||
if (IsRecording())
|
|
||||||
SetToReplayMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString InputRecording::resolveGameName()
|
|
||||||
{
|
|
||||||
std::string gameName;
|
|
||||||
const std::string gameKey(SysGetDiscID());
|
|
||||||
if (!gameKey.empty())
|
|
||||||
{
|
|
||||||
auto game = GameDatabase::findGame(gameKey);
|
|
||||||
if (game)
|
|
||||||
{
|
|
||||||
gameName = game->name;
|
|
||||||
gameName += " (" + game->region + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return !gameName.empty() ? StringUtil::UTF8StringToWxString(gameName) : Path::GetFilename(g_Conf->CurrentIso);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "InputRecording.h"
|
#include "InputRecording.h"
|
||||||
|
|
||||||
|
@ -472,7 +35,6 @@ wxString InputRecording::resolveGameName()
|
||||||
|
|
||||||
#include "common/FileSystem.h"
|
#include "common/FileSystem.h"
|
||||||
#include "common/StringUtil.h"
|
#include "common/StringUtil.h"
|
||||||
#include "SaveState.h"
|
|
||||||
#include "Counters.h"
|
#include "Counters.h"
|
||||||
#include "SaveState.h"
|
#include "SaveState.h"
|
||||||
#include "VMManager.h"
|
#include "VMManager.h"
|
||||||
|
@ -481,14 +43,6 @@ wxString InputRecording::resolveGameName()
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
#include "GS.h"
|
#include "GS.h"
|
||||||
|
|
||||||
void SaveStateBase::InputRecordingFreeze()
|
|
||||||
{
|
|
||||||
// NOTE - BE CAREFUL
|
|
||||||
// CHANGING THIS WILL BREAK BACKWARDS COMPATIBILITY ON SAVESTATES
|
|
||||||
FreezeTag("InputRecording");
|
|
||||||
Freeze(g_FrameCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
InputRecording g_InputRecording;
|
InputRecording g_InputRecording;
|
||||||
|
|
||||||
bool InputRecording::create(const std::string& fileName, const bool fromSaveState, const std::string& authorName)
|
bool InputRecording::create(const std::string& fileName, const bool fromSaveState, const std::string& authorName)
|
||||||
|
@ -633,7 +187,8 @@ void InputRecording::handleControllerDataUpdate()
|
||||||
else if (m_controls.isReplaying())
|
else if (m_controls.isReplaying())
|
||||||
{
|
{
|
||||||
const auto& modifiedFrameData = updateControllerData(i, 0);
|
const auto& modifiedFrameData = updateControllerData(i, 0);
|
||||||
if (modifiedFrameData) {
|
if (modifiedFrameData)
|
||||||
|
{
|
||||||
frameData = modifiedFrameData.value();
|
frameData = modifiedFrameData.value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,141 +15,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef PCSX2_CORE
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
// TODO - Vaser - kill with wxWidgets
|
|
||||||
|
|
||||||
#include "Recording/InputRecordingFile.h"
|
|
||||||
#include "Recording/VirtualPad/VirtualPad.h"
|
|
||||||
|
|
||||||
class InputRecording
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Initializes all VirtualPad windows with "parent" as their base
|
|
||||||
void InitVirtualPadWindows(wxWindow* parent);
|
|
||||||
|
|
||||||
// Save or load PCSX2's global frame counter (g_FrameCount) along with each full/fast boot
|
|
||||||
//
|
|
||||||
// This is to prevent any inaccuracy issues caused by having a different
|
|
||||||
// internal emulation frame count than what it was at the beginning of the
|
|
||||||
// original recording
|
|
||||||
void RecordingReset();
|
|
||||||
|
|
||||||
// Main handler for ingesting input data and either saving it to the recording file (recording)
|
|
||||||
// or mutating it to the contents of the recording file (replaying)
|
|
||||||
void ControllerInterrupt(u8 port, size_t fifoSize, u8 dataIn, u8 dataOut);
|
|
||||||
|
|
||||||
// The running frame counter for the input recording
|
|
||||||
s32 GetFrameCounter();
|
|
||||||
|
|
||||||
InputRecordingFile& GetInputRecordingData();
|
|
||||||
|
|
||||||
// The internal PCSX2 g_FrameCount value on the first frame of the recording
|
|
||||||
u32 GetStartingFrame();
|
|
||||||
|
|
||||||
void IncrementFrameCounter();
|
|
||||||
|
|
||||||
// DEPRECATED: Slated for removal
|
|
||||||
// If the current frame contains controller / input data
|
|
||||||
bool IsInterruptFrame();
|
|
||||||
|
|
||||||
// If there is currently an input recording being played back or actively being recorded
|
|
||||||
bool IsActive();
|
|
||||||
|
|
||||||
// Whether or not the recording's initial state has yet to be loaded or saved and
|
|
||||||
// the rest of the recording can be initialized
|
|
||||||
// This is not applicable to recordings from a "power-on" state
|
|
||||||
bool IsInitialLoad();
|
|
||||||
|
|
||||||
// If there is currently an input recording being played back
|
|
||||||
bool IsReplaying();
|
|
||||||
|
|
||||||
// If there are inputs currently being recorded to a file
|
|
||||||
bool IsRecording();
|
|
||||||
|
|
||||||
// String representation of the current recording mode to be interpolated into the title
|
|
||||||
wxString RecordingModeTitleSegment();
|
|
||||||
|
|
||||||
// Sets input recording to Record Mode
|
|
||||||
void SetToRecordMode();
|
|
||||||
|
|
||||||
// Sets input recording to Replay Mode
|
|
||||||
void SetToReplayMode();
|
|
||||||
|
|
||||||
// Set the running frame counter for the input recording to an arbitrary value
|
|
||||||
void SetFrameCounter(u32 newGFrameCount);
|
|
||||||
|
|
||||||
// Sets up all values and prints console logs pertaining to the start of a recording
|
|
||||||
void SetupInitialState(u32 newStartingFrame);
|
|
||||||
|
|
||||||
/// Functions called from GUI
|
|
||||||
|
|
||||||
// Create a new input recording file
|
|
||||||
bool Create(wxString filename, const bool fromSaveState, wxString authorName);
|
|
||||||
// Play an existing input recording from a file
|
|
||||||
// Calls a file dialog if it fails to locate the default base savestate
|
|
||||||
bool Play(wxWindow* parent, wxString filename);
|
|
||||||
// Stop the active input recording
|
|
||||||
void Stop();
|
|
||||||
// Displays the VirtualPad window for the chosen pad
|
|
||||||
void ShowVirtualPad(const int port);
|
|
||||||
// Logs the padData and redraws the virtualPad windows of active pads
|
|
||||||
void LogAndRedraw();
|
|
||||||
// Resets emulation to the beginning of a recording
|
|
||||||
// Calls a file dialog if it fails to locate the base savestate
|
|
||||||
void GoToFirstFrame(wxWindow* parent);
|
|
||||||
// Resets a recording if the base savestate could not be loaded at the start
|
|
||||||
void FailedSavestate();
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum class InputRecordingMode
|
|
||||||
{
|
|
||||||
NotActive,
|
|
||||||
Recording,
|
|
||||||
Replaying,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int CONTROLLER_PORT_ONE = 0;
|
|
||||||
static const int CONTROLLER_PORT_TWO = 1;
|
|
||||||
|
|
||||||
// 0x42 is the magic number to indicate the default controller read query
|
|
||||||
// See - PAD.cpp::PADpoll - https://github.com/PCSX2/pcsx2/blob/master/pcsx2/PAD/Windows/PAD.cpp#L1255
|
|
||||||
static const u8 READ_DATA_AND_VIBRATE_FIRST_BYTE = 0x42;
|
|
||||||
// 0x5A is always the second byte in the buffer when the normal READ_DATA_AND_VIBRATE (0x42) query is executed.
|
|
||||||
// See - PAD.cpp::PADpoll - https://github.com/PCSX2/pcsx2/blob/master/pcsx2/PAD/Windows/PAD.cpp#L1256
|
|
||||||
static const u8 READ_DATA_AND_VIBRATE_SECOND_BYTE = 0x5A;
|
|
||||||
|
|
||||||
// DEPRECATED: Slated for removal
|
|
||||||
bool fInterruptFrame = false;
|
|
||||||
InputRecordingFile inputRecordingData;
|
|
||||||
bool initialLoad = false;
|
|
||||||
u32 startingFrame = 0;
|
|
||||||
s32 frameCounter = 0;
|
|
||||||
bool incrementUndo = false;
|
|
||||||
InputRecordingMode state = InputRecording::InputRecordingMode::NotActive;
|
|
||||||
wxString savestate;
|
|
||||||
|
|
||||||
// Array of usable pads (currently, only 2)
|
|
||||||
struct InputRecordingPad
|
|
||||||
{
|
|
||||||
// Controller Data
|
|
||||||
PadData* padData;
|
|
||||||
// VirtualPad
|
|
||||||
VirtualPad* virtualPad;
|
|
||||||
InputRecordingPad();
|
|
||||||
~InputRecordingPad();
|
|
||||||
} pads[2];
|
|
||||||
|
|
||||||
// Resolve the name and region of the game currently loaded using the GameDB
|
|
||||||
// If the game cannot be found in the DB, the fallback is the ISO filename
|
|
||||||
wxString resolveGameName();
|
|
||||||
};
|
|
||||||
|
|
||||||
extern InputRecording g_InputRecording;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "Recording/InputRecordingFile.h"
|
#include "Recording/InputRecordingFile.h"
|
||||||
#include "Recording/InputRecordingControls.h"
|
#include "Recording/InputRecordingControls.h"
|
||||||
|
|
||||||
|
|
|
@ -13,211 +13,10 @@
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef PCSX2_CORE
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
// TODO - Vaser - kill with wxWidgets
|
|
||||||
|
|
||||||
#include "Counters.h"
|
|
||||||
#include "DebugTools/Debug.h"
|
|
||||||
#include "MemoryTypes.h"
|
|
||||||
#include "gui/MainFrame.h"
|
|
||||||
|
|
||||||
#include "InputRecording.h"
|
|
||||||
#include "InputRecordingControls.h"
|
|
||||||
#include "Utilities/InputRecordingLogger.h"
|
|
||||||
|
|
||||||
InputRecordingControls g_InputRecordingControls;
|
|
||||||
|
|
||||||
void InputRecordingControls::CheckPauseStatus()
|
|
||||||
{
|
|
||||||
frame_advance_frame_counter++;
|
|
||||||
if (frameAdvancing && frame_advance_frame_counter >= frames_per_frame_advance)
|
|
||||||
{
|
|
||||||
frameAdvancing = false;
|
|
||||||
pauseEmulation = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_InputRecording.IsActive())
|
|
||||||
{
|
|
||||||
g_InputRecording.IncrementFrameCounter();
|
|
||||||
|
|
||||||
if (switchToReplay)
|
|
||||||
{
|
|
||||||
g_InputRecording.SetToReplayMode();
|
|
||||||
switchToReplay = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsFinishedReplaying() || g_InputRecording.GetFrameCounter() == INT_MAX)
|
|
||||||
{
|
|
||||||
if (!pauseEmulation)
|
|
||||||
pauseEmulation = true;
|
|
||||||
StopCapture();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_InputRecording.LogAndRedraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::HandlePausingAndLocking()
|
|
||||||
{
|
|
||||||
// Explicit frame locking
|
|
||||||
if (frameLock)
|
|
||||||
{
|
|
||||||
if (g_FrameCount == frameLockTracker)
|
|
||||||
{
|
|
||||||
frameLock = false;
|
|
||||||
Resume();
|
|
||||||
}
|
|
||||||
else if (!emulationCurrentlyPaused && GetCoreThread().IsOpen() && GetCoreThread().IsRunning())
|
|
||||||
{
|
|
||||||
emulationCurrentlyPaused = true;
|
|
||||||
GetCoreThread().PauseSelf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pauseEmulation && GetCoreThread().IsOpen() && GetCoreThread().IsRunning())
|
|
||||||
{
|
|
||||||
emulationCurrentlyPaused = true;
|
|
||||||
GetCoreThread().PauseSelf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::ResumeCoreThreadIfStarted()
|
|
||||||
{
|
|
||||||
if (resumeEmulation && GetCoreThread().IsOpen())
|
|
||||||
{
|
|
||||||
GetCoreThread().Resume();
|
|
||||||
resumeEmulation = false;
|
|
||||||
emulationCurrentlyPaused = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::FrameAdvance()
|
|
||||||
{
|
|
||||||
if (!IsFinishedReplaying())
|
|
||||||
{
|
|
||||||
frameAdvancing = true;
|
|
||||||
frame_advance_frame_counter = 0;
|
|
||||||
Resume();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
g_InputRecording.SetToRecordMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::setFrameAdvanceAmount(int amount)
|
|
||||||
{
|
|
||||||
frames_per_frame_advance = amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingControls::IsFrameAdvancing()
|
|
||||||
{
|
|
||||||
return frameAdvancing;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingControls::IsPaused()
|
|
||||||
{
|
|
||||||
return emulationCurrentlyPaused && GetCoreThread().IsOpen() && GetCoreThread().IsPaused();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::Pause()
|
|
||||||
{
|
|
||||||
pauseEmulation = true;
|
|
||||||
resumeEmulation = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::PauseImmediately()
|
|
||||||
{
|
|
||||||
if (!GetCoreThread().IsPaused())
|
|
||||||
{
|
|
||||||
Pause();
|
|
||||||
if (GetCoreThread().IsOpen() && GetCoreThread().IsRunning())
|
|
||||||
{
|
|
||||||
emulationCurrentlyPaused = true;
|
|
||||||
GetCoreThread().PauseSelf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::Resume()
|
|
||||||
{
|
|
||||||
if (!IsFinishedReplaying())
|
|
||||||
{
|
|
||||||
pauseEmulation = false;
|
|
||||||
resumeEmulation = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
g_InputRecording.SetToRecordMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::ResumeImmediately()
|
|
||||||
{
|
|
||||||
if (GetCoreThread().IsPaused())
|
|
||||||
{
|
|
||||||
Resume();
|
|
||||||
if (GetCoreThread().IsRunning())
|
|
||||||
{
|
|
||||||
emulationCurrentlyPaused = false;
|
|
||||||
GetCoreThread().Resume();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::TogglePause()
|
|
||||||
{
|
|
||||||
if (!pauseEmulation || !IsFinishedReplaying())
|
|
||||||
{
|
|
||||||
resumeEmulation = pauseEmulation;
|
|
||||||
pauseEmulation = !pauseEmulation;
|
|
||||||
InputRec::log(pauseEmulation ? "Paused Emulation" : "Resumed Emulation");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
g_InputRecording.SetToRecordMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::RecordModeToggle()
|
|
||||||
{
|
|
||||||
if (g_InputRecording.IsReplaying())
|
|
||||||
g_InputRecording.SetToRecordMode();
|
|
||||||
else if (g_InputRecording.IsRecording())
|
|
||||||
{
|
|
||||||
if (IsPaused() || g_InputRecording.GetFrameCounter() < g_InputRecording.GetInputRecordingData().GetTotalFrames())
|
|
||||||
g_InputRecording.SetToReplayMode();
|
|
||||||
else
|
|
||||||
switchToReplay = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::Lock(u32 frame)
|
|
||||||
{
|
|
||||||
frameLock = true;
|
|
||||||
frameLockTracker = frame;
|
|
||||||
frameAdvancing = false;
|
|
||||||
//Ensures that g_frameCount can be used to resume emulation after a fast/full boot
|
|
||||||
if (!g_InputRecording.GetInputRecordingData().FromSaveState())
|
|
||||||
g_FrameCount = frame + 1;
|
|
||||||
else
|
|
||||||
sMainFrame.StartInputRecording();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingControls::IsFinishedReplaying() const
|
|
||||||
{
|
|
||||||
return g_InputRecording.IsReplaying() &&
|
|
||||||
g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingControls::StopCapture() const
|
|
||||||
{
|
|
||||||
if (MainEmuFrame* mainFrame = GetMainFramePtr())
|
|
||||||
{
|
|
||||||
if (mainFrame->IsCapturing())
|
|
||||||
{
|
|
||||||
mainFrame->VideoCaptureToggle();
|
|
||||||
InputRec::log("Capture completed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "DebugTools/Debug.h"
|
#include "DebugTools/Debug.h"
|
||||||
#include "MemoryTypes.h"
|
#include "MemoryTypes.h"
|
||||||
|
|
||||||
|
|
|
@ -15,91 +15,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
#ifdef PCSX2_CORE
|
||||||
// TODO - Vaser - kill with wxWidgets
|
|
||||||
|
|
||||||
class InputRecordingControls
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Intended to be called at the end of each frame, but will no-op if frame lock is active
|
|
||||||
//
|
|
||||||
// Will set the pausing parameters for emulation if:
|
|
||||||
// - The InputRecordingControls::FrameAdvance was hit on the previous frame
|
|
||||||
// - Emulation was explicitly paused using InputRecordingControls::TogglePause
|
|
||||||
// - We are replaying an input recording and have hit the end
|
|
||||||
void CheckPauseStatus();
|
|
||||||
|
|
||||||
// When loading a recording file or booting with a recording active, lock will be enabled.
|
|
||||||
// Emulation will be forced into and remain in a paused state until the transition in progress
|
|
||||||
// has completed - signaled when g_framecount and frameCountTracker are equal
|
|
||||||
//
|
|
||||||
// This function also handles actually pausing emulation when told to
|
|
||||||
void HandlePausingAndLocking();
|
|
||||||
|
|
||||||
// Called much more frequently than HandleFrameAdvanceAndPausing, instead of being per frame
|
|
||||||
// this hooks into pcsx2's main App event handler as it has to be able to resume emulation
|
|
||||||
// when drawing frames has compltely stopped
|
|
||||||
//
|
|
||||||
// Resumes emulation if:
|
|
||||||
// - CoreThread is currently open and paused
|
|
||||||
// - We've signaled emulation to be resumed via TogglePause or FrameAdvancing
|
|
||||||
void ResumeCoreThreadIfStarted();
|
|
||||||
|
|
||||||
// Resume emulation (incase the emulation is currently paused) and pause after a single frame has passed
|
|
||||||
void FrameAdvance();
|
|
||||||
void setFrameAdvanceAmount(int amount);
|
|
||||||
// Returns true if emulation is currently set up to frame advance.
|
|
||||||
bool IsFrameAdvancing();
|
|
||||||
// Returns true if the input recording has been paused, which can occur:
|
|
||||||
// - After a single frame has passed after InputRecordingControls::FrameAdvance
|
|
||||||
// - Explicitly paused via an InputRecordingControls function
|
|
||||||
bool IsPaused();
|
|
||||||
// Pause emulation at the next available Vsync
|
|
||||||
void Pause();
|
|
||||||
// Pause emulation immediately, not waiting for the next Vsync
|
|
||||||
void PauseImmediately();
|
|
||||||
// Resume emulation when the next pcsx2 App event is handled
|
|
||||||
void Resume();
|
|
||||||
/**
|
|
||||||
* @brief Resumes emulation immediately, don't wait until the next VSync
|
|
||||||
*/
|
|
||||||
void ResumeImmediately();
|
|
||||||
// Alternates emulation between a paused and unpaused state
|
|
||||||
void TogglePause();
|
|
||||||
// Switches between recording and replaying the active input recording file
|
|
||||||
void RecordModeToggle();
|
|
||||||
// Enables the frame locking mechanism so that when recordings are loaded
|
|
||||||
// or when processing a reboot with a recording active that no frames are
|
|
||||||
// lost in prior emulation
|
|
||||||
void Lock(u32 frame);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Indicates if the input recording controls have explicitly paused emulation or not
|
|
||||||
bool emulationCurrentlyPaused = false;
|
|
||||||
// Indicates on the next VSync if we are frame advancing, this value
|
|
||||||
// and should be cleared once a single frame has passed
|
|
||||||
bool frameAdvancing = false;
|
|
||||||
u32 frame_advance_frame_counter = 0;
|
|
||||||
u32 frames_per_frame_advance = 1;
|
|
||||||
// Indicates if we intend to call CoreThread.PauseSelf() on the current or next available vsync
|
|
||||||
bool pauseEmulation = false;
|
|
||||||
// Indicates if we intend to call CoreThread.Resume() when the next pcsx2 App event is handled
|
|
||||||
bool resumeEmulation = false;
|
|
||||||
// Indicates to switch to replay mode after the next vsync
|
|
||||||
bool switchToReplay = false;
|
|
||||||
// Used to stop recording frames from incrementing during a reset
|
|
||||||
bool frameLock = false;
|
|
||||||
// The frame value to use as the frame lock reset point
|
|
||||||
u32 frameLockTracker = 0;
|
|
||||||
|
|
||||||
bool IsFinishedReplaying() const;
|
|
||||||
// Calls mainEmuFrame's videoCaptureToggle to end a capture if active
|
|
||||||
void StopCapture() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern InputRecordingControls g_InputRecordingControls;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
|
|
@ -13,225 +13,10 @@
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef PCSX2_CORE
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
// TODO - Vaser - kill with wxWidgets
|
|
||||||
|
|
||||||
#include "DebugTools/Debug.h"
|
|
||||||
#include "gui/MainFrame.h"
|
|
||||||
#include "MemoryTypes.h"
|
|
||||||
|
|
||||||
#include "InputRecordingFile.h"
|
|
||||||
#include "Utilities/InputRecordingLogger.h"
|
|
||||||
|
|
||||||
#include <fmt/format.h>
|
|
||||||
|
|
||||||
void InputRecordingFileHeader::Init()
|
|
||||||
{
|
|
||||||
memset(author, 0, std::size(author));
|
|
||||||
memset(gameName, 0, std::size(gameName));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingFileHeader::SetEmulatorVersion()
|
|
||||||
{
|
|
||||||
wxString emuVersion = wxString::Format("%s-%d.%d.%d", pxGetAppName().c_str(), PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo);
|
|
||||||
int max = std::size(emu) - 1;
|
|
||||||
strncpy(emu, emuVersion.c_str(), max);
|
|
||||||
emu[max] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingFileHeader::SetAuthor(wxString _author)
|
|
||||||
{
|
|
||||||
int max = std::size(author) - 1;
|
|
||||||
strncpy(author, _author.c_str(), max);
|
|
||||||
author[max] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingFileHeader::SetGameName(wxString _gameName)
|
|
||||||
{
|
|
||||||
int max = std::size(gameName) - 1;
|
|
||||||
strncpy(gameName, _gameName.c_str(), max);
|
|
||||||
gameName[max] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingFile::Close()
|
|
||||||
{
|
|
||||||
if (recordingFile == nullptr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
fclose(recordingFile);
|
|
||||||
recordingFile = nullptr;
|
|
||||||
filename = "";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const wxString& InputRecordingFile::GetFilename()
|
|
||||||
{
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
InputRecordingFileHeader& InputRecordingFile::GetHeader()
|
|
||||||
{
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
long& InputRecordingFile::GetTotalFrames()
|
|
||||||
{
|
|
||||||
return totalFrames;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long& InputRecordingFile::GetUndoCount()
|
|
||||||
{
|
|
||||||
return undoCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingFile::FromSaveState()
|
|
||||||
{
|
|
||||||
return savestate.fromSavestate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingFile::IncrementUndoCount()
|
|
||||||
{
|
|
||||||
undoCount++;
|
|
||||||
if (recordingFile == nullptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fseek(recordingFile, seekpointUndoCount, SEEK_SET);
|
|
||||||
fwrite(&undoCount, 4, 1, recordingFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingFile::open(const wxString path, bool newRecording)
|
|
||||||
{
|
|
||||||
if (newRecording)
|
|
||||||
{
|
|
||||||
if ((recordingFile = wxFopen(path, L"wb+")) != nullptr)
|
|
||||||
{
|
|
||||||
filename = path;
|
|
||||||
totalFrames = 0;
|
|
||||||
undoCount = 0;
|
|
||||||
header.Init();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((recordingFile = wxFopen(path, L"rb+")) != nullptr)
|
|
||||||
{
|
|
||||||
if (verifyRecordingFileHeader())
|
|
||||||
{
|
|
||||||
filename = path;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Close();
|
|
||||||
InputRec::consoleLog("Input recording file header is invalid");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
InputRec::consoleLog(fmt::format("Input recording file opening failed. Error - {}", strerror(errno)));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingFile::OpenNew(const wxString& path, bool fromSavestate)
|
|
||||||
{
|
|
||||||
if (!open(path, true))
|
|
||||||
return false;
|
|
||||||
savestate.fromSavestate = fromSavestate;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingFile::OpenExisting(const wxString& path)
|
|
||||||
{
|
|
||||||
return open(path, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingFile::ReadKeyBuffer(u8& result, const uint& frame, const uint port, const uint bufIndex)
|
|
||||||
{
|
|
||||||
if (recordingFile == nullptr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
long seek = getRecordingBlockSeekPoint(frame) + controllerInputBytes * port + bufIndex;
|
|
||||||
if (fseek(recordingFile, seek, SEEK_SET) != 0 || fread(&result, 1, 1, recordingFile) != 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingFile::SetTotalFrames(long frame)
|
|
||||||
{
|
|
||||||
if (recordingFile == nullptr || totalFrames >= frame)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
totalFrames = frame;
|
|
||||||
fseek(recordingFile, seekpointTotalFrames, SEEK_SET);
|
|
||||||
fwrite(&totalFrames, 4, 1, recordingFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingFile::WriteHeader()
|
|
||||||
{
|
|
||||||
if (recordingFile == nullptr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
rewind(recordingFile);
|
|
||||||
if (fwrite(&header, sizeof(InputRecordingFileHeader), 1, recordingFile) != 1 || fwrite(&totalFrames, 4, 1, recordingFile) != 1 || fwrite(&undoCount, 4, 1, recordingFile) != 1 || fwrite(&savestate, 1, 1, recordingFile) != 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingFile::WriteKeyBuffer(const uint& frame, const uint port, const uint bufIndex, const u8& buf)
|
|
||||||
{
|
|
||||||
if (recordingFile == nullptr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
long seek = getRecordingBlockSeekPoint(frame) + 18 * port + bufIndex;
|
|
||||||
|
|
||||||
if (fseek(recordingFile, seek, SEEK_SET) != 0 || fwrite(&buf, 1, 1, recordingFile) != 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fflush(recordingFile);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
long InputRecordingFile::getRecordingBlockSeekPoint(const long& frame)
|
|
||||||
{
|
|
||||||
return headerSize + sizeof(bool) + frame * inputBytesPerFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecordingFile::verifyRecordingFileHeader()
|
|
||||||
{
|
|
||||||
if (recordingFile == nullptr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Verify header contents
|
|
||||||
rewind(recordingFile);
|
|
||||||
if (fread(&header, sizeof(InputRecordingFileHeader), 1, recordingFile) != 1 || fread(&totalFrames, 4, 1, recordingFile) != 1 || fread(&undoCount, 4, 1, recordingFile) != 1 || fread(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for current verison
|
|
||||||
if (header.version != 1)
|
|
||||||
{
|
|
||||||
InputRec::consoleLog(fmt::format("Input recording file is not a supported version - {}", header.version));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "InputRecordingFile.h"
|
#include "InputRecordingFile.h"
|
||||||
|
|
||||||
#include "Utilities/InputRecordingLogger.h"
|
#include "Utilities/InputRecordingLogger.h"
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
#ifdef PCSX2_CORE
|
||||||
// TODO - Vaser - kill with wxWidgets
|
|
||||||
|
|
||||||
#include "System.h"
|
#include "System.h"
|
||||||
#include "PadData.h"
|
#include "PadData.h"
|
||||||
|
@ -24,103 +23,6 @@
|
||||||
// NOTE / TODOs for Version 2
|
// NOTE / TODOs for Version 2
|
||||||
// - Move fromSavestate, undoCount, and total frames into the header
|
// - Move fromSavestate, undoCount, and total frames into the header
|
||||||
|
|
||||||
struct InputRecordingFileHeader
|
|
||||||
{
|
|
||||||
u8 version = 1;
|
|
||||||
char emu[50] = "";
|
|
||||||
char author[255] = "";
|
|
||||||
char gameName[255] = "";
|
|
||||||
|
|
||||||
public:
|
|
||||||
void SetEmulatorVersion();
|
|
||||||
void Init();
|
|
||||||
void SetAuthor(wxString author);
|
|
||||||
void SetGameName(wxString cdrom);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// DEPRECATED / Slated for Removal
|
|
||||||
struct InputRecordingSavestate
|
|
||||||
{
|
|
||||||
// Whether we start from the savestate or from power-on
|
|
||||||
bool fromSavestate = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handles all operations on the input recording file
|
|
||||||
class InputRecordingFile
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
~InputRecordingFile() { Close(); }
|
|
||||||
|
|
||||||
// Closes the underlying input recording file, writing the header and
|
|
||||||
// prepares for a possible new recording to be started
|
|
||||||
bool Close();
|
|
||||||
// Retrieve the input recording's filename (not the path)
|
|
||||||
const wxString& GetFilename();
|
|
||||||
// Retrieve the input recording's header which contains high-level metadata on the recording
|
|
||||||
InputRecordingFileHeader& GetHeader();
|
|
||||||
// The maximum number of frames, or in other words, the length of the recording
|
|
||||||
long& GetTotalFrames();
|
|
||||||
// The number of times a save-state has been loaded while recording this movie
|
|
||||||
// this is also often referred to as a "re-record"
|
|
||||||
unsigned long& GetUndoCount();
|
|
||||||
// Whether or not this input recording starts by loading a save-state or by booting the game fresh
|
|
||||||
bool FromSaveState();
|
|
||||||
// Increment the number of undo actions and commit it to the recording file
|
|
||||||
void IncrementUndoCount();
|
|
||||||
// Open an existing recording file
|
|
||||||
bool OpenExisting(const wxString& path);
|
|
||||||
// Create and open a brand new input recording, either starting from a save-state or from
|
|
||||||
// booting the game
|
|
||||||
bool OpenNew(const wxString& path, bool fromSaveState);
|
|
||||||
// Reads the current frame's input data from the file in order to intercept and overwrite
|
|
||||||
// the current frame's value from the emulator
|
|
||||||
bool ReadKeyBuffer(u8& result, const uint& frame, const uint port, const uint bufIndex);
|
|
||||||
// Updates the total frame counter and commit it to the recording file
|
|
||||||
void SetTotalFrames(long frames);
|
|
||||||
// Persist the input recording file header's current state to the file
|
|
||||||
bool WriteHeader();
|
|
||||||
// Writes the current frame's input data to the file so it can be replayed
|
|
||||||
bool WriteKeyBuffer(const uint& frame, const uint port, const uint bufIndex, const u8& buf);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const int controllerPortsSupported = 2;
|
|
||||||
static const int controllerInputBytes = 18;
|
|
||||||
static const int inputBytesPerFrame = controllerInputBytes * controllerPortsSupported;
|
|
||||||
// TODO - version 2, this could be greatly simplified if everything was in the header
|
|
||||||
// + 4 + 4 is the totalFrame and undoCount values
|
|
||||||
static const int headerSize = sizeof(InputRecordingFileHeader) + 4 + 4;
|
|
||||||
// DEPRECATED / Slated for Removal
|
|
||||||
static const int recordingSavestateHeaderSize = sizeof(bool);
|
|
||||||
static const int seekpointTotalFrames = sizeof(InputRecordingFileHeader);
|
|
||||||
static const int seekpointUndoCount = sizeof(InputRecordingFileHeader) + 4;
|
|
||||||
static const int seekpointSaveStateHeader = seekpointUndoCount + 4;
|
|
||||||
|
|
||||||
InputRecordingFileHeader header;
|
|
||||||
wxString filename = "";
|
|
||||||
FILE* recordingFile = nullptr;
|
|
||||||
InputRecordingSavestate savestate;
|
|
||||||
|
|
||||||
// An signed 32-bit frame limit is equivalent to 1.13 years of continuous 60fps footage
|
|
||||||
long totalFrames = 0;
|
|
||||||
unsigned long undoCount = 0;
|
|
||||||
|
|
||||||
// Calculates the position of the current frame in the input recording
|
|
||||||
long getRecordingBlockSeekPoint(const long& frame);
|
|
||||||
bool open(const wxString path, bool newRecording);
|
|
||||||
bool verifyRecordingFileHeader();
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "System.h"
|
|
||||||
#include "PadData.h"
|
|
||||||
|
|
||||||
// NOTE / TODOs for Version 2
|
|
||||||
// - Move fromSavestate, undoCount, and total frames into the header
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Handles all operations on the input recording file
|
// Handles all operations on the input recording file
|
||||||
class InputRecordingFile
|
class InputRecordingFile
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2022 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file dies along with wxWidgets
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
|
||||||
|
|
||||||
#include "NewRecordingFrame.h"
|
|
||||||
|
|
||||||
#include <wx/gbsizer.h>
|
|
||||||
|
|
||||||
NewRecordingFrame::NewRecordingFrame(wxWindow* parent)
|
|
||||||
: wxDialog(parent, wxID_ANY, "New Input Recording", wxDefaultPosition, wxDefaultSize, wxSTAY_ON_TOP | wxCLOSE_BOX | wxCAPTION)
|
|
||||||
{
|
|
||||||
m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _("panel"));
|
|
||||||
|
|
||||||
wxGridBagSizer* gbs = new wxGridBagSizer(20, 20);
|
|
||||||
gbs->SetFlexibleDirection(wxBOTH);
|
|
||||||
gbs->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
|
|
||||||
wxBoxSizer* container = new wxBoxSizer(wxVERTICAL);
|
|
||||||
|
|
||||||
m_fileLabel = new wxStaticText(m_panel, wxID_ANY, _("File Path"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
|
||||||
m_authorLabel = new wxStaticText(m_panel, wxID_ANY, _("Author"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
|
||||||
m_fromLabel = new wxStaticText(m_panel, wxID_ANY, _("Record From"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
|
||||||
|
|
||||||
m_filePicker = new wxFilePickerCtrl(m_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(m_panel, MenuIds_New_Recording_Frame_Author, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
|
|
||||||
m_fromChoice = new wxChoice(m_panel, MenuIds_New_Recording_Frame_From, wxDefaultPosition, wxDefaultSize);
|
|
||||||
|
|
||||||
m_savestate_label =
|
|
||||||
_("Be Warned! Basing an input recording off a savestate can be a mistake as savestates can break across emulator versions. Be prepared to be stuck to an emulator version or have to re-create your starting savestate in a later version.");
|
|
||||||
m_warning_label = new wxStaticText(m_panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
|
||||||
m_warning_label->SetForegroundColour(wxColor(*wxRED));
|
|
||||||
|
|
||||||
m_startRecording = new wxButton(m_panel, wxID_OK, _("Browse Required"), wxDefaultPosition, wxDefaultSize);
|
|
||||||
m_startRecording->Enable(false);
|
|
||||||
m_cancelRecording = new wxButton(m_panel, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize);
|
|
||||||
|
|
||||||
gbs->Add(m_fileLabel, wxGBPosition(0, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
|
||||||
gbs->Add(m_filePicker, wxGBPosition(0, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
|
||||||
|
|
||||||
gbs->Add(m_authorLabel, wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
|
||||||
gbs->Add(m_authorInput, wxGBPosition(1, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
|
||||||
|
|
||||||
gbs->Add(m_fromLabel, wxGBPosition(2, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
|
||||||
gbs->Add(m_fromChoice, wxGBPosition(2, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxEXPAND);
|
|
||||||
|
|
||||||
gbs->Add(m_warning_label, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALIGN_CENTER_VERTICAL);
|
|
||||||
|
|
||||||
gbs->Add(m_startRecording, wxGBPosition(4, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
|
||||||
gbs->Add(m_cancelRecording, wxGBPosition(4, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
|
||||||
|
|
||||||
gbs->AddGrowableCol(0);
|
|
||||||
gbs->AddGrowableCol(1);
|
|
||||||
gbs->AddGrowableRow(3);
|
|
||||||
|
|
||||||
container->Add(gbs, 1, wxALL | wxEXPAND, 15);
|
|
||||||
m_panel->SetSizer(container);
|
|
||||||
m_panel->GetSizer()->Fit(this);
|
|
||||||
Centre();
|
|
||||||
|
|
||||||
m_fileBrowsed = false;
|
|
||||||
m_filePicker->GetPickerCtrl()->Bind(wxEVT_FILEPICKER_CHANGED, &NewRecordingFrame::OnFileDirChange, this);
|
|
||||||
m_filePicker->Bind(wxEVT_FILEPICKER_CHANGED, &NewRecordingFrame::OnFileChanged, this);
|
|
||||||
m_fromChoice->Bind(wxEVT_CHOICE, &NewRecordingFrame::OnRecordingTypeChoiceChanged, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
int NewRecordingFrame::ShowModal(const bool isCoreThreadOpen)
|
|
||||||
{
|
|
||||||
static const char* choices[2] = {"Boot", "Current Frame"};
|
|
||||||
m_fromChoice->Set(wxArrayString(1 + isCoreThreadOpen, &choices[0]));
|
|
||||||
m_fromChoice->SetSelection(isCoreThreadOpen);
|
|
||||||
if (m_fromChoice->GetSelection() == 1)
|
|
||||||
{
|
|
||||||
m_warning_label->SetLabel(m_savestate_label);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_warning_label->SetLabel("");
|
|
||||||
}
|
|
||||||
m_warning_label->Wrap(GetClientSize().GetWidth());
|
|
||||||
m_panel->GetSizer()->Fit(this);
|
|
||||||
return wxDialog::ShowModal();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NewRecordingFrame::OnFileDirChange(wxFileDirPickerEvent& event)
|
|
||||||
{
|
|
||||||
m_filePicker->wxFileDirPickerCtrlBase::OnFileDirChange(event);
|
|
||||||
m_fileBrowsed = true;
|
|
||||||
EnableOkBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NewRecordingFrame::OnFileChanged(wxFileDirPickerEvent& event)
|
|
||||||
{
|
|
||||||
EnableOkBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NewRecordingFrame::OnRecordingTypeChoiceChanged(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
if (m_fromChoice->GetSelection() == 1)
|
|
||||||
{
|
|
||||||
m_warning_label->SetLabel(m_savestate_label);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_warning_label->SetLabel("");
|
|
||||||
}
|
|
||||||
m_warning_label->Wrap(GetClientSize().GetWidth());
|
|
||||||
m_panel->GetSizer()->Fit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NewRecordingFrame::EnableOkBox()
|
|
||||||
{
|
|
||||||
if (m_filePicker->GetPath().length() == 0)
|
|
||||||
{
|
|
||||||
m_fileBrowsed = false;
|
|
||||||
m_startRecording->SetLabel(_("Browse Required"));
|
|
||||||
m_startRecording->Enable(false);
|
|
||||||
}
|
|
||||||
else if (m_fileBrowsed)
|
|
||||||
{
|
|
||||||
m_startRecording->SetLabel(_("Start"));
|
|
||||||
m_startRecording->Enable(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString NewRecordingFrame::GetFile() const
|
|
||||||
{
|
|
||||||
wxString path = m_filePicker->GetPath();
|
|
||||||
// wxWidget's removes the extension if it contains wildcards
|
|
||||||
// on wxGTK https://trac.wxwidgets.org/ticket/15285
|
|
||||||
if (!path.EndsWith(".p2m2"))
|
|
||||||
{
|
|
||||||
return wxString::Format("%s.p2m2", path);
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString NewRecordingFrame::GetAuthor() const
|
|
||||||
{
|
|
||||||
return m_authorInput->GetValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
int NewRecordingFrame::GetFrom() const
|
|
||||||
{
|
|
||||||
return m_fromChoice->GetSelection();
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,61 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2022 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
|
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
|
|
||||||
#include <wx/wx.h>
|
|
||||||
#include <wx/filepicker.h>
|
|
||||||
|
|
||||||
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);
|
|
||||||
int ShowModal(const bool isCoreThreadOpen);
|
|
||||||
|
|
||||||
wxString GetFile() const;
|
|
||||||
wxString GetAuthor() const;
|
|
||||||
int GetFrom() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void OnFileDirChange(wxFileDirPickerEvent& event);
|
|
||||||
void OnFileChanged(wxFileDirPickerEvent& event);
|
|
||||||
void OnRecordingTypeChoiceChanged(wxCommandEvent& event);
|
|
||||||
void EnableOkBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
wxPanel* m_panel;
|
|
||||||
wxStaticText* m_fileLabel;
|
|
||||||
wxFilePickerCtrl* m_filePicker;
|
|
||||||
bool m_fileBrowsed;
|
|
||||||
wxStaticText* m_authorLabel;
|
|
||||||
wxTextCtrl* m_authorInput;
|
|
||||||
wxStaticText* m_fromLabel;
|
|
||||||
wxChoice* m_fromChoice;
|
|
||||||
wxButton* m_startRecording;
|
|
||||||
wxButton* m_cancelRecording;
|
|
||||||
wxString m_savestate_label;
|
|
||||||
wxStaticText* m_warning_label;
|
|
||||||
};
|
|
||||||
#endif
|
|
|
@ -13,199 +13,13 @@
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef PCSX2_CORE
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
#include "DebugTools/Debug.h"
|
#include "DebugTools/Debug.h"
|
||||||
#include "Recording/PadData.h"
|
#include "Recording/PadData.h"
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
|
|
||||||
void PadData::UpdateControllerData(u16 bufIndex, u8 const& bufVal)
|
|
||||||
{
|
|
||||||
const BufferIndex index = static_cast<BufferIndex>(bufIndex);
|
|
||||||
switch (index)
|
|
||||||
{
|
|
||||||
case BufferIndex::PressedFlagsGroupOne:
|
|
||||||
leftPressed = IsButtonPressed(LEFT, bufVal);
|
|
||||||
downPressed = IsButtonPressed(DOWN, bufVal);
|
|
||||||
rightPressed = IsButtonPressed(RIGHT, bufVal);
|
|
||||||
upPressed = IsButtonPressed(UP, bufVal);
|
|
||||||
start = IsButtonPressed(START, bufVal);
|
|
||||||
r3 = IsButtonPressed(R3, bufVal);
|
|
||||||
l3 = IsButtonPressed(L3, bufVal);
|
|
||||||
select = IsButtonPressed(SELECT, bufVal);
|
|
||||||
break;
|
|
||||||
case BufferIndex::PressedFlagsGroupTwo:
|
|
||||||
squarePressed = IsButtonPressed(SQUARE, bufVal);
|
|
||||||
crossPressed = IsButtonPressed(CROSS, bufVal);
|
|
||||||
circlePressed = IsButtonPressed(CIRCLE, bufVal);
|
|
||||||
trianglePressed = IsButtonPressed(TRIANGLE, bufVal);
|
|
||||||
r1Pressed = IsButtonPressed(R1, bufVal);
|
|
||||||
l1Pressed = IsButtonPressed(L1, bufVal);
|
|
||||||
r2Pressed = IsButtonPressed(R2, bufVal);
|
|
||||||
l2Pressed = IsButtonPressed(L2, bufVal);
|
|
||||||
break;
|
|
||||||
case BufferIndex::RightAnalogXVector:
|
|
||||||
rightAnalogX = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::RightAnalogYVector:
|
|
||||||
rightAnalogY = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::LeftAnalogXVector:
|
|
||||||
leftAnalogX = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::LeftAnalogYVector:
|
|
||||||
leftAnalogY = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::RightPressure:
|
|
||||||
rightPressure = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::LeftPressure:
|
|
||||||
leftPressure = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::UpPressure:
|
|
||||||
upPressure = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::DownPressure:
|
|
||||||
downPressure = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::TrianglePressure:
|
|
||||||
trianglePressure = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::CirclePressure:
|
|
||||||
circlePressure = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::CrossPressure:
|
|
||||||
crossPressure = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::SquarePressure:
|
|
||||||
squarePressure = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::L1Pressure:
|
|
||||||
l1Pressure = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::R1Pressure:
|
|
||||||
r1Pressure = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::L2Pressure:
|
|
||||||
l2Pressure = bufVal;
|
|
||||||
break;
|
|
||||||
case BufferIndex::R2Pressure:
|
|
||||||
r2Pressure = bufVal;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 PadData::PollControllerData(u16 bufIndex)
|
|
||||||
{
|
|
||||||
u8 byte = 0;
|
|
||||||
const BufferIndex index = static_cast<BufferIndex>(bufIndex);
|
|
||||||
switch (index)
|
|
||||||
{
|
|
||||||
case BufferIndex::PressedFlagsGroupOne:
|
|
||||||
// Construct byte by combining flags if the buttons are pressed
|
|
||||||
byte |= BitmaskOrZero(leftPressed, LEFT);
|
|
||||||
byte |= BitmaskOrZero(downPressed, DOWN);
|
|
||||||
byte |= BitmaskOrZero(rightPressed, RIGHT);
|
|
||||||
byte |= BitmaskOrZero(upPressed, UP);
|
|
||||||
byte |= BitmaskOrZero(start, START);
|
|
||||||
byte |= BitmaskOrZero(r3, R3);
|
|
||||||
byte |= BitmaskOrZero(l3, L3);
|
|
||||||
byte |= BitmaskOrZero(select, SELECT);
|
|
||||||
// We flip the bits because as mentioned below, 0 = pressed
|
|
||||||
return ~byte;
|
|
||||||
case BufferIndex::PressedFlagsGroupTwo:
|
|
||||||
// Construct byte by combining flags if the buttons are pressed
|
|
||||||
byte |= BitmaskOrZero(squarePressed, SQUARE);
|
|
||||||
byte |= BitmaskOrZero(crossPressed, CROSS);
|
|
||||||
byte |= BitmaskOrZero(circlePressed, CIRCLE);
|
|
||||||
byte |= BitmaskOrZero(trianglePressed, TRIANGLE);
|
|
||||||
byte |= BitmaskOrZero(r1Pressed, R1);
|
|
||||||
byte |= BitmaskOrZero(l1Pressed, L1);
|
|
||||||
byte |= BitmaskOrZero(r2Pressed, R2);
|
|
||||||
byte |= BitmaskOrZero(l2Pressed, L2);
|
|
||||||
// We flip the bits because as mentioned below, 0 = pressed
|
|
||||||
return ~byte;
|
|
||||||
case BufferIndex::RightAnalogXVector:
|
|
||||||
return rightAnalogX;
|
|
||||||
case BufferIndex::RightAnalogYVector:
|
|
||||||
return rightAnalogY;
|
|
||||||
case BufferIndex::LeftAnalogXVector:
|
|
||||||
return leftAnalogX;
|
|
||||||
case BufferIndex::LeftAnalogYVector:
|
|
||||||
return leftAnalogY;
|
|
||||||
case BufferIndex::RightPressure:
|
|
||||||
return rightPressure;
|
|
||||||
case BufferIndex::LeftPressure:
|
|
||||||
return leftPressure;
|
|
||||||
case BufferIndex::UpPressure:
|
|
||||||
return upPressure;
|
|
||||||
case BufferIndex::DownPressure:
|
|
||||||
return downPressure;
|
|
||||||
case BufferIndex::TrianglePressure:
|
|
||||||
return trianglePressure;
|
|
||||||
case BufferIndex::CirclePressure:
|
|
||||||
return circlePressure;
|
|
||||||
case BufferIndex::CrossPressure:
|
|
||||||
return crossPressure;
|
|
||||||
case BufferIndex::SquarePressure:
|
|
||||||
return squarePressure;
|
|
||||||
case BufferIndex::L1Pressure:
|
|
||||||
return l1Pressure;
|
|
||||||
case BufferIndex::R1Pressure:
|
|
||||||
return r1Pressure;
|
|
||||||
case BufferIndex::L2Pressure:
|
|
||||||
return l2Pressure;
|
|
||||||
case BufferIndex::R2Pressure:
|
|
||||||
return r2Pressure;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PadData::IsButtonPressed(ButtonResolver buttonResolver, u8 const& bufVal)
|
|
||||||
{
|
|
||||||
// Rather than the flags being SET if the button is pressed, it is the opposite
|
|
||||||
// For example: 0111 1111 with `left` being the first bit indicates `left` is pressed.
|
|
||||||
// So, we are forced to flip the pressed bits with a NOT first
|
|
||||||
return (~bufVal & buttonResolver.buttonBitmask) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 PadData::BitmaskOrZero(bool pressed, ButtonResolver buttonInfo)
|
|
||||||
{
|
|
||||||
return pressed ? buttonInfo.buttonBitmask : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - Vaser - kill with wxWidgets
|
|
||||||
// TODO - Vaser - replace with this something better in Qt
|
|
||||||
wxString PadData::RawPadBytesToString(int start, int end)
|
|
||||||
{
|
|
||||||
wxString str;
|
|
||||||
for (int i = start; i < end; i++)
|
|
||||||
{
|
|
||||||
str += wxString::Format("%d", PollControllerData(i));
|
|
||||||
if (i != end - 1)
|
|
||||||
str += ", ";
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PadData::LogPadData(u8 const& port)
|
|
||||||
{
|
|
||||||
wxString pressedBytes = RawPadBytesToString(0, 2);
|
|
||||||
wxString rightAnalogBytes = RawPadBytesToString(2, 4);
|
|
||||||
wxString leftAnalogBytes = RawPadBytesToString(4, 6);
|
|
||||||
wxString pressureBytes = RawPadBytesToString(6, 17);
|
|
||||||
wxString fullLog =
|
|
||||||
wxString::Format("[PAD %d] Raw Bytes: Pressed = [%s]\n", port + 1, pressedBytes) +
|
|
||||||
wxString::Format("[PAD %d] Raw Bytes: Right Analog = [%s]\n", port + 1, rightAnalogBytes) +
|
|
||||||
wxString::Format("[PAD %d] Raw Bytes: Left Analog = [%s]\n", port + 1, leftAnalogBytes) +
|
|
||||||
wxString::Format("[PAD %d] Raw Bytes: Pressure = [%s]\n", port + 1, pressureBytes);
|
|
||||||
controlLog(fullLog.ToUTF8());
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
||||||
#include "PAD/Host/KeyStatus.h"
|
#include "PAD/Host/KeyStatus.h"
|
||||||
|
|
|
@ -15,121 +15,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
#ifdef PCSX2_CORE
|
||||||
|
|
||||||
class PadData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/// Constants
|
|
||||||
static const u8 ANALOG_VECTOR_NEUTRAL = 127;
|
|
||||||
|
|
||||||
enum class BufferIndex
|
|
||||||
{
|
|
||||||
PressedFlagsGroupOne,
|
|
||||||
PressedFlagsGroupTwo,
|
|
||||||
RightAnalogXVector,
|
|
||||||
RightAnalogYVector,
|
|
||||||
LeftAnalogXVector,
|
|
||||||
LeftAnalogYVector,
|
|
||||||
RightPressure,
|
|
||||||
LeftPressure,
|
|
||||||
UpPressure,
|
|
||||||
DownPressure,
|
|
||||||
TrianglePressure,
|
|
||||||
CirclePressure,
|
|
||||||
CrossPressure,
|
|
||||||
SquarePressure,
|
|
||||||
L1Pressure,
|
|
||||||
R1Pressure,
|
|
||||||
L2Pressure,
|
|
||||||
R2Pressure
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Pressure Buttons - 0-255
|
|
||||||
u8 circlePressure = 0;
|
|
||||||
u8 crossPressure = 0;
|
|
||||||
u8 squarePressure = 0;
|
|
||||||
u8 trianglePressure = 0;
|
|
||||||
u8 downPressure = 0;
|
|
||||||
u8 leftPressure = 0;
|
|
||||||
u8 rightPressure = 0;
|
|
||||||
u8 upPressure = 0;
|
|
||||||
u8 l1Pressure = 0;
|
|
||||||
u8 l2Pressure = 0;
|
|
||||||
u8 r1Pressure = 0;
|
|
||||||
u8 r2Pressure = 0;
|
|
||||||
|
|
||||||
/// Pressure Button Flags
|
|
||||||
/// NOTE - It shouldn't be possible to depress a button while also having no pressure
|
|
||||||
/// But for the sake of completeness, it should be tracked.
|
|
||||||
bool circlePressed = false;
|
|
||||||
bool crossPressed = false;
|
|
||||||
bool squarePressed = false;
|
|
||||||
bool trianglePressed = false;
|
|
||||||
bool downPressed = false;
|
|
||||||
bool leftPressed = false;
|
|
||||||
bool rightPressed = false;
|
|
||||||
bool upPressed = false;
|
|
||||||
bool l1Pressed = false;
|
|
||||||
bool l2Pressed = false;
|
|
||||||
bool r1Pressed = false;
|
|
||||||
bool r2Pressed = false;
|
|
||||||
|
|
||||||
/// Normal (un)pressed buttons
|
|
||||||
bool select = false;
|
|
||||||
bool start = false;
|
|
||||||
bool l3 = false;
|
|
||||||
bool r3 = false;
|
|
||||||
|
|
||||||
/// Analog Sticks - 0-255 (127 center)
|
|
||||||
u8 leftAnalogX = ANALOG_VECTOR_NEUTRAL;
|
|
||||||
u8 leftAnalogY = ANALOG_VECTOR_NEUTRAL;
|
|
||||||
u8 rightAnalogX = ANALOG_VECTOR_NEUTRAL;
|
|
||||||
u8 rightAnalogY = ANALOG_VECTOR_NEUTRAL;
|
|
||||||
|
|
||||||
// Given the input buffer and the current index, updates the correct field(s)
|
|
||||||
void UpdateControllerData(u16 bufIndex, u8 const& bufVal);
|
|
||||||
u8 PollControllerData(u16 bufIndex);
|
|
||||||
|
|
||||||
// Prints current PadData to the Controller Log filter which disabled by default
|
|
||||||
void LogPadData(u8 const& port);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct ButtonResolver
|
|
||||||
{
|
|
||||||
u8 buttonBitmask;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ButtonResolver LEFT = ButtonResolver{0b10000000};
|
|
||||||
const ButtonResolver DOWN = ButtonResolver{0b01000000};
|
|
||||||
const ButtonResolver RIGHT = ButtonResolver{0b00100000};
|
|
||||||
const ButtonResolver UP = ButtonResolver{0b00010000};
|
|
||||||
const ButtonResolver START = ButtonResolver{0b00001000};
|
|
||||||
const ButtonResolver R3 = ButtonResolver{0b00000100};
|
|
||||||
const ButtonResolver L3 = ButtonResolver{0b00000010};
|
|
||||||
const ButtonResolver SELECT = ButtonResolver{0b00000001};
|
|
||||||
|
|
||||||
const ButtonResolver SQUARE = ButtonResolver{0b10000000};
|
|
||||||
const ButtonResolver CROSS = ButtonResolver{0b01000000};
|
|
||||||
const ButtonResolver CIRCLE = ButtonResolver{0b00100000};
|
|
||||||
const ButtonResolver TRIANGLE = ButtonResolver{0b00010000};
|
|
||||||
const ButtonResolver R1 = ButtonResolver{0b00001000};
|
|
||||||
const ButtonResolver L1 = ButtonResolver{0b00000100};
|
|
||||||
const ButtonResolver R2 = ButtonResolver{0b00000010};
|
|
||||||
const ButtonResolver L2 = ButtonResolver{0b00000001};
|
|
||||||
|
|
||||||
// Checks and returns if button a is pressed or not
|
|
||||||
bool IsButtonPressed(ButtonResolver buttonResolver, u8 const& bufVal);
|
|
||||||
u8 BitmaskOrZero(bool pressed, ButtonResolver buttonInfo);
|
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
wxString RawPadBytesToString(int start, int end);
|
|
||||||
#else
|
|
||||||
std::string RawPadBytesToString(int start, int end);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class PadData
|
class PadData
|
||||||
{
|
{
|
||||||
|
@ -180,12 +66,6 @@ public:
|
||||||
|
|
||||||
// Prints current PadData to the Controller Log filter which is disabled by default
|
// Prints current PadData to the Controller Log filter which is disabled by default
|
||||||
void LogPadData() const;
|
void LogPadData() const;
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
wxString RawPadBytesToString(int start, int end);
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,438 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2020 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"
|
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "gui/App.h"
|
|
||||||
#include "gui/MSWstuff.h"
|
|
||||||
#include "gui/EmbeddedImage.h"
|
|
||||||
#include "wx/dcbuffer.h"
|
|
||||||
#include "wx/display.h"
|
|
||||||
#include "wx/spinctrl.h"
|
|
||||||
|
|
||||||
#include "Recording/VirtualPad/VirtualPad.h"
|
|
||||||
#include "Recording/VirtualPad/VirtualPadResources.h"
|
|
||||||
|
|
||||||
#include "Recording/VirtualPad/img/circlePressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/controllerFull.h"
|
|
||||||
#include "Recording/VirtualPad/img/controllerThreeQuarters.h"
|
|
||||||
#include "Recording/VirtualPad/img/controllerHalf.h"
|
|
||||||
#include "Recording/VirtualPad/img/crossPressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/downPressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/l1Pressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/l2Pressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/l3Pressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/leftPressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/r1Pressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/r2Pressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/r3Pressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/rightPressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/selectPressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/squarePressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/startPressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/trianglePressed.h"
|
|
||||||
#include "Recording/VirtualPad/img/upPressed.h"
|
|
||||||
|
|
||||||
|
|
||||||
VirtualPad::VirtualPad(wxWindow* parent, int controllerPort, AppConfig::InputRecordingOptions& options)
|
|
||||||
: wxFrame(parent, wxID_ANY, wxEmptyString)
|
|
||||||
, options(options)
|
|
||||||
{
|
|
||||||
// Images at 1.00 scale are designed to work well on HiDPI (4k) at 150% scaling (default recommended setting on windows)
|
|
||||||
// Therefore, on a 1080p monitor we halve the scaling, on 1440p we reduce it by 25%, which from some quick tests looks comparable
|
|
||||||
// Side-note - Getting the DPI scaling amount is platform specific (with some platforms only supporting
|
|
||||||
// integer scaling as well) this is likely not reliable.
|
|
||||||
// Slight multi-monitor support, will use whatever window pcsx2 is opened with, but won't currently re-init if
|
|
||||||
// windows are dragged between differing monitors!
|
|
||||||
wxDisplay display(wxDisplay::GetFromWindow(this));
|
|
||||||
const wxRect screen = display.GetClientArea();
|
|
||||||
float dpiScale = MSW_GetDPIScale(); // linux returns 1.0
|
|
||||||
if (screen.height > 1080 && screen.height <= 1440) // 1440p display
|
|
||||||
scalingFactor = 0.75 * dpiScale;
|
|
||||||
else if (screen.height <= 1080) // 1080p display
|
|
||||||
{
|
|
||||||
scalingFactor = 0.5 * dpiScale;
|
|
||||||
}
|
|
||||||
// otherwise use default 1.0 scaling
|
|
||||||
|
|
||||||
virtualPadData = VirtualPadData();
|
|
||||||
// Based on the scaling factor, select the appropriate background image
|
|
||||||
// Don't scale these images as they've already been pre-scaled
|
|
||||||
if (floatCompare(scalingFactor, 0.5))
|
|
||||||
virtualPadData.background = NewBitmap(EmbeddedImage<res_controllerHalf>().Get(), wxPoint(0, 0), true);
|
|
||||||
else if (floatCompare(scalingFactor, 0.75))
|
|
||||||
virtualPadData.background = NewBitmap(EmbeddedImage<res_controllerThreeQuarters>().Get(), wxPoint(0, 0), true);
|
|
||||||
else
|
|
||||||
// Otherwise, scale down/up (or don't in the case of 1.0) the largst image
|
|
||||||
virtualPadData.background = NewBitmap(EmbeddedImage<res_controllerFull>().Get(), wxPoint(0, 0));
|
|
||||||
|
|
||||||
// Use the background image's size to define the window size
|
|
||||||
SetClientSize(virtualPadData.background.width, virtualPadData.background.height);
|
|
||||||
|
|
||||||
// These hard-coded pixels correspond to where the background image's components are (ie. the buttons)
|
|
||||||
// Everything is automatically scaled and adjusted based on the `scalingFactor` variable
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.square, NewBitmap(EmbeddedImage<res_squarePressed>().Get(), wxPoint(852, 287)), this, wxPoint(1055, 525));
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.triangle, NewBitmap(EmbeddedImage<res_trianglePressed>().Get(), wxPoint(938, 201)), this, wxPoint(1055, 565));
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.circle, NewBitmap(EmbeddedImage<res_circlePressed>().Get(), wxPoint(1024, 286)), this, wxPoint(1055, 605));
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.cross, NewBitmap(EmbeddedImage<res_crossPressed>().Get(), wxPoint(938, 369)), this, wxPoint(1055, 645));
|
|
||||||
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.left, NewBitmap(EmbeddedImage<res_leftPressed>().Get(), wxPoint(110, 303)), this, wxPoint(175, 525), true);
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.up, NewBitmap(EmbeddedImage<res_upPressed>().Get(), wxPoint(186, 227)), this, wxPoint(175, 565), true);
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.right, NewBitmap(EmbeddedImage<res_rightPressed>().Get(), wxPoint(248, 302)), this, wxPoint(175, 605), true);
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.down, NewBitmap(EmbeddedImage<res_downPressed>().Get(), wxPoint(186, 359)), this, wxPoint(175, 645), true);
|
|
||||||
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.l1, NewBitmap(EmbeddedImage<res_l1Pressed>().Get(), wxPoint(156, 98)), this, wxPoint(170, 135));
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.l2, NewBitmap(EmbeddedImage<res_l2Pressed>().Get(), wxPoint(156, 57)), this, wxPoint(170, 52), false, true);
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.r1, NewBitmap(EmbeddedImage<res_r1Pressed>().Get(), wxPoint(921, 98)), this, wxPoint(1035, 135), true);
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.r2, NewBitmap(EmbeddedImage<res_r2Pressed>().Get(), wxPoint(921, 57)), this, wxPoint(1035, 52), true, true);
|
|
||||||
|
|
||||||
InitNormalButtonGuiElements(virtualPadData.select, NewBitmap(EmbeddedImage<res_selectPressed>().Get(), wxPoint(458, 313)), this, wxPoint(530, 315));
|
|
||||||
InitNormalButtonGuiElements(virtualPadData.start, NewBitmap(EmbeddedImage<res_startPressed>().Get(), wxPoint(688, 311)), this, wxPoint(646, 315));
|
|
||||||
InitNormalButtonGuiElements(virtualPadData.l3, NewBitmap(EmbeddedImage<res_l3Pressed>().Get(), wxPoint(336, 453)), this, wxPoint(560, 638));
|
|
||||||
InitNormalButtonGuiElements(virtualPadData.r3, NewBitmap(EmbeddedImage<res_r3Pressed>().Get(), wxPoint(726, 453)), this, wxPoint(615, 638));
|
|
||||||
|
|
||||||
InitAnalogStickGuiElements(virtualPadData.leftAnalog, this, wxPoint(404, 522), 100, wxPoint(314, 642), wxPoint(526, 432), false, wxPoint(504, 685), wxPoint(570, 425), true);
|
|
||||||
InitAnalogStickGuiElements(virtualPadData.rightAnalog, this, wxPoint(794, 522), 100, wxPoint(706, 642), wxPoint(648, 432), true, wxPoint(700, 685), wxPoint(635, 425));
|
|
||||||
|
|
||||||
ignoreRealControllerBox = new wxCheckBox(this, wxID_ANY, wxEmptyString, ScaledPoint(wxPoint(586, 135)), wxDefaultSize);
|
|
||||||
resetButton = new wxButton(this, wxID_ANY, _("Reset"), ScaledPoint(wxPoint(1195, 5), wxSize(100, 50), true), ScaledSize(wxSize(100, 50)));
|
|
||||||
|
|
||||||
Bind(wxEVT_CHECKBOX, &VirtualPad::OnIgnoreRealController, this, ignoreRealControllerBox->GetId());
|
|
||||||
Bind(wxEVT_BUTTON, &VirtualPad::OnResetButton, this, resetButton->GetId());
|
|
||||||
|
|
||||||
// Bind Window Events
|
|
||||||
Bind(wxEVT_MOVE, &VirtualPad::OnMoveAround, this);
|
|
||||||
Bind(wxEVT_CLOSE_WINDOW, &VirtualPad::OnClose, this);
|
|
||||||
Bind(wxEVT_ICONIZE, &VirtualPad::OnIconize, this);
|
|
||||||
Bind(wxEVT_ERASE_BACKGROUND, &VirtualPad::OnEraseBackground, this);
|
|
||||||
// Temporary Paint event handler so the window displays properly before the controller-interrupt routine takes over with manual drawing.
|
|
||||||
// The reason for this is in order to minimize the performance impact, we need total control over when render is called
|
|
||||||
// Windows redraws the window _alot_ otherwise which leads to major performance problems (when GS is using the software renderer)
|
|
||||||
Bind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
|
||||||
// DevCon.WriteLn("Paint Event Bound");
|
|
||||||
|
|
||||||
// Finalize layout
|
|
||||||
SetIcons(wxGetApp().GetIconBundle());
|
|
||||||
SetTitle(wxString::Format("Virtual Pad - Port %d", controllerPort + 1));
|
|
||||||
SetPosition(options.VirtualPadPosition);
|
|
||||||
SetBackgroundColour(*wxWHITE);
|
|
||||||
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
|
||||||
// This window does not allow for resizing for sake of simplicity: all images are scaled initially and stored, ready to be rendered
|
|
||||||
SetWindowStyle(wxDEFAULT_FRAME_STYLE & ~wxRESIZE_BORDER & ~wxMAXIMIZE_BOX);
|
|
||||||
|
|
||||||
// Causes flickering, despite it supposed to be preventing it!
|
|
||||||
// SetDoubleBuffered(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnMoveAround(wxMoveEvent& event)
|
|
||||||
{
|
|
||||||
if (IsBeingDeleted() || !IsVisible() || IsIconized())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!IsMaximized())
|
|
||||||
options.VirtualPadPosition = GetPosition();
|
|
||||||
event.Skip();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnClose(wxCloseEvent& event)
|
|
||||||
{
|
|
||||||
// Re-bind the Paint event in case this is due to a game being opened/closed
|
|
||||||
manualRedrawMode = false;
|
|
||||||
Bind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
|
||||||
// DevCon.WriteLn("Paint Event Bound");
|
|
||||||
Hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnIconize(wxIconizeEvent& event)
|
|
||||||
{
|
|
||||||
if (event.IsIconized())
|
|
||||||
{
|
|
||||||
manualRedrawMode = false;
|
|
||||||
Bind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
|
||||||
// DevCon.WriteLn("Paint Event Bound");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnEraseBackground(wxEraseEvent& event)
|
|
||||||
{
|
|
||||||
// Intentionally Empty
|
|
||||||
// See - https://wiki.wxwidgets.org/Flicker-Free_Drawing
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnPaint(wxPaintEvent& event)
|
|
||||||
{
|
|
||||||
// DevCon.WriteLn("Paint Event Called");
|
|
||||||
wxBufferedPaintDC dc(this, wxBUFFER_VIRTUAL_AREA);
|
|
||||||
Render(dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::Redraw()
|
|
||||||
{
|
|
||||||
wxClientDC cdc(this);
|
|
||||||
wxBufferedDC dc(&cdc);
|
|
||||||
Render(dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::Render(wxDC& bdc)
|
|
||||||
{
|
|
||||||
// Update GUI Elements and figure out what needs to be rendered
|
|
||||||
for (VirtualPadElement* virtualPadElement : virtualPadElements)
|
|
||||||
virtualPadElement->UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
|
|
||||||
// Update Graphic Elements off render stack
|
|
||||||
// Before we start rendering (if we have to) clear and re-draw the background
|
|
||||||
if (!manualRedrawMode || clearScreenRequired || !renderQueue.empty())
|
|
||||||
{
|
|
||||||
bdc.SetBrush(*wxWHITE);
|
|
||||||
bdc.DrawRectangle(wxPoint(0, 0), bdc.GetSize());
|
|
||||||
bdc.SetBrush(wxNullBrush);
|
|
||||||
bdc.DrawBitmap(virtualPadData.background.image, virtualPadData.background.coords, true);
|
|
||||||
clearScreenRequired = false;
|
|
||||||
|
|
||||||
// Switch to Manual Rendering once the first user action on the VirtualPad is taken
|
|
||||||
if (!manualRedrawMode && !renderQueue.empty())
|
|
||||||
{
|
|
||||||
// DevCon.WriteLn("Paint Event Unbound");
|
|
||||||
Unbind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
|
||||||
manualRedrawMode = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE - there is yet another (and I think final) micro-optimization that can be done:
|
|
||||||
// It can be assumed that if the element has already been drawn to the screen (and not cleared) that we can skip rendering it
|
|
||||||
//
|
|
||||||
// For example - you hold a single button for several frames, it will currently draw that every frame
|
|
||||||
// despite the screen never being cleared - so this is not strictly necessary.
|
|
||||||
//
|
|
||||||
// Though after some tests, the performance impact is well within reason, and on the hardware renderer modes, is almost non-existant.
|
|
||||||
while (!renderQueue.empty())
|
|
||||||
{
|
|
||||||
VirtualPadElement* element = renderQueue.front();
|
|
||||||
if (element)
|
|
||||||
element->Render(bdc);
|
|
||||||
renderQueue.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VirtualPad::UpdateControllerData(u16 const bufIndex, PadData* padData)
|
|
||||||
{
|
|
||||||
return virtualPadData.UpdateVirtualPadData(bufIndex, padData, ignoreRealController && !readOnlyMode, readOnlyMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::enableUiElements(bool enable)
|
|
||||||
{
|
|
||||||
ignoreRealControllerBox->Enable(enable);
|
|
||||||
resetButton->Enable(enable);
|
|
||||||
for (VirtualPadElement* virtualPadElement : virtualPadElements)
|
|
||||||
virtualPadElement->EnableWidgets(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::SetReadOnlyMode(bool readOnly)
|
|
||||||
{
|
|
||||||
enableUiElements(!readOnly);
|
|
||||||
readOnlyMode = readOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnIgnoreRealController(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
const wxCheckBox* ignoreButton = (wxCheckBox*)event.GetEventObject();
|
|
||||||
if (ignoreButton)
|
|
||||||
ignoreRealController = ignoreButton->GetValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnResetButton(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
if (readOnlyMode)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (VirtualPadElement* virtualPadElement : virtualPadElements)
|
|
||||||
virtualPadElement->Reset(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnNormalButtonPress(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
const wxCheckBox* pressedButton = (wxCheckBox*)event.GetEventObject();
|
|
||||||
ControllerNormalButton* eventBtn = buttonElements[pressedButton->GetId()];
|
|
||||||
|
|
||||||
if (pressedButton)
|
|
||||||
eventBtn->pressed = pressedButton->GetValue();
|
|
||||||
|
|
||||||
if (!eventBtn->isControllerPressBypassed)
|
|
||||||
eventBtn->isControllerPressBypassed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnPressureButtonPressureChange(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
const wxSpinCtrl* pressureSpinner = (wxSpinCtrl*)event.GetEventObject();
|
|
||||||
ControllerPressureButton* eventBtn = pressureElements[pressureSpinner->GetId()];
|
|
||||||
|
|
||||||
if (pressureSpinner)
|
|
||||||
eventBtn->pressure = pressureSpinner->GetValue();
|
|
||||||
|
|
||||||
eventBtn->pressed = eventBtn->pressure > 0;
|
|
||||||
|
|
||||||
if (!eventBtn->isControllerPressureBypassed || !eventBtn->isControllerPressBypassed)
|
|
||||||
{
|
|
||||||
eventBtn->isControllerPressureBypassed = true;
|
|
||||||
eventBtn->isControllerPressBypassed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnAnalogSpinnerChange(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
const wxSpinCtrl* analogSpinner = (wxSpinCtrl*)event.GetEventObject();
|
|
||||||
AnalogVector* eventVector = analogElements[analogSpinner->GetId()];
|
|
||||||
|
|
||||||
if (analogSpinner)
|
|
||||||
eventVector->val = analogSpinner->GetValue();
|
|
||||||
|
|
||||||
eventVector->slider->SetValue(eventVector->val);
|
|
||||||
|
|
||||||
if (!eventVector->isControllerBypassed)
|
|
||||||
eventVector->isControllerBypassed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnAnalogSliderChange(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
const wxSlider* analogSlider = (wxSlider*)event.GetEventObject();
|
|
||||||
AnalogVector* eventVector = analogElements[analogSlider->GetId()];
|
|
||||||
|
|
||||||
if (analogSlider)
|
|
||||||
eventVector->val = analogSlider->GetValue();
|
|
||||||
|
|
||||||
eventVector->spinner->SetValue(eventVector->val);
|
|
||||||
|
|
||||||
if (!eventVector->isControllerBypassed)
|
|
||||||
eventVector->isControllerBypassed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// GUI Element Utility Functions
|
|
||||||
|
|
||||||
bool VirtualPad::floatCompare(float a, float b, float epsilon)
|
|
||||||
{
|
|
||||||
return (fabs(a - b) < epsilon);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxPoint VirtualPad::ScaledPoint(wxPoint point, wxSize widgetWidth, bool rightAlignedCoord, bool bottomAlignedCoord)
|
|
||||||
{
|
|
||||||
return ScaledPoint(point.x, point.y, widgetWidth.x, widgetWidth.y, rightAlignedCoord, bottomAlignedCoord);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxPoint VirtualPad::ScaledPoint(int x, int y, int widgetWidth, int widgetHeight, bool rightAlignedCoord, bool bottomAlignedCoord)
|
|
||||||
{
|
|
||||||
wxPoint scaledPoint = wxPoint(x * scalingFactor, y * scalingFactor);
|
|
||||||
if (rightAlignedCoord)
|
|
||||||
{
|
|
||||||
scaledPoint.x -= widgetWidth * scalingFactor;
|
|
||||||
if (scaledPoint.x < 0)
|
|
||||||
scaledPoint.x = 0;
|
|
||||||
}
|
|
||||||
if (bottomAlignedCoord)
|
|
||||||
{
|
|
||||||
scaledPoint.y -= widgetHeight * scalingFactor;
|
|
||||||
if (scaledPoint.y < 0)
|
|
||||||
scaledPoint.y = 0;
|
|
||||||
}
|
|
||||||
return scaledPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxSize VirtualPad::ScaledSize(wxSize size)
|
|
||||||
{
|
|
||||||
return ScaledSize(size.x, size.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxSize VirtualPad::ScaledSize(int x, int y)
|
|
||||||
{
|
|
||||||
return wxSize(x * scalingFactor, y * scalingFactor);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageFile VirtualPad::NewBitmap(wxImage resource, wxPoint imgCoord, bool dontScale)
|
|
||||||
{
|
|
||||||
return NewBitmap(dontScale ? 1 : scalingFactor, resource, imgCoord);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageFile VirtualPad::NewBitmap(float scalingFactor, wxImage resource, wxPoint imgCoord)
|
|
||||||
{
|
|
||||||
wxBitmap bitmap = wxBitmap(resource.Rescale(resource.GetWidth() * scalingFactor, resource.GetHeight() * scalingFactor, wxIMAGE_QUALITY_HIGH));
|
|
||||||
|
|
||||||
ImageFile image = ImageFile();
|
|
||||||
image.image = bitmap;
|
|
||||||
image.width = bitmap.GetWidth();
|
|
||||||
image.height = bitmap.GetHeight();
|
|
||||||
image.coords = ScaledPoint(imgCoord);
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::InitNormalButtonGuiElements(ControllerNormalButton& button, ImageFile image, wxWindow* parentWindow, wxPoint checkboxCoord)
|
|
||||||
{
|
|
||||||
button.icon = image;
|
|
||||||
button.pressedBox = new wxCheckBox(parentWindow, wxID_ANY, wxEmptyString, ScaledPoint(checkboxCoord), wxDefaultSize);
|
|
||||||
Bind(wxEVT_CHECKBOX, &VirtualPad::OnNormalButtonPress, this, button.pressedBox->GetId());
|
|
||||||
buttonElements[button.pressedBox->GetId()] = &button;
|
|
||||||
virtualPadElements.push_back(&button);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::InitPressureButtonGuiElements(ControllerPressureButton& button, ImageFile image, wxWindow* parentWindow, wxPoint pressureSpinnerCoord, bool rightAlignedCoord, bool bottomAlignedCoord)
|
|
||||||
{
|
|
||||||
const wxPoint scaledPoint = ScaledPoint(pressureSpinnerCoord, SPINNER_SIZE, rightAlignedCoord, bottomAlignedCoord);
|
|
||||||
wxSpinCtrl* spinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, scaledPoint, ScaledSize(SPINNER_SIZE), wxSP_ARROW_KEYS, 0, 255, 0);
|
|
||||||
|
|
||||||
button.icon = image;
|
|
||||||
button.pressureSpinner = spinner;
|
|
||||||
Bind(wxEVT_SPINCTRL, &VirtualPad::OnPressureButtonPressureChange, this, button.pressureSpinner->GetId());
|
|
||||||
pressureElements[button.pressureSpinner->GetId()] = &button;
|
|
||||||
virtualPadElements.push_back(&button);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::InitAnalogStickGuiElements(AnalogStick& analog, wxWindow* parentWindow, wxPoint centerPoint, int radius,
|
|
||||||
wxPoint xSliderPoint, wxPoint ySliderPoint, bool flipYSlider, wxPoint xSpinnerPoint, wxPoint ySpinnerPoint, bool rightAlignedSpinners)
|
|
||||||
{
|
|
||||||
AnalogPosition analogPos = AnalogPosition();
|
|
||||||
analogPos.centerCoords = ScaledPoint(centerPoint);
|
|
||||||
analogPos.endCoords = ScaledPoint(centerPoint);
|
|
||||||
analogPos.radius = radius * scalingFactor;
|
|
||||||
analogPos.lineThickness = 6 * scalingFactor;
|
|
||||||
|
|
||||||
const wxPoint xSpinnerScaledPoint = ScaledPoint(xSpinnerPoint, SPINNER_SIZE, rightAlignedSpinners);
|
|
||||||
const wxPoint ySpinnerScaledPoint = ScaledPoint(ySpinnerPoint, SPINNER_SIZE, rightAlignedSpinners, true);
|
|
||||||
|
|
||||||
wxSlider* xSlider = new wxSlider(parentWindow, wxID_ANY, ANALOG_NEUTRAL, 0, ANALOG_MAX,
|
|
||||||
ScaledPoint(xSliderPoint), ScaledSize(ANALOG_SLIDER_WIDTH, ANALOG_SLIDER_HEIGHT));
|
|
||||||
wxSlider* ySlider = new wxSlider(parentWindow, wxID_ANY, ANALOG_NEUTRAL, 0, ANALOG_MAX,
|
|
||||||
ScaledPoint(ySliderPoint), ScaledSize(ANALOG_SLIDER_HEIGHT, ANALOG_SLIDER_WIDTH), flipYSlider ? wxSL_LEFT : wxSL_RIGHT);
|
|
||||||
wxSpinCtrl* xSpinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, xSpinnerScaledPoint, ScaledSize(SPINNER_SIZE), wxSP_ARROW_KEYS, 0, 255, 127);
|
|
||||||
wxSpinCtrl* ySpinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, ySpinnerScaledPoint, ScaledSize(SPINNER_SIZE), wxSP_ARROW_KEYS, 0, 255, 127);
|
|
||||||
|
|
||||||
analog.xVector.slider = xSlider;
|
|
||||||
analog.yVector.slider = ySlider;
|
|
||||||
analog.xVector.spinner = xSpinner;
|
|
||||||
analog.yVector.spinner = ySpinner;
|
|
||||||
analog.positionGraphic = analogPos;
|
|
||||||
Bind(wxEVT_SLIDER, &VirtualPad::OnAnalogSliderChange, this, xSlider->GetId());
|
|
||||||
Bind(wxEVT_SLIDER, &VirtualPad::OnAnalogSliderChange, this, ySlider->GetId());
|
|
||||||
Bind(wxEVT_SPINCTRL, &VirtualPad::OnAnalogSpinnerChange, this, xSpinner->GetId());
|
|
||||||
Bind(wxEVT_SPINCTRL, &VirtualPad::OnAnalogSpinnerChange, this, ySpinner->GetId());
|
|
||||||
analogElements[xSlider->GetId()] = &analog.xVector;
|
|
||||||
analogElements[ySlider->GetId()] = &analog.yVector;
|
|
||||||
analogElements[xSpinner->GetId()] = &analog.xVector;
|
|
||||||
analogElements[ySpinner->GetId()] = &analog.yVector;
|
|
||||||
virtualPadElements.push_back(&analog);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,119 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2020 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
|
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
#include "gui/AppConfig.h"
|
|
||||||
#include "common/Pcsx2Types.h"
|
|
||||||
|
|
||||||
#include "wx/button.h"
|
|
||||||
#include "wx/checkbox.h"
|
|
||||||
#include "wx/dc.h"
|
|
||||||
#include "wx/event.h"
|
|
||||||
#include "wx/frame.h"
|
|
||||||
#include "wx/gdicmn.h"
|
|
||||||
#include "wx/string.h"
|
|
||||||
#include "wx/window.h"
|
|
||||||
#include "wx/windowid.h"
|
|
||||||
|
|
||||||
#include "Recording/PadData.h"
|
|
||||||
#include "Recording/VirtualPad/VirtualPadData.h"
|
|
||||||
|
|
||||||
class VirtualPad : public wxFrame
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VirtualPad(wxWindow* parent, int controllerPort, AppConfig::InputRecordingOptions& options);
|
|
||||||
// Updates the VirtualPad's data if necessary, as well as updates the provided PadData if the VirtualPad overrides it
|
|
||||||
// - PadData will not be updated if ReadOnly mode is set
|
|
||||||
// - returns a bool to indicate if the PadData has been updated
|
|
||||||
bool UpdateControllerData(u16 const bufIndex, PadData* padData);
|
|
||||||
// Enables/Disables read only mode and enables/disables GUI widgets
|
|
||||||
void SetReadOnlyMode(bool readOnly);
|
|
||||||
// To be called at maximum, once per frame to update widget's value and re-render the VirtualPad's graphics
|
|
||||||
void Redraw();
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// Constants
|
|
||||||
const wxSize SPINNER_SIZE = wxSize(100, 40);
|
|
||||||
static const int ANALOG_SLIDER_WIDTH = 185;
|
|
||||||
static const int ANALOG_SLIDER_HEIGHT = 30;
|
|
||||||
|
|
||||||
static const int PRESSURE_MAX = 255;
|
|
||||||
static const int ANALOG_NEUTRAL = 127;
|
|
||||||
static const int ANALOG_MAX = 255;
|
|
||||||
|
|
||||||
AppConfig::InputRecordingOptions& options;
|
|
||||||
|
|
||||||
bool clearScreenRequired = false;
|
|
||||||
bool ignoreRealController = false;
|
|
||||||
// When enabled, forces the VirtualPad to be re-rendered even if no updates are made.
|
|
||||||
// This helps to make sure the UI is rendered prior to receiving data from the controller
|
|
||||||
bool manualRedrawMode = false;
|
|
||||||
bool readOnlyMode = false;
|
|
||||||
|
|
||||||
VirtualPadData virtualPadData;
|
|
||||||
|
|
||||||
std::vector<VirtualPadElement*> virtualPadElements;
|
|
||||||
std::queue<VirtualPadElement*> renderQueue;
|
|
||||||
|
|
||||||
void enableUiElements(bool enable);
|
|
||||||
|
|
||||||
/// GUI Elements
|
|
||||||
wxCheckBox* ignoreRealControllerBox;
|
|
||||||
wxButton* resetButton;
|
|
||||||
|
|
||||||
std::map<wxWindowID, ControllerNormalButton*> buttonElements;
|
|
||||||
std::map<wxWindowID, ControllerPressureButton*> pressureElements;
|
|
||||||
std::map<wxWindowID, AnalogVector*> analogElements;
|
|
||||||
|
|
||||||
/// Event Listeners
|
|
||||||
void OnMoveAround(wxMoveEvent& event);
|
|
||||||
void OnClose(wxCloseEvent& event);
|
|
||||||
void OnIconize(wxIconizeEvent& event);
|
|
||||||
void OnEraseBackground(wxEraseEvent& event);
|
|
||||||
void OnPaint(wxPaintEvent& event);
|
|
||||||
void Render(wxDC& dc);
|
|
||||||
|
|
||||||
void OnAnalogSliderChange(wxCommandEvent& event);
|
|
||||||
void OnAnalogSpinnerChange(wxCommandEvent& event);
|
|
||||||
void OnIgnoreRealController(wxCommandEvent& event);
|
|
||||||
void OnNormalButtonPress(wxCommandEvent& event);
|
|
||||||
void OnPressureButtonPressureChange(wxCommandEvent& event);
|
|
||||||
void OnResetButton(wxCommandEvent& event);
|
|
||||||
|
|
||||||
/// GUI Creation Utility Functions
|
|
||||||
float scalingFactor = 1.0;
|
|
||||||
bool floatCompare(float A, float B, float epsilon = 0.005f);
|
|
||||||
|
|
||||||
wxSize ScaledSize(wxSize size);
|
|
||||||
wxSize ScaledSize(int x, int y);
|
|
||||||
wxPoint ScaledPoint(wxPoint point, wxSize widgetSize = wxDefaultSize, bool rightAlignedCoord = false, bool bottomAlignedCoord = false);
|
|
||||||
wxPoint ScaledPoint(int x, int y, int widgetWidth, int widgetHeight, bool rightAlignedCoord = false, bool bottomAlignedCoord = false);
|
|
||||||
|
|
||||||
ImageFile NewBitmap(wxImage resource, wxPoint imgCoord, bool dontScale = false);
|
|
||||||
ImageFile NewBitmap(float scalingFactor, wxImage resource, wxPoint imgCoord);
|
|
||||||
|
|
||||||
void InitPressureButtonGuiElements(ControllerPressureButton& button, ImageFile image, wxWindow* parentWindow, wxPoint pressureSpinnerCoord, bool rightAlignedCoord = false, bool bottomAlignedCoord = false);
|
|
||||||
void InitNormalButtonGuiElements(ControllerNormalButton& btn, ImageFile image, wxWindow* parentWindow, wxPoint checkboxCoord);
|
|
||||||
void InitAnalogStickGuiElements(AnalogStick& analog, wxWindow* parentWindow, wxPoint centerPoint, int radius, wxPoint xSliderPoint,
|
|
||||||
wxPoint ySliderPoint, bool flipYSlider, wxPoint xSpinnerPoint, wxPoint ySpinnerPoint, bool rightAlignedSpinners = false);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,84 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2020 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"
|
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
|
|
||||||
#include "Recording/VirtualPad/VirtualPadData.h"
|
|
||||||
|
|
||||||
bool VirtualPadData::UpdateVirtualPadData(u16 bufIndex, PadData* padData, bool ignoreRealController, bool readOnly)
|
|
||||||
{
|
|
||||||
bool changeDetected = false;
|
|
||||||
PadData::BufferIndex index = static_cast<PadData::BufferIndex>(bufIndex);
|
|
||||||
switch (index)
|
|
||||||
{
|
|
||||||
case PadData::BufferIndex::PressedFlagsGroupOne:
|
|
||||||
changeDetected |= left.UpdateData(padData->leftPressed, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= down.UpdateData(padData->downPressed, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= right.UpdateData(padData->rightPressed, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= up.UpdateData(padData->upPressed, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= start.UpdateData(padData->start, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= r3.UpdateData(padData->r3, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= l3.UpdateData(padData->l3, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= select.UpdateData(padData->select, ignoreRealController, readOnly);
|
|
||||||
return changeDetected;
|
|
||||||
case PadData::BufferIndex::PressedFlagsGroupTwo:
|
|
||||||
changeDetected |= square.UpdateData(padData->squarePressed, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= cross.UpdateData(padData->crossPressed, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= circle.UpdateData(padData->circlePressed, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= triangle.UpdateData(padData->trianglePressed, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= r1.UpdateData(padData->r1Pressed, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= l1.UpdateData(padData->l1Pressed, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= r2.UpdateData(padData->r2Pressed, ignoreRealController, readOnly);
|
|
||||||
changeDetected |= l2.UpdateData(padData->l2Pressed, ignoreRealController, readOnly);
|
|
||||||
return changeDetected;
|
|
||||||
case PadData::BufferIndex::RightAnalogXVector:
|
|
||||||
return rightAnalog.xVector.UpdateData(padData->rightAnalogX, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::RightAnalogYVector:
|
|
||||||
return rightAnalog.yVector.UpdateData(padData->rightAnalogY, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::LeftAnalogXVector:
|
|
||||||
return leftAnalog.xVector.UpdateData(padData->leftAnalogX, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::LeftAnalogYVector:
|
|
||||||
return leftAnalog.yVector.UpdateData(padData->leftAnalogY, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::RightPressure:
|
|
||||||
return right.UpdateData(padData->rightPressure, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::LeftPressure:
|
|
||||||
return left.UpdateData(padData->leftPressure, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::UpPressure:
|
|
||||||
return up.UpdateData(padData->upPressure, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::DownPressure:
|
|
||||||
return down.UpdateData(padData->downPressure, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::TrianglePressure:
|
|
||||||
return triangle.UpdateData(padData->trianglePressure, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::CirclePressure:
|
|
||||||
return circle.UpdateData(padData->circlePressure, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::CrossPressure:
|
|
||||||
return cross.UpdateData(padData->crossPressure, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::SquarePressure:
|
|
||||||
return square.UpdateData(padData->squarePressure, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::L1Pressure:
|
|
||||||
return l1.UpdateData(padData->l1Pressure, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::R1Pressure:
|
|
||||||
return r1.UpdateData(padData->r1Pressure, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::L2Pressure:
|
|
||||||
return l2.UpdateData(padData->l2Pressure, ignoreRealController, readOnly);
|
|
||||||
case PadData::BufferIndex::R2Pressure:
|
|
||||||
return r2.UpdateData(padData->r2Pressure, ignoreRealController, readOnly);
|
|
||||||
}
|
|
||||||
return changeDetected;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,63 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2020 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
|
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
|
|
||||||
#include "common/Pcsx2Types.h"
|
|
||||||
|
|
||||||
#include "Recording/PadData.h"
|
|
||||||
#include "Recording/VirtualPad/VirtualPadResources.h"
|
|
||||||
|
|
||||||
class VirtualPadData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/// Controller Background
|
|
||||||
ImageFile background;
|
|
||||||
|
|
||||||
/// Pressure Buttons
|
|
||||||
ControllerPressureButton circle;
|
|
||||||
ControllerPressureButton cross;
|
|
||||||
ControllerPressureButton down;
|
|
||||||
ControllerPressureButton l1;
|
|
||||||
ControllerPressureButton l2;
|
|
||||||
ControllerPressureButton left;
|
|
||||||
ControllerPressureButton r1;
|
|
||||||
ControllerPressureButton r2;
|
|
||||||
ControllerPressureButton right;
|
|
||||||
ControllerPressureButton square;
|
|
||||||
ControllerPressureButton triangle;
|
|
||||||
ControllerPressureButton up;
|
|
||||||
|
|
||||||
/// Normal (un)pressed buttons
|
|
||||||
ControllerNormalButton l3;
|
|
||||||
ControllerNormalButton r3;
|
|
||||||
ControllerNormalButton select;
|
|
||||||
ControllerNormalButton start;
|
|
||||||
|
|
||||||
/// Analog Sticks
|
|
||||||
AnalogStick leftAnalog;
|
|
||||||
AnalogStick rightAnalog;
|
|
||||||
|
|
||||||
// Given the input buffer and the current index, updates the respective field(s) within this object
|
|
||||||
// Additionally overwrites the PadData object under the following criteria:
|
|
||||||
// - If ignoreRealController is true (and readOnly is false) PadData will always be updated
|
|
||||||
// - else if the VirtualPad has overwritten the value, and the real controller has not changed since that moment in time
|
|
||||||
// returns a boolean to indicate if it has updated the PadData
|
|
||||||
bool UpdateVirtualPadData(u16 bufIndex, PadData* padData, bool ignoreRealController = false, bool readOnly = false);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,267 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2020 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"
|
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
|
|
||||||
#include <wx/spinctrl.h>
|
|
||||||
|
|
||||||
#include "Recording/VirtualPad/VirtualPadResources.h"
|
|
||||||
#include "Recording/PadData.h"
|
|
||||||
|
|
||||||
wxCommandEvent VirtualPadElement::ConstructEvent(wxEventTypeTag<wxCommandEvent> eventType, wxWindow* obj)
|
|
||||||
{
|
|
||||||
wxCommandEvent event(eventType, obj->GetId());
|
|
||||||
event.SetEventObject(obj);
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxCommandEvent VirtualPadElement::ConstructEvent(wxEventTypeTag<wxSpinEvent> eventType, wxWindow* obj)
|
|
||||||
{
|
|
||||||
wxCommandEvent event(eventType, obj->GetId());
|
|
||||||
event.SetEventObject(obj);
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControllerNormalButton::UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired)
|
|
||||||
{
|
|
||||||
ControllerNormalButton& button = *this;
|
|
||||||
// This boolean is set when we parse the PadData in VirtualPadData::UpdateVirtualPadData
|
|
||||||
// Updating wxWidget elements can be expensive, we only want to do this if required
|
|
||||||
if (button.widgetUpdateRequired)
|
|
||||||
button.pressedBox->SetValue(button.pressed);
|
|
||||||
|
|
||||||
// We only render the button if it is pressed
|
|
||||||
if (button.pressed)
|
|
||||||
renderQueue.push(this);
|
|
||||||
// However, if the button has been drawn to the screen in the past
|
|
||||||
// we need to ensure the screen is cleared.
|
|
||||||
// This is needed in the scenario where only a single button is being pressed/released
|
|
||||||
// As no other elements will trigger a clear
|
|
||||||
else if (button.currentlyRendered)
|
|
||||||
{
|
|
||||||
button.currentlyRendered = false;
|
|
||||||
clearScreenRequired = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControllerPressureButton::UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired)
|
|
||||||
{
|
|
||||||
ControllerPressureButton& button = *this;
|
|
||||||
if (button.widgetUpdateRequired)
|
|
||||||
button.pressureSpinner->SetValue(button.pressure);
|
|
||||||
|
|
||||||
if (button.pressed)
|
|
||||||
renderQueue.push(this);
|
|
||||||
else if (button.currentlyRendered)
|
|
||||||
{
|
|
||||||
button.currentlyRendered = false;
|
|
||||||
clearScreenRequired = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnalogStick::UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired)
|
|
||||||
{
|
|
||||||
AnalogStick& analogStick = *this;
|
|
||||||
if (analogStick.xVector.widgetUpdateRequired)
|
|
||||||
{
|
|
||||||
analogStick.xVector.slider->SetValue(analogStick.xVector.val);
|
|
||||||
analogStick.xVector.spinner->SetValue(analogStick.xVector.val);
|
|
||||||
}
|
|
||||||
if (analogStick.yVector.widgetUpdateRequired)
|
|
||||||
{
|
|
||||||
analogStick.yVector.slider->SetValue(analogStick.yVector.val);
|
|
||||||
analogStick.yVector.spinner->SetValue(analogStick.yVector.val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We render the analog sticks as long as they are not in the neutral position
|
|
||||||
if (!(analogStick.xVector.val == PadData::ANALOG_VECTOR_NEUTRAL && analogStick.yVector.val == PadData::ANALOG_VECTOR_NEUTRAL))
|
|
||||||
renderQueue.push(this);
|
|
||||||
else if (analogStick.currentlyRendered)
|
|
||||||
{
|
|
||||||
analogStick.currentlyRendered = false;
|
|
||||||
clearScreenRequired = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControllerNormalButton::EnableWidgets(bool enable)
|
|
||||||
{
|
|
||||||
this->pressedBox->Enable(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControllerPressureButton::EnableWidgets(bool enable)
|
|
||||||
{
|
|
||||||
this->pressureSpinner->Enable(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnalogStick::EnableWidgets(bool enable)
|
|
||||||
{
|
|
||||||
this->xVector.slider->Enable(enable);
|
|
||||||
this->yVector.slider->Enable(enable);
|
|
||||||
this->xVector.spinner->Enable(enable);
|
|
||||||
this->yVector.spinner->Enable(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControllerNormalButton::Render(wxDC& dc)
|
|
||||||
{
|
|
||||||
ControllerNormalButton& button = *this;
|
|
||||||
ImageFile& img = button.icon;
|
|
||||||
dc.DrawBitmap(img.image, img.coords, true);
|
|
||||||
button.currentlyRendered = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControllerPressureButton::Render(wxDC& dc)
|
|
||||||
{
|
|
||||||
ControllerPressureButton& button = *this;
|
|
||||||
ImageFile& img = button.icon;
|
|
||||||
dc.DrawBitmap(img.image, img.coords, true);
|
|
||||||
button.currentlyRendered = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnalogStick::Render(wxDC& dc)
|
|
||||||
{
|
|
||||||
AnalogStick& analogStick = *this;
|
|
||||||
// Render graphic
|
|
||||||
AnalogPosition analogPos = analogStick.positionGraphic;
|
|
||||||
// Determine new end coordinates
|
|
||||||
int newXCoord = analogPos.centerCoords.x + ((analogStick.xVector.val - 127) / 127.0) * analogPos.radius;
|
|
||||||
int newYCoord = analogPos.centerCoords.y + ((analogStick.yVector.val - 127) / 127.0) * analogPos.radius;
|
|
||||||
// We want to ensure the line segment length is capped at the defined radius
|
|
||||||
// NOTE - The conventional way to do this is using arctan2, but the analog values that come out
|
|
||||||
// of Pad in pcsx2 do not permit this, the coordinates returned do not define a circle.
|
|
||||||
const float lengthOfLine = sqrt(pow(newXCoord - analogPos.centerCoords.x, 2) + pow(newYCoord - analogPos.centerCoords.y, 2));
|
|
||||||
if (lengthOfLine > analogPos.radius)
|
|
||||||
{
|
|
||||||
newXCoord = ((1 - analogPos.radius / lengthOfLine) * analogPos.centerCoords.x) + analogPos.radius / lengthOfLine * newXCoord;
|
|
||||||
newYCoord = ((1 - analogPos.radius / lengthOfLine) * analogPos.centerCoords.y) + analogPos.radius / lengthOfLine * newYCoord;
|
|
||||||
}
|
|
||||||
// Set the new end coordinate
|
|
||||||
analogPos.endCoords = wxPoint(newXCoord, newYCoord);
|
|
||||||
// Draw line and tip
|
|
||||||
dc.SetPen(wxPen(*wxBLUE, analogPos.lineThickness));
|
|
||||||
dc.DrawLine(analogPos.centerCoords, analogPos.endCoords);
|
|
||||||
dc.DrawCircle(analogPos.endCoords, wxCoord(analogPos.lineThickness));
|
|
||||||
dc.SetPen(wxNullPen);
|
|
||||||
analogStick.currentlyRendered = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControllerNormalButton::Reset(wxEvtHandler* destWindow)
|
|
||||||
{
|
|
||||||
this->pressedBox->SetValue(false);
|
|
||||||
wxPostEvent(destWindow, ConstructEvent(wxEVT_CHECKBOX, this->pressedBox));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControllerPressureButton::Reset(wxEvtHandler* destWindow)
|
|
||||||
{
|
|
||||||
this->pressureSpinner->SetValue(0);
|
|
||||||
wxPostEvent(destWindow, ConstructEvent(wxEVT_SPINCTRL, this->pressureSpinner));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnalogStick::Reset(wxEvtHandler* destWindow)
|
|
||||||
{
|
|
||||||
this->xVector.slider->SetValue(127);
|
|
||||||
this->yVector.slider->SetValue(127);
|
|
||||||
wxPostEvent(destWindow, ConstructEvent(wxEVT_SLIDER, this->xVector.slider));
|
|
||||||
wxPostEvent(destWindow, ConstructEvent(wxEVT_SLIDER, this->yVector.slider));
|
|
||||||
this->xVector.spinner->SetValue(127);
|
|
||||||
this->xVector.spinner->SetValue(127);
|
|
||||||
wxPostEvent(destWindow, ConstructEvent(wxEVT_SPINCTRL, this->xVector.spinner));
|
|
||||||
wxPostEvent(destWindow, ConstructEvent(wxEVT_SPINCTRL, this->yVector.spinner));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ControllerNormalButton::UpdateData(bool& padDataVal, bool ignoreRealController, bool readOnly)
|
|
||||||
{
|
|
||||||
return this->UpdateButtonData(padDataVal, ignoreRealController, readOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ControllerPressureButton::UpdateData(bool& padDataVal, bool ignoreRealController, bool readOnly)
|
|
||||||
{
|
|
||||||
return this->UpdateButtonData(padDataVal, ignoreRealController, readOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ControllerButton::UpdateButtonData(bool& padDataVal, bool ignoreRealController, bool readOnly)
|
|
||||||
{
|
|
||||||
ControllerButton& button = *this;
|
|
||||||
if (!ignoreRealController || readOnly)
|
|
||||||
{
|
|
||||||
// If controller is being bypassed and controller's state has changed
|
|
||||||
const bool bypassedWithChangedState = button.isControllerPressBypassed && padDataVal != button.prevPressedVal;
|
|
||||||
if (bypassedWithChangedState)
|
|
||||||
{
|
|
||||||
button.prevPressedVal = padDataVal;
|
|
||||||
button.isControllerPressBypassed = false;
|
|
||||||
}
|
|
||||||
// If we aren't bypassing the controller OR the previous condition was met
|
|
||||||
if (bypassedWithChangedState || !button.isControllerPressBypassed || readOnly)
|
|
||||||
{
|
|
||||||
button.widgetUpdateRequired = button.pressed != padDataVal;
|
|
||||||
button.pressed = padDataVal;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Otherwise, we update the real PadData value, which will in turn be used to update the interrupt's buffer
|
|
||||||
button.prevPressedVal = padDataVal;
|
|
||||||
padDataVal = button.pressed;
|
|
||||||
return button.prevPressedVal != button.pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ControllerPressureButton::UpdateData(u8& padDataVal, bool ignoreRealController, bool readOnly)
|
|
||||||
{
|
|
||||||
ControllerPressureButton& button = *this;
|
|
||||||
if (!ignoreRealController || readOnly)
|
|
||||||
{
|
|
||||||
const bool bypassedWithChangedState = button.isControllerPressureBypassed && padDataVal != button.prevPressureVal;
|
|
||||||
if (bypassedWithChangedState)
|
|
||||||
{
|
|
||||||
button.prevPressureVal = padDataVal;
|
|
||||||
button.isControllerPressureBypassed = false;
|
|
||||||
}
|
|
||||||
if (bypassedWithChangedState || !button.isControllerPressureBypassed || readOnly)
|
|
||||||
{
|
|
||||||
button.widgetUpdateRequired = button.pressure != padDataVal;
|
|
||||||
button.pressure = padDataVal;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
button.prevPressureVal = padDataVal;
|
|
||||||
padDataVal = button.pressure;
|
|
||||||
return button.prevPressureVal != button.pressure;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AnalogVector::UpdateData(u8& padDataVal, bool ignoreRealController, bool readOnly)
|
|
||||||
{
|
|
||||||
AnalogVector& vector = *this;
|
|
||||||
if (!ignoreRealController || readOnly)
|
|
||||||
{
|
|
||||||
const bool bypassedWithChangedState = vector.isControllerBypassed && padDataVal != vector.prevVal;
|
|
||||||
if (bypassedWithChangedState)
|
|
||||||
{
|
|
||||||
vector.prevVal = padDataVal;
|
|
||||||
vector.isControllerBypassed = false;
|
|
||||||
}
|
|
||||||
if (bypassedWithChangedState || !vector.isControllerBypassed || readOnly)
|
|
||||||
{
|
|
||||||
vector.widgetUpdateRequired = vector.val != padDataVal;
|
|
||||||
vector.val = padDataVal;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vector.prevVal = padDataVal;
|
|
||||||
padDataVal = vector.val;
|
|
||||||
return vector.prevVal != vector.val;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,133 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2020 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
|
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
#include "common/Pcsx2Types.h"
|
|
||||||
#include "wx/bitmap.h"
|
|
||||||
#include "wx/checkbox.h"
|
|
||||||
#include "wx/gdicmn.h"
|
|
||||||
#include "wx/slider.h"
|
|
||||||
#include "wx/spinctrl.h"
|
|
||||||
#include "wx/dcbuffer.h"
|
|
||||||
|
|
||||||
struct ImageFile
|
|
||||||
{
|
|
||||||
wxBitmap image;
|
|
||||||
wxPoint coords;
|
|
||||||
u32 width = 0;
|
|
||||||
u32 height = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AnalogVector
|
|
||||||
{
|
|
||||||
wxSlider* slider = 0;
|
|
||||||
wxSpinCtrl* spinner = 0;
|
|
||||||
|
|
||||||
u8 val = 127;
|
|
||||||
|
|
||||||
bool isControllerBypassed = false;
|
|
||||||
bool widgetUpdateRequired = false;
|
|
||||||
u8 prevVal = 127;
|
|
||||||
|
|
||||||
bool UpdateData(u8& padDataVal, bool ignoreRealController, bool readOnly);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct AnalogPosition
|
|
||||||
{
|
|
||||||
wxPoint centerCoords;
|
|
||||||
wxPoint endCoords;
|
|
||||||
|
|
||||||
int lineThickness = 0;
|
|
||||||
int radius = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VirtualPadElement
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool currentlyRendered = false;
|
|
||||||
|
|
||||||
wxCommandEvent ConstructEvent(wxEventTypeTag<wxCommandEvent> eventType, wxWindow *obj);
|
|
||||||
wxCommandEvent ConstructEvent(wxEventTypeTag<wxSpinEvent> eventType, wxWindow *obj);
|
|
||||||
|
|
||||||
virtual void EnableWidgets(bool enable) = 0;
|
|
||||||
virtual void Render(wxDC& dc) = 0;
|
|
||||||
virtual void Reset(wxEvtHandler* destWindow) = 0;
|
|
||||||
virtual void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ControllerButton
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool isControllerPressBypassed = false;
|
|
||||||
bool pressed = false;
|
|
||||||
bool prevPressedVal = false;
|
|
||||||
bool widgetUpdateRequired = false;
|
|
||||||
|
|
||||||
bool UpdateButtonData(bool& padDataVal, bool ignoreRealController, bool readOnly);
|
|
||||||
};
|
|
||||||
|
|
||||||
class ControllerNormalButton : public ControllerButton, public VirtualPadElement
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ImageFile icon;
|
|
||||||
wxCheckBox* pressedBox = 0;
|
|
||||||
|
|
||||||
bool UpdateData(bool& padDataVal, bool ignoreRealController, bool readOnly);
|
|
||||||
void EnableWidgets(bool enable) override;
|
|
||||||
void Render(wxDC& dc) override;
|
|
||||||
void Reset(wxEvtHandler* destWindow) override;
|
|
||||||
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ControllerPressureButton : public ControllerButton, public VirtualPadElement
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ImageFile icon;
|
|
||||||
wxSpinCtrl* pressureSpinner = 0;
|
|
||||||
|
|
||||||
u8 pressure = 0;
|
|
||||||
|
|
||||||
bool isControllerPressureBypassed = false;
|
|
||||||
u8 prevPressureVal = 0;
|
|
||||||
|
|
||||||
bool UpdateData(bool& padDataVal, bool ignoreRealController, bool readOnly);
|
|
||||||
bool UpdateData(u8& padDataVal, bool ignoreRealController, bool readOnly);
|
|
||||||
void EnableWidgets(bool enable) override;
|
|
||||||
void Render(wxDC& dc) override;
|
|
||||||
void Reset(wxEvtHandler* destWindow) override;
|
|
||||||
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AnalogStick : public VirtualPadElement
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AnalogVector xVector;
|
|
||||||
AnalogVector yVector;
|
|
||||||
|
|
||||||
AnalogPosition positionGraphic;
|
|
||||||
|
|
||||||
void EnableWidgets(bool enable) override;
|
|
||||||
void Render(wxDC& dc) override;
|
|
||||||
void Reset(wxEvtHandler* destWindow) override;
|
|
||||||
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1 +0,0 @@
|
||||||
*.h
|
|
|
@ -1,18 +0,0 @@
|
||||||
|
|
||||||
:: Probably self-explanatory: This batch file compiles a single souce image into a
|
|
||||||
:: CPP header file for use by pcsx2.
|
|
||||||
::
|
|
||||||
:: bin2cpp.cmd SrcImage
|
|
||||||
::
|
|
||||||
:: Parameters
|
|
||||||
:: SrcImage - Complete filename with extension.
|
|
||||||
::
|
|
||||||
|
|
||||||
@echo off
|
|
||||||
|
|
||||||
SETLOCAL ENABLEEXTENSIONS
|
|
||||||
|
|
||||||
cd "%~0\..\"
|
|
||||||
"..\..\..\..\tools\bin\bin2cpp.exe" %1
|
|
||||||
|
|
||||||
ENDLOCAL
|
|
Before Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 121 KiB |
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 836 B |
Before Width: | Height: | Size: 1017 B |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 302 B |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 1.6 KiB |
|
@ -30,8 +30,6 @@
|
||||||
#include "RecentIsoList.h"
|
#include "RecentIsoList.h"
|
||||||
#include "DriveList.h"
|
#include "DriveList.h"
|
||||||
|
|
||||||
#include "Recording/NewRecordingFrame.h"
|
|
||||||
|
|
||||||
class DisassemblyDialog;
|
class DisassemblyDialog;
|
||||||
struct HostKeyEvent;
|
struct HostKeyEvent;
|
||||||
|
|
||||||
|
@ -482,13 +480,6 @@ public:
|
||||||
MainEmuFrame* GetMainFramePtr() const { return (MainEmuFrame*)wxWindow::FindWindowById(m_id_MainFrame); }
|
MainEmuFrame* GetMainFramePtr() const { return (MainEmuFrame*)wxWindow::FindWindowById(m_id_MainFrame); }
|
||||||
DisassemblyDialog* GetDisassemblyPtr() const { return (DisassemblyDialog*)wxWindow::FindWindowById(m_id_Disassembler); }
|
DisassemblyDialog* GetDisassemblyPtr() const { return (DisassemblyDialog*)wxWindow::FindWindowById(m_id_Disassembler); }
|
||||||
|
|
||||||
#ifndef PCSX2_CORE
|
|
||||||
NewRecordingFrame* GetNewRecordingFramePtr() const
|
|
||||||
{
|
|
||||||
return (NewRecordingFrame*)wxWindow::FindWindowById(m_id_NewRecordingFrame);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void enterDebugMode();
|
void enterDebugMode();
|
||||||
void leaveDebugMode();
|
void leaveDebugMode();
|
||||||
void resetDebugger();
|
void resetDebugger();
|
||||||
|
|
|
@ -234,13 +234,9 @@ void Pcsx2App::SysApplySettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppCoreThread::OnResumeReady()
|
void AppCoreThread::OnResumeReady()
|
||||||
{
|
|
||||||
if (!g_InputRecordingControls.IsFrameAdvancing())
|
|
||||||
{
|
{
|
||||||
wxGetApp().SysApplySettings();
|
wxGetApp().SysApplySettings();
|
||||||
wxGetApp().PostMethod(AppSaveSettings);
|
wxGetApp().PostMethod(AppSaveSettings);
|
||||||
}
|
|
||||||
|
|
||||||
sApp.PostAppMethod(&Pcsx2App::leaveDebugMode);
|
sApp.PostAppMethod(&Pcsx2App::leaveDebugMode);
|
||||||
_parent::OnResumeReady();
|
_parent::OnResumeReady();
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,11 +104,6 @@ void Pcsx2App::OpenMainFrame()
|
||||||
DisassemblyDialog* disassembly = new DisassemblyDialog(mainFrame);
|
DisassemblyDialog* disassembly = new DisassemblyDialog(mainFrame);
|
||||||
m_id_Disassembler = disassembly->GetId();
|
m_id_Disassembler = disassembly->GetId();
|
||||||
|
|
||||||
NewRecordingFrame* newRecordingFrame = new NewRecordingFrame(mainFrame);
|
|
||||||
m_id_NewRecordingFrame = newRecordingFrame->GetId();
|
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
|
||||||
g_InputRecording.InitVirtualPadWindows(mainFrame);
|
|
||||||
|
|
||||||
if (g_Conf->EmuOptions.Debugger.ShowDebuggerOnStart)
|
if (g_Conf->EmuOptions.Debugger.ShowDebuggerOnStart)
|
||||||
disassembly->Show();
|
disassembly->Show();
|
||||||
|
|
||||||
|
|
|
@ -450,23 +450,6 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
|
||||||
{
|
|
||||||
if (g_InputRecordingControls.IsPaused())
|
|
||||||
{
|
|
||||||
// When the GSFrame CoreThread is paused, so is the logical VSync
|
|
||||||
// Meaning that we have to grab the user-input through here to potentially
|
|
||||||
// resume emulation.
|
|
||||||
if (const HostKeyEvent* ev = PADkeyEvent() )
|
|
||||||
{
|
|
||||||
if( ev->key != 0 )
|
|
||||||
{
|
|
||||||
PadKeyDispatch( *ev );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_InputRecordingControls.ResumeCoreThreadIfStarted();
|
|
||||||
}
|
|
||||||
(handler->*func)(event);
|
(handler->*func)(event);
|
||||||
}
|
}
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -481,9 +464,6 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
|
||||||
// Saved state load failed prior to the system getting corrupted (ie, file not found
|
// Saved state load failed prior to the system getting corrupted (ie, file not found
|
||||||
// or some zipfile error) -- so log it and resume emulation.
|
// or some zipfile error) -- so log it and resume emulation.
|
||||||
Console.Warning( ex.FormatDiagnosticMessage() );
|
Console.Warning( ex.FormatDiagnosticMessage() );
|
||||||
if (g_InputRecording.IsInitialLoad())
|
|
||||||
g_InputRecording.FailedSavestate();
|
|
||||||
|
|
||||||
CoreThread.Resume();
|
CoreThread.Resume();
|
||||||
}
|
}
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -768,15 +748,6 @@ void Pcsx2App::OpenGsPanel()
|
||||||
std::optional<WindowInfo> wi = gsFrame->GetViewport()->GetWindowInfo();
|
std::optional<WindowInfo> wi = gsFrame->GetViewport()->GetWindowInfo();
|
||||||
pxAssertDev(wi.has_value(), "GS frame has a valid native window");
|
pxAssertDev(wi.has_value(), "GS frame has a valid native window");
|
||||||
g_gs_window_info = std::move(*wi);
|
g_gs_window_info = std::move(*wi);
|
||||||
|
|
||||||
// Enable New & Play after the first game load of the session
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_New, !g_InputRecording.IsActive());
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_Play, true);
|
|
||||||
|
|
||||||
// Enable recording menu options as the game is now running
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_FrameAdvance, true);
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_TogglePause, true);
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_ToggleRecordingMode, g_InputRecording.IsActive());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -816,11 +787,6 @@ void Pcsx2App::OnGsFrameDestroyed(wxWindowID id)
|
||||||
|
|
||||||
m_id_GsFrame = wxID_ANY;
|
m_id_GsFrame = wxID_ANY;
|
||||||
g_gs_window_info = {};
|
g_gs_window_info = {};
|
||||||
|
|
||||||
// Disable recording controls that only make sense if the game is running
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_FrameAdvance, false);
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_TogglePause, false);
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_ToggleRecordingMode, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pcsx2App::OnProgramLogClosed( wxWindowID id )
|
void Pcsx2App::OnProgramLogClosed( wxWindowID id )
|
||||||
|
@ -834,11 +800,6 @@ void Pcsx2App::OnProgramLogClosed( wxWindowID id )
|
||||||
|
|
||||||
void Pcsx2App::OnMainFrameClosed( wxWindowID id )
|
void Pcsx2App::OnMainFrameClosed( wxWindowID id )
|
||||||
{
|
{
|
||||||
if (g_InputRecording.IsActive())
|
|
||||||
{
|
|
||||||
g_InputRecording.Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing threaded depends on the mainframe (yet) -- it all passes through the main wxApp
|
// Nothing threaded depends on the mainframe (yet) -- it all passes through the main wxApp
|
||||||
// message handler. But that might change in the future.
|
// message handler. But that might change in the future.
|
||||||
if( m_id_MainFrame != id ) return;
|
if( m_id_MainFrame != id ) return;
|
||||||
|
@ -933,10 +894,6 @@ void Pcsx2App::SysExecute( CDVD_SourceType cdvdsrc, const wxString& elf_override
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SysExecutorThread.PostEvent( new SysExecEvent_Execute(cdvdsrc, elf_override) );
|
SysExecutorThread.PostEvent( new SysExecEvent_Execute(cdvdsrc, elf_override) );
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
|
||||||
{
|
|
||||||
g_InputRecording.RecordingReset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if there is a "valid" virtual machine state from the user's perspective. This
|
// Returns true if there is a "valid" virtual machine state from the user's perspective. This
|
||||||
|
|
|
@ -107,76 +107,11 @@ void GSPanel::InitDefaultAccelerators()
|
||||||
m_Accels->Map( FULLSCREEN_TOGGLE_ACCELERATOR_GSPANEL, "FullscreenToggle" );
|
m_Accels->Map( FULLSCREEN_TOGGLE_ACCELERATOR_GSPANEL, "FullscreenToggle" );
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSPanel::InitRecordingAccelerators()
|
|
||||||
{
|
|
||||||
// Note: these override GlobalAccels ( Pcsx2App::InitDefaultGlobalAccelerators() )
|
|
||||||
// For plain letters or symbols, replace e.g. WXK_F1 with e.g. wxKeyCode('q') or wxKeyCode('-')
|
|
||||||
// For plain letter keys with shift, use e.g. AAC( wxKeyCode('q') ).Shift() and NOT wxKeyCode('Q')
|
|
||||||
// For a symbol with shift (e.g. '_' which is '-' with shift) use AAC( wxKeyCode('-') ).Shift()
|
|
||||||
|
|
||||||
typedef KeyAcceleratorCode AAC;
|
|
||||||
|
|
||||||
if (!m_Accels) m_Accels = std::unique_ptr<AcceleratorDictionary>(new AcceleratorDictionary);
|
|
||||||
|
|
||||||
m_Accels->Map(AAC(WXK_SPACE), "FrameAdvance");
|
|
||||||
m_Accels->Map(AAC(wxKeyCode('p')).Shift(), "TogglePause");
|
|
||||||
m_Accels->Map(AAC(wxKeyCode('r')).Shift(), "InputRecordingModeToggle");
|
|
||||||
m_Accels->Map(AAC(wxKeyCode('l')).Shift(), "GoToFirstFrame");
|
|
||||||
#if defined(__unix__)
|
|
||||||
// Shift+P (80) and Shift+p (112) have two completely different codes
|
|
||||||
// On Linux the former is sometimes fired so define bindings for both
|
|
||||||
m_Accels->Map(AAC(wxKeyCode('P')).Shift(), "TogglePause");
|
|
||||||
m_Accels->Map(AAC(wxKeyCode('R')).Shift(), "InputRecordingModeToggle");
|
|
||||||
m_Accels->Map(AAC(wxKeyCode('L')).Shift(), "GoToFirstFrame");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD0).Shift(), "States_SaveSlot0");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD1).Shift(), "States_SaveSlot1");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD2).Shift(), "States_SaveSlot2");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD3).Shift(), "States_SaveSlot3");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD4).Shift(), "States_SaveSlot4");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD5).Shift(), "States_SaveSlot5");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD6).Shift(), "States_SaveSlot6");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD7).Shift(), "States_SaveSlot7");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD8).Shift(), "States_SaveSlot8");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD9).Shift(), "States_SaveSlot9");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD0), "States_LoadSlot0");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD1), "States_LoadSlot1");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD2), "States_LoadSlot2");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD3), "States_LoadSlot3");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD4), "States_LoadSlot4");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD5), "States_LoadSlot5");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD6), "States_LoadSlot6");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD7), "States_LoadSlot7");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD8), "States_LoadSlot8");
|
|
||||||
m_Accels->Map(AAC(WXK_NUMPAD9), "States_LoadSlot9");
|
|
||||||
|
|
||||||
GetMainFramePtr()->initializeRecordingMenuItem(
|
|
||||||
MenuId_Recording_FrameAdvance,
|
|
||||||
GetAssociatedKeyCode("FrameAdvance"));
|
|
||||||
GetMainFramePtr()->initializeRecordingMenuItem(
|
|
||||||
MenuId_Recording_TogglePause,
|
|
||||||
GetAssociatedKeyCode("TogglePause"));
|
|
||||||
GetMainFramePtr()->initializeRecordingMenuItem(
|
|
||||||
MenuId_Recording_ToggleRecordingMode,
|
|
||||||
GetAssociatedKeyCode("InputRecordingModeToggle"),
|
|
||||||
g_InputRecording.IsActive());
|
|
||||||
|
|
||||||
InputRec::consoleLog("Initialized Input Recording Key Bindings");
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString GSPanel::GetAssociatedKeyCode(const char* id)
|
wxString GSPanel::GetAssociatedKeyCode(const char* id)
|
||||||
{
|
{
|
||||||
return m_Accels->findKeycodeWithCommandId(id).toTitleizedString();
|
return m_Accels->findKeycodeWithCommandId(id).toTitleizedString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSPanel::RemoveRecordingAccelerators()
|
|
||||||
{
|
|
||||||
m_Accels.reset(new AcceleratorDictionary);
|
|
||||||
InitDefaultAccelerators();
|
|
||||||
recordingConLog("Disabled Input Recording Key Bindings\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
GSPanel::GSPanel( wxWindow* parent )
|
GSPanel::GSPanel( wxWindow* parent )
|
||||||
: wxWindow()
|
: wxWindow()
|
||||||
, m_HideMouseTimer( this )
|
, m_HideMouseTimer( this )
|
||||||
|
@ -192,11 +127,6 @@ GSPanel::GSPanel( wxWindow* parent )
|
||||||
|
|
||||||
InitDefaultAccelerators();
|
InitDefaultAccelerators();
|
||||||
|
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
|
||||||
{
|
|
||||||
InitRecordingAccelerators();
|
|
||||||
}
|
|
||||||
|
|
||||||
SetBackgroundColour(wxColour((unsigned long)0));
|
SetBackgroundColour(wxColour((unsigned long)0));
|
||||||
if( g_Conf->GSWindow.AlwaysHideMouse )
|
if( g_Conf->GSWindow.AlwaysHideMouse )
|
||||||
{
|
{
|
||||||
|
@ -899,17 +829,7 @@ void GSFrame::OnUpdateTitle( wxTimerEvent& evt )
|
||||||
const u64& smode2 = *(u64*)PS2GS_BASE(GS_SMODE2);
|
const u64& smode2 = *(u64*)PS2GS_BASE(GS_SMODE2);
|
||||||
wxString omodef = (smode2 & 2) ? templates.OutputFrame : templates.OutputField;
|
wxString omodef = (smode2 & 2) ? templates.OutputFrame : templates.OutputField;
|
||||||
wxString omodei = (smode2 & 1) ? templates.OutputInterlaced : templates.OutputProgressive;
|
wxString omodei = (smode2 & 1) ? templates.OutputInterlaced : templates.OutputProgressive;
|
||||||
wxString title;
|
wxString title = templates.TitleTemplate;
|
||||||
wxString movieMode;
|
|
||||||
if (g_InputRecording.IsActive())
|
|
||||||
{
|
|
||||||
title = templates.RecordingTemplate;
|
|
||||||
title.Replace(L"${frame}", pxsFmt(L"%d", g_InputRecording.GetFrameCounter()));
|
|
||||||
title.Replace(L"${maxFrame}", pxsFmt(L"%d", g_InputRecording.GetInputRecordingData().GetTotalFrames()));
|
|
||||||
title.Replace(L"${mode}", g_InputRecording.RecordingModeTitleSegment());
|
|
||||||
} else {
|
|
||||||
title = templates.TitleTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string gsStats;
|
std::string gsStats;
|
||||||
GSgetTitleStats(gsStats);
|
GSgetTitleStats(gsStats);
|
||||||
|
|
|
@ -53,8 +53,6 @@ public:
|
||||||
void DirectKeyCommand( const KeyAcceleratorCode& kac );
|
void DirectKeyCommand( const KeyAcceleratorCode& kac );
|
||||||
void InitDefaultAccelerators();
|
void InitDefaultAccelerators();
|
||||||
wxString GetAssociatedKeyCode(const char* id);
|
wxString GetAssociatedKeyCode(const char* id);
|
||||||
void InitRecordingAccelerators();
|
|
||||||
void RemoveRecordingAccelerators();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void AppStatusEvent_OnSettingsApplied();
|
void AppStatusEvent_OnSettingsApplied();
|
||||||
|
|
|
@ -305,10 +305,6 @@ namespace Implementations
|
||||||
if (g_Conf->GSWindow.CloseOnEsc)
|
if (g_Conf->GSWindow.CloseOnEsc)
|
||||||
{
|
{
|
||||||
sMainFrame.SetFocus();
|
sMainFrame.SetFocus();
|
||||||
// Disable recording controls that only make sense if the game is running
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_FrameAdvance, false);
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_TogglePause, false);
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_ToggleRecordingMode, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,38 +416,6 @@ namespace Implementations
|
||||||
if (GSFrame* gsframe = wxGetApp().GetGsFramePtr())
|
if (GSFrame* gsframe = wxGetApp().GetGsFramePtr())
|
||||||
gsframe->ShowFullScreen(!gsframe->IsFullScreen());
|
gsframe->ShowFullScreen(!gsframe->IsFullScreen());
|
||||||
}
|
}
|
||||||
void FrameAdvance()
|
|
||||||
{
|
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
|
||||||
{
|
|
||||||
g_InputRecordingControls.FrameAdvance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TogglePause()
|
|
||||||
{
|
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
|
||||||
{
|
|
||||||
g_InputRecordingControls.TogglePause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRecordingModeToggle()
|
|
||||||
{
|
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
|
||||||
{
|
|
||||||
g_InputRecordingControls.RecordModeToggle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GoToFirstFrame()
|
|
||||||
{
|
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools && g_InputRecording.IsActive())
|
|
||||||
{
|
|
||||||
// Assumes that gui is active, as you can't access recording options without it
|
|
||||||
g_InputRecording.GoToFirstFrame(GetMainFramePtr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void States_SaveSlot(int slot)
|
void States_SaveSlot(int slot)
|
||||||
{
|
{
|
||||||
|
@ -730,11 +694,6 @@ static const GlobalCommandDescriptor CommandDeclarations[] =
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
|
||||||
{"FrameAdvance", Implementations::FrameAdvance, NULL, NULL, false},
|
|
||||||
{"TogglePause", Implementations::TogglePause, NULL, NULL, false},
|
|
||||||
{"InputRecordingModeToggle", Implementations::InputRecordingModeToggle, NULL, NULL, false},
|
|
||||||
{"GoToFirstFrame", Implementations::GoToFirstFrame, NULL, NULL, false},
|
|
||||||
|
|
||||||
{"States_SaveSlot0", Implementations::States_SaveSlot0, NULL, NULL, false},
|
{"States_SaveSlot0", Implementations::States_SaveSlot0, NULL, NULL, false},
|
||||||
{"States_SaveSlot1", Implementations::States_SaveSlot1, NULL, NULL, false},
|
{"States_SaveSlot1", Implementations::States_SaveSlot1, NULL, NULL, false},
|
||||||
{"States_SaveSlot2", Implementations::States_SaveSlot2, NULL, NULL, false},
|
{"States_SaveSlot2", Implementations::States_SaveSlot2, NULL, NULL, false},
|
||||||
|
|
|
@ -69,16 +69,11 @@ void MainEmuFrame::UpdateStatusBar()
|
||||||
{
|
{
|
||||||
wxString temp(wxEmptyString);
|
wxString temp(wxEmptyString);
|
||||||
|
|
||||||
if (g_InputRecording.IsActive() && g_InputRecording.GetInputRecordingData().FromSaveState())
|
|
||||||
temp += "Base Savestate - " + g_InputRecording.GetInputRecordingData().GetFilename() + "_SaveState.p2s";
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (g_Conf->EnableFastBoot)
|
if (g_Conf->EnableFastBoot)
|
||||||
temp += "Fast Boot - ";
|
temp += "Fast Boot - ";
|
||||||
|
|
||||||
if (g_Conf->CdvdSource == CDVD_SourceType::Iso)
|
if (g_Conf->CdvdSource == CDVD_SourceType::Iso)
|
||||||
temp += "Load: '" + wxFileName(g_Conf->CurrentIso).GetFullName() + "' ";
|
temp += "Load: '" + wxFileName(g_Conf->CurrentIso).GetFullName() + "' ";
|
||||||
}
|
|
||||||
|
|
||||||
m_statusbar.SetStatusText(temp, 0);
|
m_statusbar.SetStatusText(temp, 0);
|
||||||
|
|
||||||
|
@ -111,10 +106,7 @@ void MainEmuFrame::UpdateCdvdSrcSelection()
|
||||||
jNO_DEFAULT
|
jNO_DEFAULT
|
||||||
}
|
}
|
||||||
sMenuBar.Check(cdsrc, true);
|
sMenuBar.Check(cdsrc, true);
|
||||||
if (!g_InputRecording.IsActive())
|
|
||||||
{
|
|
||||||
ApplyCDVDStatus();
|
ApplyCDVDStatus();
|
||||||
}
|
|
||||||
UpdateStatusBar();
|
UpdateStatusBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,17 +303,6 @@ void MainEmuFrame::ConnectMenus()
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Capture_Video_IncludeAudio_Click, this, MenuId_Capture_Video_IncludeAudio);
|
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Capture_Video_IncludeAudio_Click, this, MenuId_Capture_Video_IncludeAudio);
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Capture_Screenshot_Screenshot_Click, this, MenuId_Capture_Screenshot_Screenshot);
|
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Capture_Screenshot_Screenshot_Click, this, MenuId_Capture_Screenshot_Screenshot);
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Capture_Screenshot_Screenshot_As_Click, this, MenuId_Capture_Screenshot_Screenshot_As);
|
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Capture_Screenshot_Screenshot_As_Click, this, MenuId_Capture_Screenshot_Screenshot_As);
|
||||||
|
|
||||||
// Recording
|
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Recording_New_Click, this, MenuId_Recording_New);
|
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Recording_Play_Click, this, MenuId_Recording_Play);
|
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Recording_Stop_Click, this, MenuId_Recording_Stop);
|
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Recording_Config_FrameAdvance, this, MenuId_Recording_Config_FrameAdvance);
|
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Recording_TogglePause_Click, this, MenuId_Recording_TogglePause);
|
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Recording_FrameAdvance_Click, this, MenuId_Recording_FrameAdvance);
|
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Recording_ToggleRecordingMode_Click, this, MenuId_Recording_ToggleRecordingMode);
|
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Recording_VirtualPad_Open_Click, this, MenuId_Recording_VirtualPad_Port0);
|
|
||||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_Recording_VirtualPad_Open_Click, this, MenuId_Recording_VirtualPad_Port1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainEmuFrame::InitLogBoxPosition(AppConfig::ConsoleLogOptions& conf)
|
void MainEmuFrame::InitLogBoxPosition(AppConfig::ConsoleLogOptions& conf)
|
||||||
|
@ -393,7 +374,7 @@ void MainEmuFrame::CreatePcsx2Menu()
|
||||||
_("Enabling Widescreen Patches may occasionally cause issues."), wxITEM_CHECK);
|
_("Enabling Widescreen Patches may occasionally cause issues."), wxITEM_CHECK);
|
||||||
|
|
||||||
m_GameSettingsSubmenu.Append(MenuId_EnableInputRecording, _("Enable &Input Recording"),
|
m_GameSettingsSubmenu.Append(MenuId_EnableInputRecording, _("Enable &Input Recording"),
|
||||||
_("Input Recording for controller/keyboard presses, tools for automation and playback."), wxITEM_CHECK);
|
_("Input Recording for controller/keyboard presses, tools for automation and playback."), wxITEM_NORMAL);
|
||||||
|
|
||||||
m_GameSettingsSubmenu.Append(MenuId_EnableHostFs, _("Enable &Host Filesystem"),
|
m_GameSettingsSubmenu.Append(MenuId_EnableHostFs, _("Enable &Host Filesystem"),
|
||||||
wxEmptyString, wxITEM_CHECK);
|
wxEmptyString, wxITEM_CHECK);
|
||||||
|
@ -583,11 +564,6 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
|
||||||
|
|
||||||
SetMenuBar(&m_menubar);
|
SetMenuBar(&m_menubar);
|
||||||
|
|
||||||
// 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, _("&Input Record"));
|
|
||||||
}
|
|
||||||
m_menubar.Append(&m_menuHelp, _("&Help"));
|
m_menubar.Append(&m_menuHelp, _("&Help"));
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -813,12 +789,6 @@ void MainEmuFrame::ApplyConfigToGui(AppConfig& configToApply, int flags)
|
||||||
menubar.Check(MenuId_EnableWideScreenPatches, configToApply.EmuOptions.EnableWideScreenPatches);
|
menubar.Check(MenuId_EnableWideScreenPatches, configToApply.EmuOptions.EnableWideScreenPatches);
|
||||||
menubar.Check(MenuId_Capture_Video_IncludeAudio, configToApply.AudioCapture.EnableAudio);
|
menubar.Check(MenuId_Capture_Video_IncludeAudio, configToApply.AudioCapture.EnableAudio);
|
||||||
|
|
||||||
menubar.Check(MenuId_EnableInputRecording, configToApply.EmuOptions.EnableRecordingTools);
|
|
||||||
wxString frame_advance_label = wxString(_("Configure Frame Advance"));
|
|
||||||
frame_advance_label.Append(wxString::Format(" (%d)", configToApply.inputRecording.m_frame_advance_amount));
|
|
||||||
m_submenu_recording_settings.SetLabel(MenuId_Recording_Config_FrameAdvance, frame_advance_label);
|
|
||||||
g_InputRecordingControls.setFrameAdvanceAmount(configToApply.inputRecording.m_frame_advance_amount);
|
|
||||||
|
|
||||||
menubar.Check(MenuId_EnableHostFs, configToApply.EmuOptions.HostFs);
|
menubar.Check(MenuId_EnableHostFs, configToApply.EmuOptions.HostFs);
|
||||||
menubar.Check(MenuId_Debug_CreateBlockdump, configToApply.EmuOptions.CdvdDumpBlocks);
|
menubar.Check(MenuId_Debug_CreateBlockdump, configToApply.EmuOptions.CdvdDumpBlocks);
|
||||||
#if defined(__POSIX__)
|
#if defined(__POSIX__)
|
||||||
|
@ -847,18 +817,3 @@ void MainEmuFrame::AppendShortcutToMenuOption(wxMenuItem& item, wxString keyCode
|
||||||
const size_t tabPos = text.rfind(L'\t');
|
const size_t tabPos = text.rfind(L'\t');
|
||||||
item.SetItemLabel(text.Mid(0, tabPos) + L"\t" + keyCodeStr);
|
item.SetItemLabel(text.Mid(0, tabPos) + L"\t" + keyCodeStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainEmuFrame::initializeRecordingMenuItem(MenuIdentifiers menuId, wxString keyCodeStr, bool enable)
|
|
||||||
{
|
|
||||||
wxMenuItem& item = *m_menuRecording.FindChildItem(menuId);
|
|
||||||
wxString text = item.GetItemLabel();
|
|
||||||
const size_t tabPos = text.rfind(L'\t');
|
|
||||||
item.SetItemLabel(text.Mid(0, tabPos) + L"\t" + keyCodeStr);
|
|
||||||
item.Enable(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::enableRecordingMenuItem(MenuIdentifiers menuId, bool enable)
|
|
||||||
{
|
|
||||||
wxMenuItem& item = *m_menuRecording.FindChildItem(menuId);
|
|
||||||
item.Enable(enable);
|
|
||||||
}
|
|
||||||
|
|
|
@ -122,11 +122,6 @@ public:
|
||||||
void VideoCaptureToggle();
|
void VideoCaptureToggle();
|
||||||
bool IsCapturing() const noexcept { return m_capturingVideo; }
|
bool IsCapturing() const noexcept { return m_capturingVideo; }
|
||||||
|
|
||||||
void initializeRecordingMenuItem(MenuIdentifiers menuId, wxString keyCodeStr, bool enable = true);
|
|
||||||
void enableRecordingMenuItem(MenuIdentifiers menuId, bool enable);
|
|
||||||
void StartInputRecording();
|
|
||||||
void StopInputRecording();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void DoGiveHelp(const wxString& text, bool show);
|
void DoGiveHelp(const wxString& text, bool show);
|
||||||
|
|
||||||
|
@ -205,16 +200,6 @@ protected:
|
||||||
void Menu_Capture_Screenshot_Screenshot_Click(wxCommandEvent& event);
|
void Menu_Capture_Screenshot_Screenshot_Click(wxCommandEvent& event);
|
||||||
void Menu_Capture_Screenshot_Screenshot_As_Click(wxCommandEvent& event);
|
void Menu_Capture_Screenshot_Screenshot_As_Click(wxCommandEvent& event);
|
||||||
|
|
||||||
void Menu_Recording_New_Click(wxCommandEvent& event);
|
|
||||||
void Menu_Recording_Play_Click(wxCommandEvent& event);
|
|
||||||
void Menu_Recording_Stop_Click(wxCommandEvent& event);
|
|
||||||
void Menu_Recording_Config_FrameAdvance(wxCommandEvent& event);
|
|
||||||
void ApplyFirstFrameStatus();
|
|
||||||
void Menu_Recording_TogglePause_Click(wxCommandEvent& event);
|
|
||||||
void Menu_Recording_FrameAdvance_Click(wxCommandEvent& event);
|
|
||||||
void Menu_Recording_ToggleRecordingMode_Click(wxCommandEvent& event);
|
|
||||||
void Menu_Recording_VirtualPad_Open_Click(wxCommandEvent& event);
|
|
||||||
|
|
||||||
void _DoBootCdvd();
|
void _DoBootCdvd();
|
||||||
bool _DoSelectIsoBrowser(wxString& dest);
|
bool _DoSelectIsoBrowser(wxString& dest);
|
||||||
bool _DoSelectELFBrowser();
|
bool _DoSelectELFBrowser();
|
||||||
|
|
|
@ -38,10 +38,6 @@
|
||||||
#include "fmt/core.h"
|
#include "fmt/core.h"
|
||||||
#include "wx/numdlg.h"
|
#include "wx/numdlg.h"
|
||||||
|
|
||||||
#include "Recording/InputRecording.h"
|
|
||||||
#include "Recording/InputRecordingControls.h"
|
|
||||||
#include "Recording/VirtualPad/VirtualPad.h"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace Dialogs;
|
using namespace Dialogs;
|
||||||
|
|
||||||
|
@ -205,9 +201,6 @@ wxWindowID SwapOrReset_Iso(wxWindow* owner, IScopedCoreThread& core_control, con
|
||||||
dialog += dialog.GetCharHeight();
|
dialog += dialog.GetCharHeight();
|
||||||
dialog += dialog.Heading(_("Do you want to swap discs or boot the new image (via system reset)?"));
|
dialog += dialog.Heading(_("Do you want to swap discs or boot the new image (via system reset)?"));
|
||||||
|
|
||||||
if (g_InputRecording.IsActive() && g_InputRecording.GetInputRecordingData().FromSaveState())
|
|
||||||
dialog += dialog.Text(_("\n(Warning: The savestate accompanying the active input recording\nmay not be compatible with the new source)"));
|
|
||||||
|
|
||||||
result = pxIssueConfirmation(dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap"));
|
result = pxIssueConfirmation(dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap"));
|
||||||
if (result == wxID_CANCEL)
|
if (result == wxID_CANCEL)
|
||||||
{
|
{
|
||||||
|
@ -264,9 +257,6 @@ wxWindowID SwapOrReset_Disc(wxWindow* owner, IScopedCoreThread& core, const wxSt
|
||||||
dialog += dialog.GetCharHeight();
|
dialog += dialog.GetCharHeight();
|
||||||
dialog += dialog.Heading(_("Do you want to swap discs or boot the new disc (via system reset)?"));
|
dialog += dialog.Heading(_("Do you want to swap discs or boot the new disc (via system reset)?"));
|
||||||
|
|
||||||
if (g_InputRecording.IsActive() && g_InputRecording.GetInputRecordingData().FromSaveState())
|
|
||||||
dialog += dialog.Text(_("\n(Warning: The savestate accompanying the active input recording\nmay not be compatible with the new source)"));
|
|
||||||
|
|
||||||
result = pxIssueConfirmation(dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap"));
|
result = pxIssueConfirmation(dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap"));
|
||||||
if (result == wxID_CANCEL)
|
if (result == wxID_CANCEL)
|
||||||
{
|
{
|
||||||
|
@ -314,9 +304,6 @@ wxWindowID SwapOrReset_CdvdSrc(wxWindow* owner, CDVD_SourceType newsrc)
|
||||||
dialog += dialog.Heading(changeMsg + L"\n\n" +
|
dialog += dialog.Heading(changeMsg + L"\n\n" +
|
||||||
_("Do you want to swap discs or boot the new image (system reset)?"));
|
_("Do you want to swap discs or boot the new image (system reset)?"));
|
||||||
|
|
||||||
if (g_InputRecording.IsActive() && g_InputRecording.GetInputRecordingData().FromSaveState())
|
|
||||||
dialog += dialog.Text(_("\n(Warning: The savestate accompanying the active input recording\nmay not be compatible with the new source)"));
|
|
||||||
|
|
||||||
result = pxIssueConfirmation(dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap"));
|
result = pxIssueConfirmation(dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap"));
|
||||||
|
|
||||||
if (result == wxID_CANCEL)
|
if (result == wxID_CANCEL)
|
||||||
|
@ -506,24 +493,14 @@ void MainEmuFrame::Menu_CdvdSource_Click(wxCommandEvent& event)
|
||||||
}
|
}
|
||||||
|
|
||||||
SwapOrReset_CdvdSrc(this, newsrc);
|
SwapOrReset_CdvdSrc(this, newsrc);
|
||||||
if (!g_InputRecording.IsActive())
|
|
||||||
{
|
|
||||||
ApplyCDVDStatus();
|
ApplyCDVDStatus();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::Menu_BootCdvd_Click(wxCommandEvent& event)
|
void MainEmuFrame::Menu_BootCdvd_Click(wxCommandEvent& event)
|
||||||
{
|
|
||||||
if (g_InputRecording.IsActive())
|
|
||||||
{
|
|
||||||
g_InputRecording.GoToFirstFrame(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
g_Conf->EmuOptions.UseBOOT2Injection = g_Conf->EnableFastBoot;
|
g_Conf->EmuOptions.UseBOOT2Injection = g_Conf->EnableFastBoot;
|
||||||
_DoBootCdvd();
|
_DoBootCdvd();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::Menu_FastBoot_Click(wxCommandEvent& event)
|
void MainEmuFrame::Menu_FastBoot_Click(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
|
@ -681,66 +658,8 @@ void MainEmuFrame::Menu_EnableWideScreenPatches_Click(wxCommandEvent&)
|
||||||
|
|
||||||
void MainEmuFrame::Menu_EnableRecordingTools_Click(wxCommandEvent& event)
|
void MainEmuFrame::Menu_EnableRecordingTools_Click(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
bool checked = GetMenuBar()->IsChecked(MenuId_EnableInputRecording);
|
Msgbox::Alert("Input Recording has been deprecated from the wxWidgets version.\nUse an older dev build (before v1.7.3650) or switch to the Qt version!\nOld recordings should still play correctly!");
|
||||||
// Confirm with User
|
return;
|
||||||
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 Input Recording"))
|
|
||||||
{
|
|
||||||
checked = false;
|
|
||||||
m_GameSettingsSubmenu.FindChildItem(MenuId_EnableInputRecording)->Check(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If still enabled, add the menu item, else, remove it
|
|
||||||
if (checked)
|
|
||||||
{
|
|
||||||
GetMenuBar()->Insert(TopLevelMenu_InputRecording, &m_menuRecording, _("&Input Record"));
|
|
||||||
g_InputRecording.InitVirtualPadWindows(this);
|
|
||||||
SysConsole.recordingConsole.Enabled = true;
|
|
||||||
// Enable Recording Keybindings
|
|
||||||
if (GSFrame* gsFrame = wxGetApp().GetGsFramePtr())
|
|
||||||
{
|
|
||||||
if (GSPanel* viewport = gsFrame->GetViewport())
|
|
||||||
{
|
|
||||||
viewport->InitRecordingAccelerators();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Properly close any currently loaded recording file before disabling
|
|
||||||
StopInputRecording();
|
|
||||||
GetMenuBar()->Remove(TopLevelMenu_InputRecording);
|
|
||||||
// Always turn controller logs off, but never turn it on by default
|
|
||||||
SysConsole.controlInfo.Enabled = checked;
|
|
||||||
// Return Keybindings Back to Normal
|
|
||||||
if (GSFrame* gsFrame = wxGetApp().GetGsFramePtr())
|
|
||||||
{
|
|
||||||
if (GSPanel* viewport = gsFrame->GetViewport())
|
|
||||||
{
|
|
||||||
viewport->RemoveRecordingAccelerators();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SysConsole.recordingConsole.Enabled = false;
|
|
||||||
if (g_InputRecordingControls.IsPaused())
|
|
||||||
g_InputRecordingControls.Resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
g_Conf->EmuOptions.EnableRecordingTools = checked;
|
|
||||||
// Update GS Title Frequency
|
|
||||||
if (GSFrame* gsFrame = wxGetApp().GetGsFramePtr())
|
|
||||||
{
|
|
||||||
gsFrame->UpdateTitleUpdateFreq();
|
|
||||||
}
|
|
||||||
// Enable Recording Logs
|
|
||||||
ConsoleLogFrame* progLog = wxGetApp().GetProgramLog();
|
|
||||||
progLog->UpdateLogList();
|
|
||||||
AppApplySettings();
|
|
||||||
AppSaveSettings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainEmuFrame::Menu_EnableHostFs_Click(wxCommandEvent&)
|
void MainEmuFrame::Menu_EnableHostFs_Click(wxCommandEvent&)
|
||||||
|
@ -825,10 +744,6 @@ protected:
|
||||||
if (CoreThread.IsOpen())
|
if (CoreThread.IsOpen())
|
||||||
{
|
{
|
||||||
CoreThread.Suspend();
|
CoreThread.Suspend();
|
||||||
// Disable recording controls that only make sense if the game is running
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_FrameAdvance, false);
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_TogglePause, false);
|
|
||||||
sMainFrame.enableRecordingMenuItem(MenuId_Recording_ToggleRecordingMode, false);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CoreThread.Resume();
|
CoreThread.Resume();
|
||||||
|
@ -848,34 +763,6 @@ void MainEmuFrame::Menu_SuspendResume_Click(wxCommandEvent& event)
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainEmuFrame::Menu_SysShutdown_Click(wxCommandEvent& event)
|
void MainEmuFrame::Menu_SysShutdown_Click(wxCommandEvent& event)
|
||||||
{
|
|
||||||
bool doShutdown = true;
|
|
||||||
if (!g_InputRecording.IsActive())
|
|
||||||
{
|
|
||||||
if (g_InputRecordingControls.IsPaused())
|
|
||||||
g_InputRecordingControls.Resume();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const bool initiallyPaused = g_InputRecordingControls.IsPaused();
|
|
||||||
if (!initiallyPaused)
|
|
||||||
g_InputRecordingControls.Pause();
|
|
||||||
wxWindowID result = wxID_CANCEL;
|
|
||||||
wxDialogWithHelpers dialog(this, _("Shutdown & Close Input Recording"));
|
|
||||||
dialog += dialog.Heading(L"\nShutting down emulation will close the active input recording file.\nProceed?");
|
|
||||||
result = pxIssueConfirmation(dialog, MsgButtons().Close().Cancel());
|
|
||||||
if (result == wxID_CLOSE)
|
|
||||||
{
|
|
||||||
StopInputRecording();
|
|
||||||
g_InputRecordingControls.Resume();
|
|
||||||
}
|
|
||||||
else if (!initiallyPaused)
|
|
||||||
{
|
|
||||||
g_InputRecordingControls.Resume();
|
|
||||||
doShutdown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (doShutdown)
|
|
||||||
{
|
{
|
||||||
if (m_capturingVideo)
|
if (m_capturingVideo)
|
||||||
VideoCaptureToggle();
|
VideoCaptureToggle();
|
||||||
|
@ -883,7 +770,6 @@ void MainEmuFrame::Menu_SysShutdown_Click(wxCommandEvent& event)
|
||||||
Console.SetTitle("PCSX2 Program Log");
|
Console.SetTitle("PCSX2 Program Log");
|
||||||
CoreThread.Reset();
|
CoreThread.Reset();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Debug_Open_Click(wxCommandEvent& event)
|
void MainEmuFrame::Menu_Debug_Open_Click(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
|
@ -1049,151 +935,3 @@ void MainEmuFrame::Menu_Capture_Screenshot_Screenshot_As_Click(wxCommandEvent& e
|
||||||
CoreThread.Resume();
|
CoreThread.Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
Msgbox::Alert("Input Recording has been deprecated from the wxWidgets version.\nUse an older dev build or switch to the Qt version!\nOld recordings should still play correctly!");
|
|
||||||
return;
|
|
||||||
const bool emulation_initially_paused = CoreThread.IsPaused();
|
|
||||||
const bool recording_initially_paused = g_InputRecordingControls.IsPaused();
|
|
||||||
|
|
||||||
if (!emulation_initially_paused && !recording_initially_paused)
|
|
||||||
g_InputRecordingControls.PauseImmediately();
|
|
||||||
|
|
||||||
NewRecordingFrame* newRecordingFrame = wxGetApp().GetNewRecordingFramePtr();
|
|
||||||
if (newRecordingFrame)
|
|
||||||
{
|
|
||||||
if (newRecordingFrame->ShowModal(CoreThread.IsOpen()) != wxID_CANCEL)
|
|
||||||
{
|
|
||||||
if (g_InputRecording.Create(newRecordingFrame->GetFile(), newRecordingFrame->GetFrom(), newRecordingFrame->GetAuthor()))
|
|
||||||
{
|
|
||||||
if (!g_InputRecording.GetInputRecordingData().FromSaveState())
|
|
||||||
StartInputRecording();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!emulation_initially_paused && !recording_initially_paused)
|
|
||||||
g_InputRecordingControls.ResumeImmediately();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
Msgbox::Alert("Input Recording has been deprecated from the wxWidgets version.\nUse an older dev build or switch to the Qt version!\nOld recordings should still play correctly!");
|
|
||||||
return;
|
|
||||||
const bool initiallyPaused = g_InputRecordingControls.IsPaused();
|
|
||||||
|
|
||||||
if (!initiallyPaused)
|
|
||||||
g_InputRecordingControls.PauseImmediately();
|
|
||||||
|
|
||||||
wxFileDialog openFileDialog(this, _("Select P2M2 record file."), L"", L"",
|
|
||||||
L"p2m2 file(*.p2m2)|*.p2m2", wxFD_OPEN);
|
|
||||||
if (openFileDialog.ShowModal() == wxID_CANCEL)
|
|
||||||
{
|
|
||||||
if (!initiallyPaused)
|
|
||||||
g_InputRecordingControls.Resume();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
StopInputRecording();
|
|
||||||
if (!g_InputRecording.Play(this, openFileDialog.GetPath()))
|
|
||||||
{
|
|
||||||
if (!initiallyPaused)
|
|
||||||
g_InputRecordingControls.Resume();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_InputRecording.GetInputRecordingData().FromSaveState())
|
|
||||||
StartInputRecording();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::ApplyFirstFrameStatus()
|
|
||||||
{
|
|
||||||
wxMenuItem* cdvd_menu = m_menuSys.FindChildItem(MenuId_Boot_CDVD);
|
|
||||||
|
|
||||||
wxString keyCodeStr;
|
|
||||||
if (GSFrame* gsFrame = wxGetApp().GetGsFramePtr())
|
|
||||||
if (GSPanel* viewport = gsFrame->GetViewport())
|
|
||||||
keyCodeStr = '\t' + viewport->GetAssociatedKeyCode(("GoToFirstFrame"));
|
|
||||||
|
|
||||||
cdvd_menu->SetItemLabel(L"Restart Recording" + keyCodeStr);
|
|
||||||
if (g_InputRecording.GetInputRecordingData().FromSaveState())
|
|
||||||
cdvd_menu->SetHelp(L"Loads the savestate that accompanies the active input recording");
|
|
||||||
else
|
|
||||||
cdvd_menu->SetHelp(L"Reboots Emulation");
|
|
||||||
|
|
||||||
UpdateStatusBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Recording_Stop_Click(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
Msgbox::Alert("Input Recording has been deprecated from the wxWidgets version.\nUse an older dev build or switch to the Qt version!\nOld recordings should still play correctly!");
|
|
||||||
return;
|
|
||||||
StopInputRecording();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Recording_Config_FrameAdvance(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
Msgbox::Alert("Input Recording has been deprecated from the wxWidgets version.\nUse an older dev build or switch to the Qt version!\nOld recordings should still play correctly!");
|
|
||||||
return;
|
|
||||||
long result = wxGetNumberFromUser(_("Enter the number of frames to advance per advance"), _("Number of Frames"), _("Configure Frame Advance"), g_Conf->inputRecording.m_frame_advance_amount, 1, INT_MAX);
|
|
||||||
if (result != -1)
|
|
||||||
{
|
|
||||||
g_Conf->inputRecording.m_frame_advance_amount = result;
|
|
||||||
g_InputRecordingControls.setFrameAdvanceAmount(result);
|
|
||||||
wxString frame_advance_label = wxString(_("Configure Frame Advance"));
|
|
||||||
frame_advance_label.Append(wxString::Format(" (%ld)", result));
|
|
||||||
m_submenu_recording_settings.SetLabel(MenuId_Recording_Config_FrameAdvance, frame_advance_label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::StartInputRecording()
|
|
||||||
{
|
|
||||||
m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(false);
|
|
||||||
m_menuRecording.FindChildItem(MenuId_Recording_Stop)->Enable(true);
|
|
||||||
m_menuRecording.FindChildItem(MenuId_Recording_ToggleRecordingMode)->Enable(true);
|
|
||||||
ApplyFirstFrameStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::StopInputRecording()
|
|
||||||
{
|
|
||||||
if (g_InputRecording.IsActive())
|
|
||||||
{
|
|
||||||
g_InputRecording.Stop();
|
|
||||||
m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(true);
|
|
||||||
m_menuRecording.FindChildItem(MenuId_Recording_Stop)->Enable(false);
|
|
||||||
m_menuRecording.FindChildItem(MenuId_Recording_ToggleRecordingMode)->Enable(false);
|
|
||||||
ApplyCDVDStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Recording_TogglePause_Click(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
Msgbox::Alert("Input Recording has been deprecated from the wxWidgets version.\nUse an older dev build or switch to the Qt version!\nOld recordings should still play correctly!");
|
|
||||||
return;
|
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
|
||||||
g_InputRecordingControls.TogglePause();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Recording_FrameAdvance_Click(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
Msgbox::Alert("Input Recording has been deprecated from the wxWidgets version.\nUse an older dev build or switch to the Qt version!\nOld recordings should still play correctly!");
|
|
||||||
return;
|
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
|
||||||
g_InputRecordingControls.FrameAdvance();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Recording_ToggleRecordingMode_Click(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
Msgbox::Alert("Input Recording has been deprecated from the wxWidgets version.\nUse an older dev build or switch to the Qt version!\nOld recordings should still play correctly!");
|
|
||||||
return;
|
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
|
||||||
g_InputRecordingControls.RecordModeToggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Recording_VirtualPad_Open_Click(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
Msgbox::Alert("Input Recording has been deprecated from the wxWidgets version.\nUse an older dev build or switch to the Qt version!\nOld recordings should still play correctly!");
|
|
||||||
return;
|
|
||||||
g_InputRecording.ShowVirtualPad(event.GetId() - MenuId_Recording_VirtualPad_Port0);
|
|
||||||
}
|
|
||||||
|
|
|
@ -171,82 +171,6 @@
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
<!-- Generate Recording GUI Image Headers -->
|
<!-- Generate Recording GUI Image Headers -->
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\controllerFull.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\controllerThreeQuarters.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\controllerHalf.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\circlePressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\crossPressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\downPressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\l1Pressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\l2Pressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\l3Pressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\leftPressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\r1Pressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\r2Pressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\r3Pressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\rightPressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\selectPressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\squarePressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\startPressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\trianglePressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\upPressed.png">
|
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
|
||||||
</CustomBuild>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="CDVD\BlockdumpFileReader.cpp" />
|
<ClCompile Include="CDVD\BlockdumpFileReader.cpp" />
|
||||||
|
@ -449,13 +373,9 @@
|
||||||
<ClCompile Include="ps2\pgif.cpp" />
|
<ClCompile Include="ps2\pgif.cpp" />
|
||||||
<ClCompile Include="Dmac.cpp" />
|
<ClCompile Include="Dmac.cpp" />
|
||||||
<ClCompile Include="Recording\InputRecordingControls.cpp" />
|
<ClCompile Include="Recording\InputRecordingControls.cpp" />
|
||||||
<ClCompile Include="Recording\VirtualPad\VirtualPad.cpp" />
|
|
||||||
<ClCompile Include="Recording\VirtualPad\VirtualPadData.cpp" />
|
|
||||||
<ClCompile Include="Recording\VirtualPad\VirtualPadResources.cpp" />
|
|
||||||
<ClCompile Include="ShiftJisToUnicode.cpp" />
|
<ClCompile Include="ShiftJisToUnicode.cpp" />
|
||||||
<ClCompile Include="sif2.cpp" />
|
<ClCompile Include="sif2.cpp" />
|
||||||
<ClCompile Include="Recording\InputRecording.cpp" />
|
<ClCompile Include="Recording\InputRecording.cpp" />
|
||||||
<ClCompile Include="Recording\NewRecordingFrame.cpp" />
|
|
||||||
<ClCompile Include="Recording\InputRecordingFile.cpp" />
|
<ClCompile Include="Recording\InputRecordingFile.cpp" />
|
||||||
<ClCompile Include="Recording\PadData.cpp" />
|
<ClCompile Include="Recording\PadData.cpp" />
|
||||||
<ClCompile Include="USB\configuration.cpp" />
|
<ClCompile Include="USB\configuration.cpp" />
|
||||||
|
@ -963,12 +883,8 @@
|
||||||
<ClInclude Include="ps2\pgif.h" />
|
<ClInclude Include="ps2\pgif.h" />
|
||||||
<ClInclude Include="Recording\InputRecording.h" />
|
<ClInclude Include="Recording\InputRecording.h" />
|
||||||
<ClInclude Include="Recording\InputRecordingControls.h" />
|
<ClInclude Include="Recording\InputRecordingControls.h" />
|
||||||
<ClInclude Include="Recording\NewRecordingFrame.h" />
|
|
||||||
<ClInclude Include="Recording\InputRecordingFile.h" />
|
<ClInclude Include="Recording\InputRecordingFile.h" />
|
||||||
<ClInclude Include="Recording\PadData.h" />
|
<ClInclude Include="Recording\PadData.h" />
|
||||||
<ClInclude Include="Recording\VirtualPad\VirtualPad.h" />
|
|
||||||
<ClInclude Include="Recording\VirtualPad\VirtualPadData.h" />
|
|
||||||
<ClInclude Include="Recording\VirtualPad\VirtualPadResources.h" />
|
|
||||||
<ClInclude Include="Recording\Utilities\InputRecordingLogger.h" />
|
<ClInclude Include="Recording\Utilities\InputRecordingLogger.h" />
|
||||||
<ClInclude Include="USB\configuration.h" />
|
<ClInclude Include="USB\configuration.h" />
|
||||||
<ClInclude Include="USB\deviceproxy.h" />
|
<ClInclude Include="USB\deviceproxy.h" />
|
||||||
|
|
|
@ -142,12 +142,6 @@
|
||||||
<Filter Include="Recording">
|
<Filter Include="Recording">
|
||||||
<UniqueIdentifier>{7b917318-5a5e-44c0-8463-1dfab67f3b67}</UniqueIdentifier>
|
<UniqueIdentifier>{7b917318-5a5e-44c0-8463-1dfab67f3b67}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Recording\gui">
|
|
||||||
<UniqueIdentifier>{93e36831-627f-4529-b709-1f4bad398512}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Recording\VirtualPad">
|
|
||||||
<UniqueIdentifier>{ae88cd9a-f9f2-4196-979c-7a16ed5e455e}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="System\Ps2\Iop\CDVD\Windows">
|
<Filter Include="System\Ps2\Iop\CDVD\Windows">
|
||||||
<UniqueIdentifier>{be861049-a142-4650-85a5-a2fdd4eef011}</UniqueIdentifier>
|
<UniqueIdentifier>{be861049-a142-4650-85a5-a2fdd4eef011}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
@ -163,9 +157,6 @@
|
||||||
<Filter Include="Recording\Utilities">
|
<Filter Include="Recording\Utilities">
|
||||||
<UniqueIdentifier>{85c5a0d2-6404-439f-8756-d908a1442b96}</UniqueIdentifier>
|
<UniqueIdentifier>{85c5a0d2-6404-439f-8756-d908a1442b96}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Recording\VirtualPad\Images">
|
|
||||||
<UniqueIdentifier>{ad528458-08eb-49a2-aefa-3c2b86ab8896}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="System\Ps2\DEV9">
|
<Filter Include="System\Ps2\DEV9">
|
||||||
<UniqueIdentifier>{8d5454f9-590c-4c53-aae1-8391c6465e50}</UniqueIdentifier>
|
<UniqueIdentifier>{8d5454f9-590c-4c53-aae1-8391c6465e50}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
@ -1049,24 +1040,12 @@
|
||||||
<ClCompile Include="Recording\PadData.cpp">
|
<ClCompile Include="Recording\PadData.cpp">
|
||||||
<Filter>Recording</Filter>
|
<Filter>Recording</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Recording\NewRecordingFrame.cpp">
|
|
||||||
<Filter>Recording\gui</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Recording\VirtualPad\VirtualPad.cpp">
|
|
||||||
<Filter>Recording\VirtualPad</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="IPU\IPUdither.cpp">
|
<ClCompile Include="IPU\IPUdither.cpp">
|
||||||
<Filter>System\Ps2\IPU</Filter>
|
<Filter>System\Ps2\IPU</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Recording\InputRecordingControls.cpp">
|
<ClCompile Include="Recording\InputRecordingControls.cpp">
|
||||||
<Filter>Recording</Filter>
|
<Filter>Recording</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Recording\VirtualPad\VirtualPadData.cpp">
|
|
||||||
<Filter>Recording\VirtualPad</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Recording\VirtualPad\VirtualPadResources.cpp">
|
|
||||||
<Filter>Recording\VirtualPad</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="CDVD\CDVDdiscReader.cpp">
|
<ClCompile Include="CDVD\CDVDdiscReader.cpp">
|
||||||
<Filter>System\Ps2\Iop\CDVD</Filter>
|
<Filter>System\Ps2\Iop\CDVD</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -2263,21 +2242,9 @@
|
||||||
<ClInclude Include="Recording\PadData.h">
|
<ClInclude Include="Recording\PadData.h">
|
||||||
<Filter>Recording</Filter>
|
<Filter>Recording</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Recording\NewRecordingFrame.h">
|
|
||||||
<Filter>Recording\gui</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Recording\VirtualPad\VirtualPad.h">
|
|
||||||
<Filter>Recording\VirtualPad</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Recording\InputRecordingControls.h">
|
<ClInclude Include="Recording\InputRecordingControls.h">
|
||||||
<Filter>Recording</Filter>
|
<Filter>Recording</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Recording\VirtualPad\VirtualPadData.h">
|
|
||||||
<Filter>Recording\VirtualPad</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Recording\VirtualPad\VirtualPadResources.h">
|
|
||||||
<Filter>Recording\VirtualPad</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="CDVD\CDVDdiscReader.h">
|
<ClInclude Include="CDVD\CDVDdiscReader.h">
|
||||||
<Filter>System\Ps2\Iop\CDVD</Filter>
|
<Filter>System\Ps2\Iop\CDVD</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -3101,63 +3068,6 @@
|
||||||
<CustomBuild Include="gui\Resources\Logo.png">
|
<CustomBuild Include="gui\Resources\Logo.png">
|
||||||
<Filter>AppHost\Resources</Filter>
|
<Filter>AppHost\Resources</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\circlePressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\controllerFull.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\controllerHalf.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\controllerThreeQuarters.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\crossPressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\downPressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\l1Pressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\l2Pressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\l3Pressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\leftPressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\startPressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\r1Pressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\r2Pressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\r3Pressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\rightPressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\selectPressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\squarePressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\trianglePressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="Recording\VirtualPad\img\upPressed.png">
|
|
||||||
<Filter>Recording\VirtualPad\Images</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Manifest Include="windows\PCSX2.manifest">
|
<Manifest Include="windows\PCSX2.manifest">
|
||||||
|
|