Initial CControllerRecorder imp (very WIP)

This commit is contained in:
Phillip Stephens 2021-05-29 00:41:52 -07:00
parent fe965cde0e
commit 4cfc4e78ec
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
7 changed files with 145 additions and 13 deletions

View File

@ -0,0 +1,50 @@
#include "Runtime/Input/CControllerRecorder.hpp"
#include "Runtime/Graphics/CGraphics.hpp"
#include "Runtime/CArchitectureQueue.hpp"
#include "Runtime/CArchitectureMessage.hpp"
namespace metaforce {
bool CControllerRecorder::ProcessInput(const CFinalInput& in, s32 frame, CArchitectureQueue& queue) {
if (m_mode == EMode::Record) {
m_finalInputs[frame] = in;
return false;
} else {
SetMode(EMode::Record);
}
if (m_mode == EMode::Play && m_finalInputs.find(frame) != m_finalInputs.end()) {
queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, m_finalInputs[frame]));
return true;
}
return false;
}
void CControllerRecorder::SetMode(EMode mode) {
EMode oldMode = m_mode;
m_mode = mode;
if (m_mode == EMode::Record && oldMode != EMode::Record) {
m_initialState = *g_GameState;
} else if (oldMode == EMode::Record && m_mode == EMode::None) {
//auto w = athena::io::FileWriter("/home/antidote/Documents/test.inp");
//PutTo(w);
} else if (oldMode == EMode::None && m_mode == EMode::Play) {
m_oldGameStatePtr = g_GameState;
g_GameState = &m_initialState;
} else if (oldMode == EMode::Play && m_mode == EMode::None) {
}
}
void CControllerRecorder::PutTo(COutputStream& out) {
out.writeUint32Big(1); // Version
m_initialState.WriteBackupBuf();
auto& buf = m_initialState.BackupBuf();
out.writeUint32Big(buf.size());
out.writeBytes(buf.data(), buf.size());
out.writeUint32Big(m_finalInputs.size());
for (auto pair : m_finalInputs) {
out.writeUint32Big(pair.first);
pair.second.PutTo(out);
}
}
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "Runtime/Input/CFinalInput.hpp"
#include "Runtime/CGameState.hpp"
namespace metaforce {
class CArchitectureQueue;
class CControllerRecorder {
public:
enum class EMode {
None,
Record,
Play
};
private:
std::map<int, CFinalInput> m_finalInputs; // frame -> input
EMode m_mode = EMode::None;
CGameState m_initialState;
const CGameState* m_oldGameStatePtr = nullptr;
public:
CControllerRecorder() = default;
bool ProcessInput(const CFinalInput& in, s32 frame, CArchitectureQueue& queue);
void SetMode(EMode mode);
void PutTo(COutputStream& out);
};
} // namespace metaforce

View File

@ -162,4 +162,51 @@ CFinalInput CFinalInput::ScaleAnalogueSticks(float leftDiv, float rightDiv) cons
ret.m_rightMul = 1.f / rightDiv;
return ret;
}
void CFinalInput::PutTo(COutputStream& out) {
out.writeFloatBig(x0_dt);
out.writeFloatBig(x4_controllerIdx);
out.writeFloatBig(x8_anaLeftX);
out.writeFloatBig(xc_anaLeftY);
out.writeFloatBig(x10_anaRightX);
out.writeFloatBig(x14_anaRightY);
out.writeFloatBig(x18_anaLeftTrigger);
out.writeFloatBig(x1c_anaRightTrigger);
out.writeBool(x20_enableAnaLeftXP);
out.writeBool(x20_enableAnaLeftNegXP);
out.writeBool(x21_enableAnaLeftYP);
out.writeBool(x21_enableAnaLeftNegYP);
out.writeBool(x22_enableAnaRightXP);
out.writeBool(x22_enableAnaRightNegXP);
out.writeBool(x23_enableAnaRightYP);
out.writeBool(x23_enableAnaRightNegYP);
out.writeBool(x24_anaLeftTriggerP);
out.writeBool(x28_anaRightTriggerP);
out.writeBool(x2c_b24_A);
out.writeBool(x2c_b25_B);
out.writeBool(x2c_b26_X);
out.writeBool(x2c_b27_Y);
out.writeBool(x2c_b28_Z);
out.writeBool(x2c_b29_L);
out.writeBool(x2c_b30_R);
out.writeBool(x2c_b31_DPUp);
out.writeBool(x2d_b24_DPRight);
out.writeBool(x2d_b25_DPDown);
out.writeBool(x2d_b26_DPLeft);
out.writeBool(x2d_b27_Start);
out.writeBool(x2d_b28_PA);
out.writeBool(x2d_b29_PB);
out.writeBool(x2d_b30_PX);
out.writeBool(x2d_b31_PY);
out.writeBool(x2e_b25_PL);
out.writeBool(x2e_b26_PR);
out.writeBool(x2e_b27_PDPUp);
out.writeBool(x2e_b28_PDPRight);
out.writeBool(x2e_b29_PDPDown);
out.writeBool(x2e_b30_PDPLeft);
out.writeBool(x2e_b31_PStart);
out.writeBytes(m_PCharKeys.data(), m_PCharKeys.size() - 1);
out.writeBytes(m_PSpecialKeys.data(), m_PSpecialKeys.size() - 1);
out.writeBytes(m_PMouseButtons.data(), m_PMouseButtons.size() - 1);
}
} // namespace metaforce

View File

@ -171,6 +171,7 @@ struct CFinalInput {
float AMouseButton(boo::EMouseButton k) const { return DMouseButton(k) ? 1.f : 0.f; }
const std::optional<CKeyboardMouseControllerData>& GetKBM() const { return m_kbm; }
void PutTo(COutputStream& out);
};
} // namespace metaforce

View File

@ -28,13 +28,15 @@ void CInputGenerator::Update(float dt, CArchitectureQueue& queue) {
input |= kbInput;
kbUsed = true;
}
if (!m_recorder.ProcessInput(input, CGraphics::GetFrameCounter(), queue)) {
queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, input));
}
}
}
/* Send straight keyboard input if no first controller present */
if (!kbUsed)
if (!kbUsed && !m_recorder.ProcessInput(kbInput, CGraphics::GetFrameCounter(), queue)) {
queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, kbInput));
}
}
} // namespace metaforce

View File

@ -5,6 +5,8 @@
#include <mutex>
#include "Runtime/Input/CFinalInput.hpp"
#include "Runtime/Input/CControllerRecorder.hpp"
#include "Runtime/Input/CKeyboardMouseController.hpp"
#include <boo/boo.hpp>
@ -33,7 +35,7 @@ class CInputGenerator : public boo::DeviceFinder {
}
bool m_firstFrame = true;
CControllerRecorder m_recorder;
public:
CInputGenerator(float leftDiv, float rightDiv)
: boo::DeviceFinder({dev_typeid(DolphinSmashAdapter)}), m_leftDiv(leftDiv), m_rightDiv(rightDiv) {}
@ -180,6 +182,7 @@ public:
/* This is where the game thread enters */
void Update(float dt, CArchitectureQueue& queue);
void SetRecordMode(CControllerRecorder::EMode mode) { m_recorder.SetMode(mode); };
};
} // namespace metaforce

View File

@ -7,6 +7,7 @@ set(INPUT_SOURCES
CRumbleManager.hpp CRumbleManager.cpp
CRumbleGenerator.hpp CRumbleGenerator.cpp
CRumbleVoice.hpp CRumbleVoice.cpp
RumbleFxTable.hpp RumbleFxTable.cpp)
RumbleFxTable.hpp RumbleFxTable.cpp
CControllerRecorder.hpp CControllerRecorder.cpp)
runtime_add_list(Input INPUT_SOURCES)