significant work on Pause component (not ready yet, but feel free to test)

This commit is contained in:
somewhatlurker
2019-10-19 15:29:07 +11:00
parent 41f8aa6d3c
commit 030850a6dd
9 changed files with 187 additions and 0 deletions
@@ -12,6 +12,7 @@
#include "DebugComponent.h"
#include "ScaleComponent.h"
#include "ScoreSaver.h"
#include "Pause.h"
#include "GameTargets/TargetInspector.h"
using ConfigFile = TLAC::FileSystem::ConfigFile;
@@ -36,6 +37,7 @@ namespace TLAC::Components
new InputEmulator(),
new TouchSliderEmulator(),
new TouchPanelEmulator(),
new Pause(), // ensure pause is always immediately after input emulators so it can swallow inputs
new PlayerDataManager(),
new FrameRateManager(),
new FastLoader(),
@@ -133,6 +135,14 @@ namespace TLAC::Components
component->UpdateInput();
}
void ComponentsManager::UpdatePostInput()
{
for (auto& component : components)
{
component->UpdatePostInput();
}
}
void ComponentsManager::OnFocusGain()
{
for (auto& component : components)
@@ -27,6 +27,7 @@ namespace TLAC::Components
void Initialize();
void Update();
void UpdateInput();
void UpdatePostInput();
void OnFocusGain();
void OnFocusLost();
void Dispose();
@@ -16,6 +16,7 @@ namespace TLAC::Components
virtual void Update() = 0;
virtual void UpdateInput() {};
virtual void UpdatePostInput() {};
virtual void OnFocusGain() {};
virtual void OnFocusLost() {};
@@ -0,0 +1,124 @@
#include "Pause.h"
#include "../Constants.h"
#include "GameState.h"
#include "Input/InputState.h"
#include <windows.h>
#include <vector>
namespace TLAC::Components
{
Pause::Pause()
{
}
Pause::~Pause()
{
}
const char* Pause::GetDisplayName()
{
return "pause";
}
void Pause::Initialize(ComponentsManager*)
{
origAetMovOp.resize(8);
memcpy(&origAetMovOp[0], aetMovPatchAddress, 8);
}
void Pause::Update()
{
}
void Pause::UpdatePostInput()
{
if (isPaused)
{
// exit pause if key is tapped or no longer in game somehow
if (isPauseKeyTapped() || *(GameState*)CURRENT_GAME_STATE_ADDRESS != GS_GAME || *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS != SUB_GAME_MAIN)
{
setPaused(false);
}
else
{
// swallow all button inputs if paused
InputState* inputState = (InputState*)(*(uint64_t*)INPUT_STATE_PTR_ADDRESS);
inputState->Tapped.Buttons = JVS_NONE;
inputState->DoubleTapped.Buttons = JVS_NONE;
inputState->Down.Buttons = JVS_NONE;
inputState->Released.Buttons = JVS_NONE;
inputState->IntervalTapped.Buttons = JVS_NONE;
// todo: slider
}
}
else
{
// only enter pause if in game
if (*(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME && *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS == SUB_GAME_MAIN)
{
if (isPauseKeyTapped())
{
setPaused(true);
}
}
}
}
bool Pause::isPauseKeyTapped()
{
return ((InputState*)(*(uint64_t*)INPUT_STATE_PTR_ADDRESS))->Tapped.Buttons & JVS_START;
}
void Pause::setPaused(bool pause)
{
uint64_t audioMixerAddr = *(uint64_t*)(AUDIO_MAIN_CLASS_ADDRESS + 0x70);
uint64_t audioStreamsAddress = *(uint64_t*)(audioMixerAddr + 0x18);;
int nAudioStreams = *(uint64_t*)(audioMixerAddr + 0x20);
if (pause)
{
*(float*)FRAME_SPEED_ADDRESS = 0.0f; // todo: hook getFrameSpeed so this can't be screwed up
((void(*)())DSC_PAUSE_FUNC_ADDRESS)();
InjectCode(aetMovPatchAddress, { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 });
for (int i = 0; i < nAudioStreams; i++)
{
uint32_t* playstate = (uint32_t*)(audioStreamsAddress + i * 0x50 + 0x18);
if (i < streamPlayStates.size())
streamPlayStates[i] = *playstate;
else
streamPlayStates.push_back(*playstate);
*playstate = 0;
}
}
else
{
*(float*)FRAME_SPEED_ADDRESS = 1.0f;
((void(*)())DSC_UNPAUSE_FUNC_ADDRESS)();
InjectCode(aetMovPatchAddress, origAetMovOp);
for (int i = 0; i < nAudioStreams; i++)
{
uint32_t* playstate = (uint32_t*)(audioStreamsAddress + i * 0x50 + 0x18);
if (i < streamPlayStates.size())
*playstate = streamPlayStates[i];
}
}
isPaused = pause;
}
void Pause::InjectCode(void* address, const std::vector<uint8_t> data)
{
const size_t byteCount = data.size() * sizeof(uint8_t);
DWORD oldProtect;
VirtualProtect(address, byteCount, PAGE_EXECUTE_READWRITE, &oldProtect);
memcpy(address, data.data(), byteCount);
VirtualProtect(address, byteCount, oldProtect, nullptr);
}
}
@@ -0,0 +1,29 @@
#pragma once
#include "EmulatorComponent.h"
#include <vector>
namespace TLAC::Components
{
class Pause : public EmulatorComponent
{
public:
Pause();
~Pause();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
virtual void UpdatePostInput() override;
private:
bool isPaused;
bool isPauseKeyTapped();
void setPaused(bool pause);
std::vector<bool> streamPlayStates;
void InjectCode(void* address, const std::vector<uint8_t> data);
std::vector<uint8_t> origAetMovOp;
uint8_t* aetMovPatchAddress = (uint8_t*)0x1401703b3;
};
}
@@ -97,6 +97,18 @@ constexpr uint64_t CURRENT_SONG_ID_ADDRESS = 0x0000000140CDD8E0;
constexpr uint64_t SELPV_CURRENT_SONG_ADDRESS = 0x000000014CC12438;
constexpr uint64_t SONG_CLEAR_COUNTS_ADDRESS = 0x00000001411A95E8;
constexpr uint64_t AUDIO_MAIN_CLASS_ADDRESS = 0x000000014CC61120;
constexpr uint64_t DSC_TIME_ADDRESS = 0x0000000140D0B518;
constexpr uint64_t DSC_START_FROM_TIME_ADDRESS = 0x0000000140D0B540;
constexpr uint64_t DSC_START_SYS_TIME_ADDRESS = 0x0000000140D0B548;
constexpr uint64_t DSC_TIME_ADDRESS_2 = 0x0000000140D0B520;
constexpr uint64_t DSC_START_FROM_TIME_ADDRESS_2 = 0x0000000140D0B560;
constexpr uint64_t DSC_START_SYS_TIME_ADDRESS_2 = 0x0000000140D0B568;
constexpr uint64_t DSC_PAUSE_FUNC_ADDRESS = 0x00000001401295C0;
constexpr uint64_t DSC_UNPAUSE_FUNC_ADDRESS = 0x0000000140129590;
#define XINPUT_A 0x00
#define XINPUT_B 0x01
#define XINPUT_X 0x02
@@ -128,6 +128,7 @@
<ClInclude Include="Components\Input\TouchPanelState.h" />
<ClInclude Include="Components\Input\TouchSliderEmulator.h" />
<ClInclude Include="Components\Input\TouchSliderState.h" />
<ClInclude Include="Components\Pause.h" />
<ClInclude Include="Components\PlayerData.h" />
<ClInclude Include="Components\PlayerDataManager.h" />
<ClInclude Include="Components\ScaleComponent.h" />
@@ -181,6 +182,7 @@
<ClCompile Include="Components\Input\TouchPanelEmulator.cpp" />
<ClCompile Include="Components\Input\TouchSliderEmulator.cpp" />
<ClCompile Include="Components\Input\TouchSliderState.cpp" />
<ClCompile Include="Components\Pause.cpp" />
<ClCompile Include="Components\PlayerDataManager.cpp" />
<ClCompile Include="Components\ScaleComponent.cpp" />
<ClCompile Include="Components\ScoreSaver.cpp" />
@@ -195,6 +195,9 @@
<ClInclude Include="pluginconfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\Pause.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
@@ -329,5 +332,8 @@
<ClCompile Include="Components\ScoreSaver.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\Pause.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
@@ -101,6 +101,8 @@ namespace TLAC
ComponentsManager.UpdateInput();
}
ComponentsManager.UpdatePostInput();
if ((framework::inputDisable))
{
Input::Keyboard::GetInstance()->PollInput();