significant work on Pause component (not ready yet, but feel free to test)
This commit is contained in:
@@ -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;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user