This commit is contained in:
nastys
2019-07-30 13:48:28 +02:00
parent 25f819bdfb
commit 998f4274a5
157 changed files with 0 additions and 0 deletions
@@ -0,0 +1,231 @@
#include "CameraController.h"
#include <algorithm>
#include "Input/InputState.h"
#include "ComponentsManager.h"
#include "../framework.h"
#include "../Input/Mouse/Mouse.h"
#include "../Input/Keyboard/Keyboard.h"
#include "../Input/Bindings/KeyboardBinding.h"
#define GLUT_CURSOR_RIGHT_ARROW 0x0000
#define GLUT_CURSOR_NONE 0x0065
using namespace TLAC::Input;
using namespace TLAC::Utilities;
namespace TLAC::Components
{
CameraController::CameraController()
{
}
CameraController::~CameraController()
{
delete ToggleBinding;
delete ForwardBinding;
delete BackwardBinding;
delete LeftBinding;
delete RightBinding;
delete UpBinding;
delete DownBinding;
delete ClockwiseBinding;
delete CounterClockwiseBinding;
delete ZoomInBinding;
delete ZoomOutBinding;
delete FastBinding;
delete SlowBinding;
}
const char* CameraController::GetDisplayName()
{
return "camera_controller";
}
void CameraController::Initialize(ComponentsManager* manager)
{
componentsManager = manager;
printf("[TLAC] CameraController::Initialize(): Initialized\n");
for (int i = 0; i < sizeof(cameraSetterAddresses) / sizeof(void*); i++)
{
DWORD oldProtect;
VirtualProtect((void*)cameraSetterAddresses[i], sizeof(uint8_t), PAGE_EXECUTE_READWRITE, &oldProtect);
originalSetterBytes[i] = *(uint8_t*)cameraSetterAddresses[i];
}
ToggleBinding = new Binding();
ToggleBinding->AddBinding(new KeyboardBinding(VK_F3));
ForwardBinding = new Binding();
ForwardBinding->AddBinding(new KeyboardBinding('W'));
BackwardBinding = new Binding();
BackwardBinding->AddBinding(new KeyboardBinding('S'));
LeftBinding = new Binding();
LeftBinding->AddBinding(new KeyboardBinding('A'));
RightBinding = new Binding();
RightBinding->AddBinding(new KeyboardBinding('D'));
UpBinding = new Binding();
UpBinding->AddBinding(new KeyboardBinding(VK_SPACE));
DownBinding = new Binding();
DownBinding->AddBinding(new KeyboardBinding(VK_CONTROL));
ClockwiseBinding = new Binding();
ClockwiseBinding->AddBinding(new KeyboardBinding('E'));
CounterClockwiseBinding = new Binding();
CounterClockwiseBinding->AddBinding(new KeyboardBinding('Q'));
ZoomInBinding = new Binding();
ZoomInBinding->AddBinding(new KeyboardBinding('R'));
ZoomOutBinding = new Binding();
ZoomOutBinding->AddBinding(new KeyboardBinding('F'));
FastBinding = new Binding();
FastBinding->AddBinding(new KeyboardBinding(VK_SHIFT));
SlowBinding = new Binding();
SlowBinding->AddBinding(new KeyboardBinding(VK_MENU));
camera = (Camera*)CAMERA_ADDRESS;
}
void CameraController::Update()
{
return;
}
void CameraController::UpdateInput()
{
if (ToggleBinding->AnyTapped())
{
SetControls(!GetIsEnabled());
return;
}
if (!GetIsEnabled())
return;
auto keyboard = Keyboard::GetInstance();
auto mouse = Mouse::GetInstance();
bool forward = ForwardBinding->AnyDown();
bool backward = BackwardBinding->AnyDown();
bool left = LeftBinding->AnyDown();
bool right = RightBinding->AnyDown();
bool up = UpBinding->AnyDown();
bool down = DownBinding->AnyDown();
bool fast = FastBinding->AnyDown();
bool slow = SlowBinding->AnyDown();
bool clockwise = ClockwiseBinding->AnyDown();
bool counterclockwise = CounterClockwiseBinding->AnyDown();
bool zoomin = ZoomInBinding->AnyDown();
bool zoomout = ZoomOutBinding->AnyDown();
float speed = GetElapsedTime() * (fast ? fastSpeed : slow ? slowSpeed : normalSpeed);
if (forward ^ backward)
camera->Position += PointFromAngle(verticalRotation + (forward ? +0.0f : -180.0f), speed);
if (left ^ right)
camera->Position += PointFromAngle(verticalRotation + (right ? +90.0f : -90.0f), speed);
if (up ^ down)
camera->Position.Y += speed * (up ? +0.25f : -0.25f);
if (clockwise ^ counterclockwise)
camera->Rotation += speed * (clockwise ? -1.0f : +1.0f);
if (zoomin ^ zoomout)
{
camera->HorizontalFov += speed * (zoomin ? -1.0f : +1.0f);
camera->HorizontalFov = std::clamp(camera->HorizontalFov, +1.0f, +170.0f);
}
if (mouse->HasMoved())
{
SetMouseWindowCenter();
auto delta = mouse->GetDeltaPosition();
verticalRotation += delta.x * sensitivity;
horizontalRotation -= delta.y * (sensitivity / 5.0f);
horizontalRotation = std::clamp(horizontalRotation, -75.0f, +75.0f);
}
((InputState*)*(uint64_t*)INPUT_STATE_PTR_ADDRESS)->HideCursor();
Vec2 focus = PointFromAngle(verticalRotation, 1.0f);
camera->Focus.X = camera->Position.X + focus.X;
camera->Focus.Z = camera->Position.Z + focus.Y;
camera->Focus.Y = camera->Position.Y + PointFromAngle(horizontalRotation, 5.0f).X;
}
void CameraController::SetControls(bool value)
{
if (GetIsEnabled() == value)
return;
SetIsEnabled(value);
componentsManager->SetUpdateGameInput(!value);
printf("[TLAC] CameraController::SetControls(): enabled = %s\n", GetIsEnabled() ? "true" : "false");
typedef void __stdcall _glutSetCursor(int);
auto glutSetCursor = (_glutSetCursor*)GLUT_SET_CURSOR_ADDRESS;
// hide cursor
glutSetCursor(value ? GLUT_CURSOR_NONE : GLUT_CURSOR_RIGHT_ARROW);
if (value)
{
// disable camera setters
for (int i = 0; i < sizeof(cameraSetterAddresses) / sizeof(void*); i++)
*(uint8_t*)cameraSetterAddresses[i] = RET_OPCODE;
// set initial camera angle
Vec2 camXz = Vec2(camera->Position.X, camera->Position.Z);
Vec2 focusXz = Vec2(camera->Focus.X, camera->Focus.Z);
verticalRotation = AngleFromPoints(camXz, focusXz);
horizontalRotation = 0;
camera->Rotation = defaultRotation;
camera->HorizontalFov = defaultFov;
}
else
{
// restore camera setters
for (int i = 0; i < sizeof(cameraSetterAddresses) / sizeof(void*); i++)
*(uint8_t*)cameraSetterAddresses[i] = originalSetterBytes[i];
}
}
void CameraController::SetMouseWindowCenter()
{
RECT windowRect = framework::GetWindowBounds();
int centerX = windowRect.left + (windowRect.right - windowRect.left) / 2;
int centerY = windowRect.top + (windowRect.bottom - windowRect.top) / 2;
Mouse::GetInstance()->SetPosition(centerX, centerY);
}
bool CameraController::GetIsEnabled()
{
return isEnabled;
}
void CameraController::SetIsEnabled(bool value)
{
isEnabled = value;
}
}
@@ -0,0 +1,80 @@
#pragma once
#include "EmulatorComponent.h"
#include "../Constants.h"
#include "../Input/Bindings/Binding.h"
#include "../Utilities/Math.h"
namespace TLAC::Components
{
struct Camera
{
Utilities::Vec3 Position;
Utilities::Vec3 Focus;
float Rotation;
float HorizontalFov;
float VerticalFov;
};
class CameraController : public EmulatorComponent
{
public:
Input::Binding* ToggleBinding;
Input::Binding* ForwardBinding;
Input::Binding* BackwardBinding;
Input::Binding* LeftBinding;
Input::Binding* RightBinding;
Input::Binding* UpBinding;
Input::Binding* DownBinding;
Input::Binding* FastBinding;
Input::Binding* SlowBinding;
Input::Binding* ClockwiseBinding;
Input::Binding* CounterClockwiseBinding;
Input::Binding* ZoomInBinding;
Input::Binding* ZoomOutBinding;
CameraController();
~CameraController();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
virtual void UpdateInput() override;
void SetControls(bool value);
bool GetIsEnabled();
private:
const float fastSpeed = 0.1f;
const float slowSpeed = 0.0005f;
const float normalSpeed = 0.005f;
const float defaultRotation = 0.0f;
const float defaultFov = 70.0f;
const float sensitivity = 0.25f;
ComponentsManager* componentsManager;
float verticalRotation;
float horizontalRotation;
bool isEnabled;
Camera* camera;
uint8_t originalSetterBytes[4];
void* cameraSetterAddresses[4] =
{
(void*)CAMERA_POS_SETTER_ADDRESS,
(void*)CAMERA_INTR_SETTER_ADDRESS,
(void*)CAMERA_ROT_SETTER_ADDRESS,
(void*)CAMERA_PERS_SETTER_ADDRESS,
};
void SetMouseWindowCenter();
void SetIsEnabled(bool value);
};
}
@@ -0,0 +1,155 @@
#include "ComponentsManager.h"
#include "../FileSystem/ConfigFile.h"
#include "../framework.h"
#include "Input/InputEmulator.h"
#include "Input/TouchSliderEmulator.h"
#include "Input/TouchPanelEmulator.h"
#include "SysTimer.h"
#include "PlayerDataManager.h"
#include "FrameRateManager.h"
#include "FastLoader.h"
#include "StageManager.h"
#include "CameraController.h"
#include "DebugComponent.h"
#include "ScaleComponent.h"
#include "FPSLimiter.h"
#include "GameTargets/TargetInspector.h"
using ConfigFile = TLAC::FileSystem::ConfigFile;
namespace TLAC::Components
{
typedef void EngineUpdateInput(void*);
ComponentsManager::ComponentsManager()
{
}
ComponentsManager::~ComponentsManager()
{
}
void ComponentsManager::ParseAddComponents()
{
EmulatorComponent* allComponents[]
{
new TargetInspector(),
new InputEmulator(),
new TouchSliderEmulator(),
new TouchPanelEmulator(),
new SysTimer(),
new PlayerDataManager(),
new FrameRateManager(),
new FastLoader(),
new ScaleComponent(),
new FPSLimiter(),
new StageManager(),
new CameraController(),
new DebugComponent(),
};
ConfigFile componentsConfig(framework::GetModuleDirectory(), COMPONENTS_CONFIG_FILE_NAME);
bool success = componentsConfig.OpenRead();
if (!success)
{
printf("ComponentsManager::ParseAddComponents(): Unable to parse %s\n", COMPONENTS_CONFIG_FILE_NAME.c_str());
return;
}
size_t componentCount = sizeof(allComponents) / sizeof(EmulatorComponent*);
components.reserve(componentCount);
std::string trueString = "true", falseString = "false";
for (int i = 0; i < componentCount; i++)
{
std::string* value;
auto name = allComponents[i]->GetDisplayName();
//printf("ComponentsManager::ParseAddComponents(): searching name: %s\n", name);
if (componentsConfig.TryGetValue(name, &value))
{
//printf("ComponentsManager::ParseAddComponents(): %s found\n", name);
if (*value == trueString)
{
//printf("ComponentsManager::ParseAddComponents(): enabling %s...\n", name);
components.push_back(allComponents[i]);
}
else if (*value == falseString)
{
//printf("ComponentsManager::ParseAddComponents(): disabling %s...\n", name);
}
else
{
//printf("ComponentsManager::ParseAddComponents(): invalid value %s for component %s\n", value, name);
}
delete value;
}
else
{
//printf("ParseAddComponents(): component %s not found\n", name);
delete allComponents[i];
}
}
}
void ComponentsManager::Initialize()
{
dwGuiDisplay = (DwGuiDisplay*) * (uint64_t*)DW_GUI_DISPLAY_INSTANCE_PTR_ADDRESS;
ParseAddComponents();
updateStopwatch.Start();
for (auto& component : components)
component->Initialize(this);
}
void ComponentsManager::Update()
{
elpasedTime = updateStopwatch.Restart();
for (auto& component : components)
{
component->SetElapsedTime(elpasedTime);
component->Update();
}
}
void ComponentsManager::UpdateInput()
{
if (!GetIsInputEmulatorUsed())
{
uint64_t* inputStatePtr = (uint64_t*)INPUT_STATE_PTR_ADDRESS;
// poll input using the original PollInput function we overwrote with the update hook instead
if (inputStatePtr != nullptr)
((EngineUpdateInput*)ENGINE_UPDATE_INPUT_ADDRESS)((void*)* inputStatePtr);
}
for (auto& component : components)
component->UpdateInput();
}
void ComponentsManager::OnFocusGain()
{
for (auto& component : components)
component->OnFocusGain();
}
void ComponentsManager::OnFocusLost()
{
for (auto& component : components)
component->OnFocusLost();
}
void ComponentsManager::Dispose()
{
for (auto& component : components)
delete component;
}
}
@@ -0,0 +1,55 @@
#pragma once
#include "EmulatorComponent.h"
#include "../Utilities/Stopwatch.h"
#include <vector>
#include <string>
namespace TLAC::Components
{
const std::string COMPONENTS_CONFIG_FILE_NAME = "components.ini";
// Incomplete type
struct DwGuiDisplay
{
void* vftable;
void* active;
void* cap;
void* on;
void* move;
void* widget;
};
class ComponentsManager
{
public:
ComponentsManager();
~ComponentsManager();
void Initialize();
void Update();
void UpdateInput();
void OnFocusGain();
void OnFocusLost();
void Dispose();
inline bool GetIsInputEmulatorUsed() { return isInputEmulatorUsed; };
inline void SetIsInputEmulatorUsed(bool value) { isInputEmulatorUsed = value; };
inline bool GetUpdateGameInput() { return updateGameInput; };
inline void SetUpdateGameInput(bool value) { updateGameInput = value; }
inline bool IsDwGuiActive() { return dwGuiDisplay->active != nullptr; };
inline bool IsDwGuiHovered() { return dwGuiDisplay->on != nullptr; };
private:
DwGuiDisplay* dwGuiDisplay;
bool isInputEmulatorUsed = false;
bool updateGameInput = true;
float elpasedTime;
Utilities::Stopwatch updateStopwatch;
std::vector<EmulatorComponent*> components;
void ParseAddComponents();
};
}
@@ -0,0 +1,20 @@
#pragma once
#include <string>
namespace TLAC::Components
{
struct CustomPlayerData
{
std::string *PlayerName;
std::string* LevelName;
int LevelPlateId;
int SkinEquip;
int BtnSeEquip;
int SlideSeEquip;
int ChainslideSeEquip;
bool ShowGreatClearBorder;
bool ShowExcellentClearBorder;
bool UseCard;
bool GameModifierOptions;
};
}
@@ -0,0 +1,263 @@
#include "DebugComponent.h"
#include "../Constants.h"
namespace TLAC::Components
{
const char* GameStateNames[] =
{
"STARTUP",
"ADVERTISE",
"GAME",
"DATA_TEST",
"TEST_MODE",
"APP_ERROR",
"MAX",
};
const char* SubGameStateNames[] =
{
"DATA_INITIALIZE",
"SYSTEM_STARTUP",
"SYSTEM_STARTUP_ERROR",
"WARNING",
"LOGO",
"RATING",
"DEMO",
"TITLE",
"RANKING",
"SCORE_RANKING",
"CM",
"PHOTO_MODE_DEMO",
"SELECTOR",
"GAME_MAIN",
"GAME_SEL",
"STAGE_RESULT",
"SCREEN_SHOT_SEL",
"SCREEN_SHOT_RESULT",
"GAME_OVER",
"DATA_TEST_MAIN",
"DATA_TEST_MISC",
"DATA_TEST_OBJ",
"DATA_TEST_STG",
"DATA_TEST_MOT",
"DATA_TEST_COLLISION",
"DATA_TEST_SPR",
"DATA_TEST_AET",
"DATA_TEST_AUTH_3D",
"DATA_TEST_CHR",
"DATA_TEST_ITEM",
"DATA_TEST_PERF",
"DATA_TEST_PVSCRIPT",
"DATA_TEST_PRINT",
"DATA_TEST_CARD",
"DATA_TEST_OPD",
"DATA_TEST_SLIDER",
"DATA_TEST_GLITTER",
"DATA_TEST_GRAPHICS",
"DATA_TEST_COLLECTION_CARD",
"TEST_MODE_MAIN",
"APP_ERROR",
"MAX",
};
const char* DataTestNames[] =
{
"MAIN TEST",
"MISC TEST",
"OBJECT TEST",
"STAGE TEST",
"MOTION TEST",
"COLLISION TEST",
"SPRITE TEST",
"2DAUTH TEST",
"3DAUTH TEST",
"CHARA TEST",
"ITEM TEST",
"PERFORMANCE TEST",
"PVSCRIPT TEST",
"PRINT TEST",
"CARD TEST",
"OPD TEST",
"SLIDER TEST",
"GLITTER TEST",
"GRAPHICS TEST",
"COLLECTION CARD TEST",
};
typedef void ChangeGameState(GameState);
ChangeGameState* changeGameState = (ChangeGameState*)CHANGE_MODE_ADDRESS;
typedef void ChangeSubState(GameState, SubGameState);
ChangeSubState* changeSubState = (ChangeSubState*)CHANGE_SUB_MODE_ADDRESS;
DebugComponent::DebugComponent()
{
}
DebugComponent::~DebugComponent()
{
}
const char* DebugComponent::GetDisplayName()
{
return "debug_component";
}
void DebugComponent::Initialize(ComponentsManager*)
{
printf("[TLAC] DebugComponent::Initialize(): Initialized\n");
InjectPatches();
HWND consoleHandle = GetConsoleWindow();
ShowWindow(consoleHandle, SW_SHOW);
// In case the FrameRateManager isn't enabled
DWORD oldProtect;
VirtualProtect((void*)AET_FRAME_DURATION_ADDRESS, sizeof(float), PAGE_EXECUTE_READWRITE, &oldProtect);
}
void DebugComponent::Update()
{
if (dataTestMain)
{
Input::Keyboard::GetInstance()->PollInput();
UpdateDataTestMain();
}
}
void DebugComponent::UpdateInput()
{
auto keyboard = Input::Keyboard::GetInstance();
// fast forward menus
if (keyboard->IsDown(VK_SHIFT))
{
float* frameDuration = (float*)AET_FRAME_DURATION_ADDRESS;
if (keyboard->IsDown(VK_TAB))
*frameDuration = 1.0f / (GetGameFrameRate() / aetSpeedUpFactor);
else if (keyboard->IsReleased(VK_TAB))
*frameDuration = 1.0f / 60.0f;
}
for (size_t i = 0; i < _countof(gameStateKeyMappings); i++)
{
if (keyboard->IsTapped(gameStateKeyMappings[i].KeyCode))
InternalChangeGameState(gameStateKeyMappings[i].State);
}
}
void DebugComponent::InjectPatches()
{
const struct { void* Address; std::initializer_list<uint8_t> Data; } patches[] =
{
// Prevent the DATA_TEST game state from exiting on the first frame
{ (void*)0x0000000140284B01, { 0x00 } },
// Enable dw_gui sprite draw calls
{ (void*)0x0000000140192601, { 0x00 } },
// Update the dw_gui display
{ (void*)0x0000000140302600, { 0xB0, 0x01 } },
// Draw the dw_gui display
{ (void*)0x0000000140302610, { 0xB0, 0x01 } },
// Enable the dw_gui widgets
{ (void*)0x0000000140192D00, { 0xB8, 0x01, 0x00, 0x00, 0x00, 0xC3 } },
};
for (size_t i = 0; i < _countof(patches); i++)
InjectCode(patches[i].Address, patches[i].Data);
}
void DebugComponent::SetConsoleForeground()
{
HWND consoleHandle = GetConsoleWindow();
ShowWindow(consoleHandle, SW_SHOW);
if (consoleHandle == NULL)
return;
WINDOWPLACEMENT place = { sizeof(WINDOWPLACEMENT) };
GetWindowPlacement(consoleHandle, &place);
switch (place.showCmd)
{
case SW_SHOWMAXIMIZED:
ShowWindow(consoleHandle, SW_SHOWMAXIMIZED);
break;
case SW_SHOWMINIMIZED:
ShowWindow(consoleHandle, SW_RESTORE);
break;
default:
ShowWindow(consoleHandle, SW_NORMAL);
break;
}
SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
SetForegroundWindow(consoleHandle);
}
void DebugComponent::PrintDataTestMain()
{
system("cls");
printf(" DATA TEST MAIN:\n\n");
for (int i = SUB_DATA_TEST_MISC; i <= SUB_DATA_TEST_COLLECTION_CARD; i++)
printf("%s %s\n", i == selectionIndex ? "->" : " ", DataTestNames[i - SUB_DATA_TEST_MAIN]);
printf("\n");
SetConsoleForeground();
}
void DebugComponent::InternalChangeGameState(GameState state)
{
changeGameState(state);
printDataTestMain = dataTestMain = (state == GS_DATA_TEST);
}
void DebugComponent::UpdateDataTestMain()
{
auto keyboard = Input::Keyboard::GetInstance();
if (keyboard->IsIntervalTapped(VK_UP))
{
selectionIndex--;
printDataTestMain = true;
}
if (keyboard->IsIntervalTapped(VK_DOWN))
{
selectionIndex++;
printDataTestMain = true;
}
if (selectionIndex > SUB_DATA_TEST_COLLECTION_CARD)
selectionIndex = SUB_DATA_TEST_MISC;
if (selectionIndex < SUB_DATA_TEST_MISC)
selectionIndex = SUB_DATA_TEST_COLLECTION_CARD;
if (keyboard->IsTapped(VK_RETURN))
{
dataTestMain = false;
printf("[%s] -> [%s]\n", SubGameStateNames[SUB_DATA_TEST_MAIN], SubGameStateNames[selectionIndex]);
changeSubState(GS_DATA_TEST, (SubGameState)selectionIndex);
}
if (printDataTestMain)
{
PrintDataTestMain();
printDataTestMain = false;
}
}
void DebugComponent::InjectCode(void* address, const std::initializer_list<uint8_t> &data)
{
const size_t byteCount = data.size() * sizeof(uint8_t);
DWORD oldProtect;
VirtualProtect(address, byteCount, PAGE_EXECUTE_READWRITE, &oldProtect);
memcpy(address, data.begin(), byteCount);
}
}
@@ -0,0 +1,44 @@
#pragma once
#include "EmulatorComponent.h"
#include "GameState.h"
#include "../Input/Keyboard/Keyboard.h"
namespace TLAC::Components
{
class DebugComponent : public EmulatorComponent
{
public:
DebugComponent();
~DebugComponent();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
virtual void UpdateInput() override;
private:
const float aetSpeedUpFactor = 4.0f;
bool dataTestMain = false;
bool printDataTestMain = false;
int selectionIndex = SUB_DATA_TEST_MISC;
const struct { BYTE KeyCode; GameState State; } gameStateKeyMappings[5] =
{
{ VK_F4, GS_ADVERTISE },
{ VK_F5, GS_GAME },
{ VK_F6, GS_DATA_TEST },
{ VK_F7, GS_TEST_MODE },
{ VK_F8, GS_APP_ERROR },
};
void InjectPatches();
void SetConsoleForeground();
void PrintDataTestMain();
void InternalChangeGameState(GameState state);
void UpdateDataTestMain();
void InjectCode(void* address, const std::initializer_list<uint8_t> &data);
};
}
@@ -0,0 +1,33 @@
#include "EmulatorComponent.h"
#include "../Constants.h"
namespace TLAC::Components
{
EmulatorComponent::EmulatorComponent()
{
}
EmulatorComponent::~EmulatorComponent()
{
}
void EmulatorComponent::SetElapsedTime(float value)
{
elapsedTime = value;
}
float EmulatorComponent::GetElapsedTime()
{
return elapsedTime == 0.0f ? (1000.0f / 60.0f) : elapsedTime;
}
float EmulatorComponent::GetFrameRate()
{
return 1000.0f / GetElapsedTime();
}
float EmulatorComponent::GetGameFrameRate()
{
return *(float*)FRAME_RATE_ADDRESS;
}
}
@@ -0,0 +1,30 @@
#pragma once
namespace TLAC::Components
{
class ComponentsManager;
class EmulatorComponent
{
public:
EmulatorComponent();
~EmulatorComponent();
virtual const char* GetDisplayName() = 0;
virtual void Initialize(ComponentsManager*) = 0;
virtual void Update() = 0;
virtual void UpdateInput() {};
virtual void OnFocusGain() {};
virtual void OnFocusLost() {};
void SetElapsedTime(float value);
float GetElapsedTime();
float GetFrameRate();
float GetGameFrameRate();
private:
float elapsedTime;
};
}
@@ -0,0 +1,67 @@
#include "FPSLimiter.h"
#include <Windows.h>
#include <chrono>
#include <thread>
#include <cmath>
#include <cstdio>
#include <tchar.h>
using dsec = std::chrono::duration<double>;
using seconds = std::chrono::seconds;
// this is pretty much just lybxlpsv's limiter, but removed from GLComponent
namespace TLAC::Components
{
using namespace std::chrono;
static std::chrono::time_point mBeginFrame = system_clock::now();
static std::chrono::time_point prevTimeInSeconds = time_point_cast<seconds>(mBeginFrame);
const LPCTSTR config_file_name = _T(".\\config.ini");
int fpsLimit = GetPrivateProfileIntW(L"graphics", L"fps.limit", 0, config_file_name);
FPSLimiter::FPSLimiter()
{
}
FPSLimiter::~FPSLimiter()
{
}
const char* FPSLimiter::GetDisplayName()
{
return "fps_limiter";
}
void FPSLimiter::Initialize(ComponentsManager* manager)
{
mBeginFrame = std::chrono::system_clock::now();
prevTimeInSeconds = std::chrono::time_point_cast<seconds>(mBeginFrame);
frameCountPerSecond = 0;
if(fpsLimit != 0)
printf("FPSLimiter fpsLimit: %d\n", fpsLimit);
}
// I assume this gets called once per frame... if not this won't work
void FPSLimiter::Update()
{
auto invFpsLimit = round<std::chrono::system_clock::duration>(dsec{ 1. / fpsLimit });
auto mEndFrame = mBeginFrame + invFpsLimit;
auto timeInSeconds = std::chrono::time_point_cast<seconds>(std::chrono::system_clock::now());
++frameCountPerSecond;
if (timeInSeconds > prevTimeInSeconds)
{
//printf("FPSLimiter::Update(): FPS: %d\n", frameCountPerSecond);
frameCountPerSecond = 0;
prevTimeInSeconds = timeInSeconds;
}
// This part keeps the frame rate.
if (fpsLimit > 19) // not sure why lyb used 19 here
std::this_thread::sleep_until(mEndFrame);
mBeginFrame = mEndFrame;
mEndFrame = mBeginFrame + invFpsLimit;
}
}
@@ -0,0 +1,23 @@
#pragma once
#include "EmulatorComponent.h"
#include <chrono>
using seconds = std::chrono::seconds;
namespace TLAC::Components
{
class FPSLimiter : public EmulatorComponent
{
public:
FPSLimiter();
~FPSLimiter();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
private:
int frameCountPerSecond;
};
}
@@ -0,0 +1,60 @@
#include "FastLoader.h"
#include "../Constants.h"
#include <stdio.h>
namespace TLAC::Components
{
FastLoader::FastLoader()
{
}
FastLoader::~FastLoader()
{
}
const char* FastLoader::GetDisplayName()
{
return "fast_loader";
}
void FastLoader::Initialize(ComponentsManager*)
{
}
void FastLoader::Update()
{
if (dataInitialized)
return;
previousGameState = currentGameState;
currentGameState = *(GameState*)CURRENT_GAME_STATE_ADDRESS;
if (currentGameState == GS_STARTUP)
{
typedef void UpdateTask();
UpdateTask* updateTask = (UpdateTask*)UPDATE_TASKS_ADDRESS;
// speed up TaskSystemStartup
for (int i = 0; i < updatesPerFrame; i++)
updateTask();
constexpr int DATA_INITIALIZED = 3;
// skip TaskDataInit
*(int*)(DATA_INIT_STATE_ADDRESS) = DATA_INITIALIZED;
// skip TaskWarning
*(int*)(SYSTEM_WARNING_ELAPSED_ADDRESS) = 3939;
}
else if (previousGameState == GS_STARTUP)
{
dataInitialized = true;
printf("[TLAC] FastLoader::Update(): Data Initialized\n");
}
}
void FastLoader::UpdateInput()
{
return;
}
}
@@ -0,0 +1,26 @@
#pragma once
#include "EmulatorComponent.h"
#include "GameState.h"
namespace TLAC::Components
{
class FastLoader : public EmulatorComponent
{
public:
FastLoader();
~FastLoader();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
virtual void UpdateInput() override;
private:
const int updatesPerFrame = 39;
GameState currentGameState;
GameState previousGameState;
bool dataInitialized = false;
};
}
@@ -0,0 +1,86 @@
#include "FrameRateManager.h"
#include "../Constants.h"
#include "GameState.h"
#include <stdio.h>
#include <windows.h>
#include "../framework.h"
namespace TLAC::Components
{
FrameRateManager::FrameRateManager()
{
}
FrameRateManager::~FrameRateManager()
{
}
const char* FrameRateManager::GetDisplayName()
{
return "frame_rate_manager";
}
void FrameRateManager::Initialize(ComponentsManager*)
{
pvFrameRate = (float*)PV_FRAME_RATE_ADDRESS;
frameSpeed = (float*)FRAME_SPEED_ADDRESS;
aetFrameDuration = (float*)AET_FRAME_DURATION_ADDRESS;
// The default is expected to be 1.0 / 60.0
defaultAetFrameDuration = *aetFrameDuration;
// This const variable is stored inside a data segment so we don't want to throw any access violations
DWORD oldProtect;
VirtualProtect((void*)AET_FRAME_DURATION_ADDRESS, sizeof(float), PAGE_EXECUTE_READWRITE, &oldProtect);
}
void FrameRateManager::Update()
{
float frameRate = 0.0f;
frameRate = RoundFrameRate(GetGameFrameRate());
*aetFrameDuration = 1.0f / frameRate;
*pvFrameRate = frameRate;
bool inGame = *(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME;
if (inGame)
{
// During the GAME state the frame rate will be handled by the PvFrameRate instead
constexpr float defaultFrameSpeed = 1.0f;
constexpr float defaultFrameRate = 60.0f;
// This PV struct creates a copy of the PvFrameRate & PvFrameSpeed during the loading screen
// so we'll make sure to keep updating it as well.
// Each new motion also creates its own copy of these values but keeping track of the active motions is annoying
// and they usually change multiple times per PV anyway so this should suffice for now
float* pvStructPvFrameRate = (float*)(0x0000000140CDD978 + 0x2BF98);
float* pvStructPvFrameSpeed = (float*)(0x0000000140CDD978 + 0x2BF9C);
*pvStructPvFrameRate = *pvFrameRate;
*pvStructPvFrameSpeed = (defaultFrameRate / *pvFrameRate);
*frameSpeed = defaultFrameSpeed;
}
else
{
*frameSpeed = *aetFrameDuration / defaultAetFrameDuration;
}
}
float FrameRateManager::RoundFrameRate(float frameRate)
{
constexpr float roundingThreshold = 4.0f;
for (int i = 0; i < sizeof(commonRefreshRates) / sizeof(float); i++)
{
float refreshRate = commonRefreshRates[i];
if (frameRate > refreshRate - roundingThreshold && frameRate < refreshRate + roundingThreshold)
frameRate = refreshRate;
}
return frameRate;
}
}
@@ -0,0 +1,34 @@
#pragma once
#include "EmulatorComponent.h"
namespace TLAC::Components
{
class FrameRateManager : public EmulatorComponent
{
public:
FrameRateManager();
~FrameRateManager();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
private:
float *pvFrameRate;
float *frameSpeed;
float *aetFrameDuration;
float defaultAetFrameDuration;
float commonRefreshRates[5]
{
60.0f,
75.0f,
120.0f,
144.0f,
240.0f,
};
float RoundFrameRate(float frameRate);
};
}
@@ -0,0 +1,62 @@
#pragma once
#include <stdint.h>
namespace TLAC::Components
{
enum GameState : uint32_t
{
GS_STARTUP,
GS_ADVERTISE,
GS_GAME,
GS_DATA_TEST,
GS_TEST_MODE,
GS_APP_ERROR,
GS_MAX,
};
enum SubGameState : uint32_t
{
SUB_DATA_INITIALIZE,
SUB_SYSTEM_STARTUP,
SUB_SYSTEM_STARTUP_ERROR,
SUB_WARNING,
SUB_LOGO,
SUB_RATING,
SUB_DEMO,
SUB_TITLE,
SUB_RANKING,
SUB_SCORE_RANKING,
SUB_CM,
SUB_PHOTO_MODE_DEMO,
SUB_SELECTOR,
SUB_GAME_MAIN,
SUB_GAME_SEL,
SUB_STAGE_RESULT,
SUB_SCREEN_SHOT_SEL,
SUB_SCREEN_SHOT_RESULT,
SUB_GAME_OVER,
SUB_DATA_TEST_MAIN,
SUB_DATA_TEST_MISC,
SUB_DATA_TEST_OBJ,
SUB_DATA_TEST_STG,
SUB_DATA_TEST_MOT,
SUB_DATA_TEST_COLLISION,
SUB_DATA_TEST_SPR,
SUB_DATA_TEST_AET,
SUB_DATA_TEST_AUTH_3D,
SUB_DATA_TEST_CHR,
SUB_DATA_TEST_ITEM,
SUB_DATA_TEST_PERF,
SUB_DATA_TEST_PVSCRIPT,
SUB_DATA_TEST_PRINT,
SUB_DATA_TEST_CARD,
SUB_DATA_TEST_OPD,
SUB_DATA_TEST_SLIDER,
SUB_DATA_TEST_GLITTER,
SUB_DATA_TEST_GRAPHICS,
SUB_DATA_TEST_COLLECTION_CARD,
SUB_TEST_MODE_MAIN,
SUB_APP_ERROR,
SUB_MAX,
};
}
@@ -0,0 +1,13 @@
#pragma once
namespace TLAC::Components
{
enum HoldState
{
HOLD_NONE,
HOLD_SANKAKU = 64,
HOLD_MARU = 128,
HOLD_BATSU = 256,
HOLD_SHIKAKU = 512,
};
}
@@ -0,0 +1,18 @@
#pragma once
namespace TLAC::Components
{
enum TargetHitStates
{
COOL,
FINE,
SAFE,
SAD,
COOL_WRONG, // unsure
FINE_WRONG, // unsure
SAFE_WRONG, // unsure
SAD_WRONG, // unsure
WORST,
NONE = 21,
};
}
@@ -0,0 +1,77 @@
#include "TargetInspector.h"
namespace TLAC::Components
{
bool TargetInspector::repressTbl[maxTargetSlots];
TargetInspector::TargetInspector()
{
}
TargetInspector::~TargetInspector()
{
}
void TargetInspector::Initialize(ComponentsManager*)
{
tgtTypePtr = (int*)TGT_TYPE_BASE_ADDRESS;
tgtHitStatePtr = (int*)TGT_HIT_STATE_BASE_ADDRESS;
tgtRemainingTimePtr = (float*)TGT_REMAINING_DURATION_BASE_ADDRESS;
}
void TargetInspector::Update()
{
GetTargetStates();
UpdateRepressTbl();
}
const char* TargetInspector::GetDisplayName()
{
return "target_inspector";
}
void TargetInspector::GetTargetStates()
{
for (int i = 0; i < maxTargetSlots; ++i)
{
tgtStates[i].tgtType = *((int*)((char*)tgtTypePtr + (i * offset)));
tgtStates[i].tgtHitState = *((int*)((char*)tgtHitStatePtr + (i * offset)));
tgtStates[i].tgtRemainingTime = *((float*)((char*)tgtRemainingTimePtr + (i * offset)));
}
}
void TargetInspector::UpdateRepressTbl()
{
for (int i = 0; i < maxTargetSlots; ++i)
{
repressTbl[i] = IsWithinRange(tgtStates[i].tgtRemainingTime)
&& HasNotBeenHit(tgtStates[i].tgtHitState)
&& !IsSlide(tgtStates[i].tgtType);
}
}
bool TargetInspector::IsWithinRange(float time)
{
return time < timingThreshold && time > -timingThreshold && time != 0;
}
bool TargetInspector::HasNotBeenHit(int hitState)
{
return hitState == NONE;
}
bool TargetInspector::IsSlide(int type)
{
return (type >= SLIDE_L && type <= SLIDE_LONG_R) || type >= SLIDE_L_CH;
}
bool TargetInspector::IsAnyRepress()
{
for (int i = 0; i < maxTargetSlots; ++i)
{
if (repressTbl[i])
return true;
}
return false;
}
}
@@ -0,0 +1,43 @@
#pragma once
#include "../EmulatorComponent.h"
#include "../Input/InputEmulator.h"
#include "../../Constants.h"
#include "TargetHitStates.h"
#include "TargetState.h"
namespace TLAC::Components
{
const int maxTargetSlots = 32;
class TargetInspector : public EmulatorComponent
{
public:
TargetInspector();
~TargetInspector();
static bool repressTbl[maxTargetSlots];
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
virtual const char* GetDisplayName() override;
void GetTargetStates();
static bool IsAnyRepress();
private:
const uint64_t offset = 0x4A8;
const float timingThreshold = 0.13f; // PS4 estimate
TargetState tgtStates[maxTargetSlots];
int* tgtTypePtr;
int* tgtHitStatePtr;
float* tgtRemainingTimePtr;
bool IsSlide(int);
bool IsWithinRange(float);
bool HasNotBeenHit(int);
void UpdateRepressTbl();
};
}
@@ -0,0 +1,11 @@
#pragma once
namespace TLAC::Components
{
struct TargetState
{
int tgtType;
int tgtHitState;
float tgtRemainingTime;
};
}
@@ -0,0 +1,26 @@
#pragma once
namespace TLAC::Components
{
enum TargetTypes
{
SANKAKU,
MARU,
BATSU,
SHIKAKU,
SANKAKU_H,
MARU_H,
BATSU_H,
SHIKAKU_H,
SLIDE_L = 12,
SLIDE_R,
SLIDE_LONG_L = 15,
SLIDE_LONG_R,
SANKAKU_CH = 18,
MARU_CH,
BATSU_CH,
SHIKAKU_CH,
SLIDE_L_CH = 23,
SLIDE_R_CH,
};
}
@@ -0,0 +1,14 @@
#pragma once
namespace TLAC::Components
{
enum InputBufferType
{
InputBufferType_Tapped,
InputBufferType_Released,
InputBufferType_Down,
InputBufferType_DoubleTapped,
InputBufferType_IntervalTapped,
InputBufferType_Max,
};
}
@@ -0,0 +1,308 @@
#include <iostream>
#include "windows.h"
#include "InputEmulator.h"
#include "../ComponentsManager.h"
#include "../../Constants.h"
#include "../../framework.h"
#include "../../Input/Bindings/KeyboardBinding.h"
#include "../../Input/Bindings/XinputBinding.h"
#include "../../Input/Bindings/MouseBinding.h"
#include "../../Input/Bindings/Ds4Binding.h"
#include "../../Input/KeyConfig/Config.h"
#include "../../Utilities/Operations.h"
#include "../../Utilities/EnumBitwiseOperations.h"
#include "../../FileSystem/ConfigFile.h"
const std::string KEY_CONFIG_FILE_NAME = "keyconfig.ini";
using namespace TLAC::Input;
using namespace TLAC::Input::KeyConfig;
using namespace TLAC::Utilities;
namespace TLAC::Components
{
InputEmulator::InputEmulator()
{
}
InputEmulator::~InputEmulator()
{
delete TestBinding;
delete ServiceBinding;
delete StartBinding;
delete SankakuBinding;
delete ShikakuBinding;
delete BatsuBinding;
delete MaruBinding;
delete LeftBinding;
delete RightBinding;
}
const char* InputEmulator::GetDisplayName()
{
return "input_emulator";
}
void InputEmulator::Initialize(ComponentsManager* manager)
{
componentsManager = manager;
componentsManager->SetIsInputEmulatorUsed(true);
inputState = GetInputStatePtr((void*)INPUT_STATE_PTR_ADDRESS);
inputState->HideCursor();
TestBinding = new Binding();
ServiceBinding = new Binding();
StartBinding = new Binding();
SankakuBinding = new Binding();
ShikakuBinding = new Binding();
BatsuBinding = new Binding();
MaruBinding = new Binding();
LeftBinding = new Binding();
RightBinding = new Binding();
FileSystem::ConfigFile configFile(framework::GetModuleDirectory(), KEY_CONFIG_FILE_NAME);
configFile.OpenRead();
Config::BindConfigKeys(configFile.ConfigMap, "JVS_TEST", *TestBinding, { "F1" });
Config::BindConfigKeys(configFile.ConfigMap, "JVS_SERVICE", *ServiceBinding, { "F2" });
Config::BindConfigKeys(configFile.ConfigMap, "JVS_START", *StartBinding, { "Enter" });
Config::BindConfigKeys(configFile.ConfigMap, "JVS_TRIANGLE", *SankakuBinding, { "W", "I" });
Config::BindConfigKeys(configFile.ConfigMap, "JVS_SQUARE", *ShikakuBinding, { "A", "J" });
Config::BindConfigKeys(configFile.ConfigMap, "JVS_CROSS", *BatsuBinding, { "S", "K" });
Config::BindConfigKeys(configFile.ConfigMap, "JVS_CIRCLE", *MaruBinding, { "D", "L" });
Config::BindConfigKeys(configFile.ConfigMap, "JVS_LEFT", *LeftBinding, { "Q", "U" });
Config::BindConfigKeys(configFile.ConfigMap, "JVS_RIGHT", *RightBinding, { "E", "O" });
mouseScrollPvSelection = configFile.GetBooleanValue("mouse_scroll_pv_selection");
}
void InputEmulator::Update()
{
return;
}
void InputEmulator::OnFocusLost()
{
// to prevent buttons from being "stuck"
inputState->ClearState();
inputState->HideCursor();
}
void InputEmulator::UpdateInput()
{
if (!componentsManager->GetUpdateGameInput())
return;
if (!componentsManager->IsDwGuiActive())
{
UpdateJvsInput();
if (mouseScrollPvSelection && !componentsManager->IsDwGuiHovered())
UpdateMousePvScroll();
}
UpdateDwGuiInput();
}
void InputEmulator::UpdateJvsInput()
{
auto tappedFunc = [](void* binding) { return ((Binding*)binding)->AnyTapped(); };
auto releasedFunc = [](void* binding) { return ((Binding*)binding)->AnyReleased(); };
auto downFunc = [](void* binding) { return ((Binding*)binding)->AnyDown(); };
lastDownState = inputState->Down.Buttons;
inputState->Tapped.Buttons = GetJvsButtonsState(tappedFunc);
inputState->Released.Buttons = GetJvsButtonsState(releasedFunc);
inputState->Down.Buttons = GetJvsButtonsState(downFunc);
inputState->DoubleTapped.Buttons = GetJvsButtonsState(tappedFunc);
inputState->IntervalTapped.Buttons = GetJvsButtonsState(tappedFunc);
UpdateHoldState();
heldButtons = GetButtonFromHold();
if ((lastDownState &= inputState->Tapped.Buttons) != 0)
{
inputState->Down.Buttons ^= inputState->Tapped.Buttons;
if (IsHold() && !TargetInspector::IsAnyRepress())
inputState->Down.Buttons |= heldButtons;
}
// repress held down buttons to not block input
//inputState->Down.Buttons ^= inputState->Tapped.Buttons;
}
HoldState InputEmulator::GetHoldState()
{
return (HoldState) * ((int*)HOLD_STATE_ADDRESS);
}
int InputEmulator::GetMaxHoldState()
{
return *(int*)MAX_HOLD_STATE_ADDRESS;
}
bool InputEmulator::IsHold()
{
return ((holdState != HOLD_NONE) && (GetMaxHoldState() != 1));
}
void InputEmulator::UpdateHoldState()
{
holdState = GetHoldState();
for (int i = 0; i < 4; ++i)
{
int holdId = 1 << (i + 6);
if ((holdId & holdState) != 0)
holdTbl[i] = 1;
else
holdTbl[i] = 0;
}
}
void InputEmulator::UpdateDwGuiInput()
{
auto keyboard = Keyboard::GetInstance();
auto mouse = Mouse::GetInstance();
auto pos = mouse->GetRelativePosition();
inputState->MouseX = (int)pos.x;
inputState->MouseY = (int)pos.y;
auto deltaPos = mouse->GetDeltaPosition();
inputState->MouseDeltaX = (int)deltaPos.x;
inputState->MouseDeltaY = (int)deltaPos.y;
inputState->Key = GetKeyState();
for (int i = 0; i < sizeof(keyBits) / sizeof(KeyBit); i++)
UpdateInputBit(keyBits[i].Bit, keyBits[i].KeyCode);
for (int i = InputBufferType_Tapped; i < InputBufferType_Max; i++)
{
inputState->SetBit(scrollUpBit, mouse->GetIsScrolledUp(), (InputBufferType)i);
inputState->SetBit(scrollDownBit, mouse->GetIsScrolledDown(), (InputBufferType)i);
}
}
void InputEmulator::UpdateMousePvScroll()
{
// I originally wanted to use a MouseBinding set to JVS_LEFT / JVS_RIGHT
// but that ended up being too slow because a PV slot can only be scrolled to once the scroll animation has finished playing
int* slotsToScroll = (int*)PV_SEL_SLOTS_TO_SCROLL;
int* modulesToScroll = (int*)MODULE_SEL_SLOTS_TO_SCROLL;
auto mouse = Mouse::GetInstance();
if (mouse->GetIsScrolledUp())
{
if (*(int*)PV_SEL_SLOTS_CONST < 26) *slotsToScroll -= 1;
if (*(int*)MODULE_IS_RECOMMENDED == 0) *modulesToScroll -= 1;
}
if (mouse->GetIsScrolledDown())
{
if (*(int*)PV_SEL_SLOTS_CONST < 26) *slotsToScroll += 1;
if (*(int*)MODULE_IS_RECOMMENDED == 0) *modulesToScroll += 1;
}
}
InputState* InputEmulator::GetInputStatePtr(void* address)
{
return (InputState*)(*(uint64_t*)address);
}
JvsButtons InputEmulator::GetJvsButtonsState(bool(*buttonTestFunc)(void*))
{
JvsButtons buttons = JVS_NONE;
if (buttonTestFunc(TestBinding))
buttons |= JVS_TEST;
if (buttonTestFunc(ServiceBinding))
buttons |= JVS_SERVICE;
if (buttonTestFunc(StartBinding))
buttons |= JVS_START;
if (buttonTestFunc(SankakuBinding))
buttons |= JVS_TRIANGLE;
if (buttonTestFunc(ShikakuBinding))
buttons |= JVS_SQUARE;
if (buttonTestFunc(BatsuBinding))
buttons |= JVS_CROSS;
if (buttonTestFunc(MaruBinding))
buttons |= JVS_CIRCLE;
if (buttonTestFunc(LeftBinding))
buttons |= JVS_L;
if (buttonTestFunc(RightBinding))
buttons |= JVS_R;
return buttons;
}
JvsButtons InputEmulator::GetButtonFromHold()
{
JvsButtons buttons = JVS_NONE;
if (holdTbl[0])
buttons |= JVS_TRIANGLE;
if (holdTbl[1])
buttons |= JVS_CIRCLE;
if (holdTbl[2])
buttons |= JVS_CROSS;
if (holdTbl[3])
buttons |= JVS_SQUARE;
return buttons;
}
char InputEmulator::GetKeyState()
{
auto keyboard = Keyboard::GetInstance();
bool upper = keyboard->IsDown(VK_SHIFT);
constexpr char caseDifference = 'A' - 'a';
char inputKey = 0x00;
for (char key = '0'; key < 'Z'; key++)
{
if (keyboard->IsIntervalTapped(key))
inputKey = (upper || key < 'A') ? key : (key - caseDifference);
}
if (keyboard->IsIntervalTapped(VK_BACK))
inputKey = 0x08;
if (keyboard->IsIntervalTapped(VK_TAB))
inputKey = 0x09;
if (keyboard->IsIntervalTapped(VK_SPACE))
inputKey = 0x20;
if (keyboard->IsIntervalTapped(VK_ESCAPE))
exit(0);
return inputKey;
}
void InputEmulator::UpdateInputBit(uint32_t bit, uint8_t keycode)
{
auto keyboard = Keyboard::GetInstance();
inputState->SetBit(bit, keyboard->IsTapped(keycode), InputBufferType_Tapped);
inputState->SetBit(bit, keyboard->IsReleased(keycode), InputBufferType_Released);
inputState->SetBit(bit, keyboard->IsDown(keycode), InputBufferType_Down);
inputState->SetBit(bit, keyboard->IsDoubleTapped(keycode), InputBufferType_DoubleTapped);
inputState->SetBit(bit, keyboard->IsIntervalTapped(keycode), InputBufferType_IntervalTapped);
}
}
@@ -0,0 +1,102 @@
#pragma once
#include <functional>
#include <Windows.h>
#include "InputState.h"
#include "../EmulatorComponent.h"
#include "../../Input/Bindings/Binding.h"
#include "../GameTargets/TargetTypes.h"
#include "../GameTargets/TargetHitStates.h"
#include "../GameTargets/HoldState.h"
#include "../GameTargets/TargetInspector.h"
namespace TLAC::Components
{
struct KeyBit
{
uint32_t Bit;
uint8_t KeyCode;
};
class InputEmulator : public EmulatorComponent
{
public:
Input::Binding* TestBinding;
Input::Binding* ServiceBinding;
Input::Binding* StartBinding;
Input::Binding* SankakuBinding;
Input::Binding* ShikakuBinding;
Input::Binding* BatsuBinding;
Input::Binding* MaruBinding;
Input::Binding* LeftBinding;
Input::Binding* RightBinding;
InputEmulator();
~InputEmulator();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
virtual void UpdateInput() override;
virtual void OnFocusLost() override;
private:
ComponentsManager* componentsManager;
bool mouseScrollPvSelection = false;
const uint32_t scrollUpBit = 99;
const uint32_t scrollDownBit = 100;
KeyBit keyBits[20] =
{
{ 5, VK_LEFT },
{ 6, VK_RIGHT },
{ 29, VK_SPACE },
{ 39, 'A' },
{ 43, 'E' },
{ 42, 'D' },
{ 55, 'Q' },
{ 57, 'S' }, // unsure
{ 61, 'W' },
{ 63, 'Y' },
{ 84, 'L' }, // unsure
{ 80, VK_RETURN },
{ 81, VK_SHIFT },
{ 82, VK_CONTROL },
{ 83, VK_MENU },
{ 91, VK_UP },
{ 93, VK_DOWN },
{ 96, MK_LBUTTON },
{ 97, VK_MBUTTON },
{ 98, MK_RBUTTON },
};
InputState* inputState;
JvsButtons lastDownState;
JvsButtons heldButtons;
int holdTbl[4];
HoldState holdState;
void UpdateJvsInput();
void UpdateDwGuiInput();
void UpdateMousePvScroll();
void UpdateHoldState();
InputState* GetInputStatePtr(void* address);
JvsButtons GetJvsButtonsState(bool(*buttonTestFunc)(void*));
JvsButtons GetButtonFromHold();
char GetKeyState();
HoldState GetHoldState();
int GetMaxHoldState();
bool IsHold();
void UpdateInputBit(uint32_t bit, uint8_t keycode);
};
}
@@ -0,0 +1,58 @@
#include "InputState.h"
#include <windows.h>
#include <stdio.h>
namespace TLAC::Components
{
void InputState::ClearState()
{
memset(this, 0, sizeof(InputState));
}
void InputState::HideCursor()
{
MouseX = INT32_MIN;
MouseY = INT32_MIN;
MouseDeltaX = 0;
MouseDeltaY = 0;
}
void InputState::SetBit(uint32_t bit, bool value, InputBufferType inputType)
{
uint8_t* data = GetInputBuffer(inputType);
if (data == nullptr || bit < 0 || bit >= MAX_BUTTON_BIT)
return;
int byteIndex = (bit / 8);
int bitIndex = (bit % 8);
BYTE mask = (1 << bitIndex);
data[byteIndex] = value ? (data[byteIndex] | mask) : (data[byteIndex] & ~mask);
}
uint8_t* InputState::GetInputBuffer(InputBufferType inputType)
{
switch (inputType)
{
case InputBufferType_Tapped:
return (uint8_t*)&Tapped;
case InputBufferType_Released:
return (uint8_t*)&Released;
case InputBufferType_Down:
return (uint8_t*)&Down;
case InputBufferType_DoubleTapped:
return (uint8_t*)&DoubleTapped;
case InputBufferType_IntervalTapped:
return (uint8_t*)&IntervalTapped;
default:
return nullptr;
}
}
}
@@ -0,0 +1,47 @@
#pragma once
#include "JvsButtons.h"
#include "InputBufferType.h"
namespace TLAC::Components
{
const int MAX_BUTTON_BIT = 0x6F;
// The button state is larger than the size of a register
// but only the first 32 bits are used during normal gameplay
// so this will provide the convenience of still being able to access them through a bit field
union ButtonState
{
JvsButtons Buttons;
uint32_t State[4];
};
// total sizeof() == 0x20E0
struct InputState
{
ButtonState Tapped;
ButtonState Released;
ButtonState Down;
uint32_t Padding_20[4];
ButtonState DoubleTapped;
uint32_t Padding_30[4];
ButtonState IntervalTapped;
uint32_t Padding_38[12];
int32_t MouseX;
int32_t MouseY;
int32_t MouseDeltaX;
int32_t MouseDeltaY;
uint32_t Padding_AC[8];
uint8_t Padding_D0[3];
char Key;
void ClearState();
void HideCursor();
void SetBit(uint32_t bit, bool value, InputBufferType inputType);
uint8_t* GetInputBuffer(InputBufferType inputType);
};
}
@@ -0,0 +1,24 @@
#pragma once
#include <stdint.h>
namespace TLAC::Components
{
enum JvsButtons : uint32_t
{
JVS_NONE = 0 << 0x00, // 0x0
JVS_TEST = 1 << 0x00, // 0x1
JVS_SERVICE = 1 << 0x01, // 0x2
JVS_START = 1 << 0x02, // 0x4
JVS_TRIANGLE = 1 << 0x07, // 0x80
JVS_SQUARE = 1 << 0x08, // 0x100
JVS_CROSS = 1 << 0x09, // 0x200
JVS_CIRCLE = 1 << 0x0A, // 0x400
JVS_L = 1 << 0x0B, // 0x800
JVS_R = 1 << 0x0C, // 0x1000
JVS_SW1 = 1 << 0x12, // 0x40000
JVS_SW2 = 1 << 0x13, // 0x80000
};
}
@@ -0,0 +1,59 @@
#include "TouchPanelEmulator.h"
#include <iostream>
#include "../ComponentsManager.h"
#include "../../Constants.h"
#include "../../Input/Mouse/Mouse.h"
#include "../../Input/Keyboard/Keyboard.h"
using namespace TLAC::Input;
namespace TLAC::Components
{
TouchPanelEmulator::TouchPanelEmulator()
{
}
TouchPanelEmulator::~TouchPanelEmulator()
{
}
const char* TouchPanelEmulator::GetDisplayName()
{
return "touch_panel_emulator";
}
void TouchPanelEmulator::Initialize(ComponentsManager* manager)
{
componentsManager = manager;
state = GetTouchStatePtr((void*)TASK_TOUCH_ADDRESS);
}
void TouchPanelEmulator::Update()
{
state->ConnectionState = 1;
}
void TouchPanelEmulator::UpdateInput()
{
if (!componentsManager->GetUpdateGameInput() || componentsManager->IsDwGuiActive() || componentsManager->IsDwGuiHovered())
return;
// TODO: rescale TouchReaction aet position
auto keyboard = Keyboard::GetInstance();
auto pos = Mouse::GetInstance()->GetRelativePosition();
state->XPosition = (float)pos.x;
state->YPosition = (float)pos.y;
bool down = keyboard->IsDown(VK_LBUTTON);
bool released = keyboard->IsReleased(VK_LBUTTON);
state->ContactType = (down ? 0x2 : released ? 0x1 : 0x0);
state->Pressure = (float)(state->ContactType != 0);
}
TouchPanelState* TouchPanelEmulator::GetTouchStatePtr(void *address)
{
return (TouchPanelState*)address;
}
}
@@ -0,0 +1,26 @@
#pragma once
#include "../EmulatorComponent.h"
#include "TouchPanelState.h"
namespace TLAC::Components
{
class TouchPanelEmulator : public EmulatorComponent
{
public:
TouchPanelEmulator();
~TouchPanelEmulator();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
virtual void UpdateInput() override;
private:
ComponentsManager* componentsManager;
TouchPanelState* state;
TouchPanelState* GetTouchStatePtr(void *address);
};
}
@@ -0,0 +1,15 @@
#pragma once
namespace TLAC::Components
{
struct TouchPanelState
{
int Padding00[0x1E];
int ConnectionState;
int Padding01[0x06];
float XPosition;
float YPosition;
float Pressure;
int ContactType;
};
}
@@ -0,0 +1,138 @@
#include "TouchSliderEmulator.h"
#include "../ComponentsManager.h"
#include "../../Constants.h"
#include "../../framework.h"
#include "../../Input/Mouse/Mouse.h"
#include "../../Input/Keyboard/Keyboard.h"
#include "../../Input/Bindings/KeyboardBinding.h"
#include "../../Input/KeyConfig/Config.h"
#include "../../FileSystem/ConfigFile.h"
#include "../../Utilities/Math.h"
#include <algorithm>
#include <stdio.h>
using namespace TLAC::Input;
using namespace TLAC::Input::KeyConfig;
using namespace TLAC::Utilities;
namespace TLAC::Components
{
const std::string KEY_CONFIG_FILE_NAME = "keyconfig.ini";
TouchSliderEmulator::TouchSliderEmulator()
{
}
TouchSliderEmulator::~TouchSliderEmulator()
{
delete LeftSideSlideLeft;
delete LeftSideSlideRight;
delete RightSideSlideLeft;
delete RightSideSlideRight;
}
const char* TouchSliderEmulator::GetDisplayName()
{
return "touch_slider_emulator";
}
void TouchSliderEmulator::Initialize(ComponentsManager* manager)
{
componentsManager = manager;
sliderState = (TouchSliderState*)SLIDER_CTRL_TASK_ADDRESS;
LeftSideSlideLeft = new Binding();
LeftSideSlideRight = new Binding();
RightSideSlideLeft = new Binding();
RightSideSlideRight = new Binding();
FileSystem::ConfigFile configFile(framework::GetModuleDirectory(), KEY_CONFIG_FILE_NAME);
configFile.OpenRead();
Config::BindConfigKeys(configFile.ConfigMap, "LEFT_SIDE_SLIDE_LEFT", *LeftSideSlideLeft, { "Q" });
Config::BindConfigKeys(configFile.ConfigMap, "LEFT_SIDE_SLIDE_RIGHT", *LeftSideSlideRight, { "E" });
Config::BindConfigKeys(configFile.ConfigMap, "RIGHT_SIDE_SLIDE_LEFT", *RightSideSlideLeft, { "U" });
Config::BindConfigKeys(configFile.ConfigMap, "RIGHT_SIDE_SLIDE_RIGHT", *RightSideSlideRight, { "O" });
float touchSliderEmulationSpeed = configFile.GetFloatValue("touch_slider_emulation_speed");
if (touchSliderEmulationSpeed != 0.0f)
sliderSpeed = touchSliderEmulationSpeed;
}
void TouchSliderEmulator::Update()
{
sliderState->State = SLIDER_OK;
}
void TouchSliderEmulator::UpdateInput()
{
if (!componentsManager->GetUpdateGameInput() || componentsManager->IsDwGuiActive())
return;
sliderIncrement = GetElapsedTime() / sliderSpeed;
constexpr float sensorStep = (1.0f / SLIDER_SENSORS);
EmulateSliderInput(LeftSideSlideLeft, LeftSideSlideRight, ContactPoints[0], 0.0f, 0.5f);
EmulateSliderInput(RightSideSlideLeft, RightSideSlideRight, ContactPoints[1], 0.5f + sensorStep, 1.0f + sensorStep);
sliderState->ResetSensors();
for (int i = 0; i < CONTACT_POINTS; i++)
ApplyContactPoint(ContactPoints[i], i);
}
void TouchSliderEmulator::OnFocusLost()
{
sliderState->ResetSensors();
}
void TouchSliderEmulator::EmulateSliderInput(Binding *leftBinding, Binding *rightBinding, ContactPoint &contactPoint, float start, float end)
{
bool leftDown = leftBinding->AnyDown();
bool rightDown = rightBinding->AnyDown();
if (leftDown)
contactPoint.Position -= sliderIncrement;
else if (rightDown)
contactPoint.Position += sliderIncrement;
if (contactPoint.Position < start)
contactPoint.Position = end;
if (contactPoint.Position > end)
contactPoint.Position = start;
bool leftTapped = leftBinding->AnyTapped();
bool rightTapped = rightBinding->AnyTapped();
if (leftTapped || rightTapped)
contactPoint.Position = (start + end) / 2.0f;
contactPoint.InContact = leftDown || rightDown;
}
void TouchSliderEmulator::ApplyContactPoint(ContactPoint &contactPoint, int section)
{
sliderState->SectionTouched[section] = contactPoint.InContact;
int pressure = contactPoint.InContact ? FULL_PRESSURE : NO_PRESSURE;
float position = std::clamp(contactPoint.Position, 0.0f, 1.0f);
if (contactPoint.InContact)
{
int sensor = (int)(position * (SLIDER_SENSORS - 1));
sliderState->SetSensor(sensor, pressure);
}
constexpr float startRange = -1.0f;
constexpr float endRange = +1.0f;
sliderState->SectionPositions[section] = contactPoint.InContact ? (ConvertRange(0.0f, 1.0f, startRange, endRange, position)) : 0.0f;
}
}
@@ -0,0 +1,49 @@
#pragma once
#include "../EmulatorComponent.h"
#include "TouchSliderState.h"
#include "../../Input/Bindings/Binding.h"
namespace TLAC::Components
{
constexpr int SLIDER_INPUTS = 4;
constexpr int CONTACT_POINTS = 2;
struct ContactPoint
{
float Position;
bool InContact;
};
class TouchSliderEmulator : public EmulatorComponent
{
public:
Input::Binding* LeftSideSlideLeft;
Input::Binding* LeftSideSlideRight;
Input::Binding* RightSideSlideLeft;
Input::Binding* RightSideSlideRight;
TouchSliderEmulator();
~TouchSliderEmulator();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
virtual void UpdateInput() override;
virtual void OnFocusLost() override;
private:
ComponentsManager* componentsManager;
float sliderSpeed = 750.0f;
float sliderIncrement;
TouchSliderState *sliderState;
ContactPoint ContactPoints[CONTACT_POINTS];
void EmulateSliderInput(Input::Binding *leftBinding, Input::Binding *rightBinding, ContactPoint &contactPoint, float start, float end);
void ApplyContactPoint(ContactPoint &contactPoint, int section);
};
}
@@ -0,0 +1,19 @@
#include "TouchSliderState.h"
namespace TLAC::Components
{
void TouchSliderState::SetSensor(int index, int value)
{
if (index < 0 || index >= SLIDER_SENSORS)
return;
SensorPressureLevels[index] = value;
SensorTouched[index].IsTouched = value > 0;
}
void TouchSliderState::ResetSensors()
{
for (int i = 0; i < SLIDER_SENSORS; i++)
SetSensor(i, NO_PRESSURE);
}
}
@@ -0,0 +1,43 @@
#pragma once
#include <stdint.h>
#define SLIDER_OK 3
#define SLIDER_SECTIONS 4
#define SLIDER_SENSORS 32
#define NO_PRESSURE 0
#define FULL_PRESSURE 180
namespace TLAC::Components
{
struct TouchSliderState
{
uint8_t Padding0000[112];
int32_t State;
uint8_t Padding0074[20 + 12];
int32_t SensorPressureLevels[SLIDER_SENSORS];
uint8_t Padding0108[52 - 12];
float SectionPositions[SLIDER_SECTIONS];
int SectionConnections[SLIDER_SECTIONS];
uint8_t Padding015C[4];
bool SectionTouched[SLIDER_SECTIONS];
uint8_t Padding013C[3128 - 52 - 40];
struct
{
uint8_t Padding00[2];
bool IsTouched;
uint8_t Padding[45];
} SensorTouched[SLIDER_SENSORS];
void SetSensor(int index, int value);
void ResetSensors();
};
}
@@ -0,0 +1,973 @@
#pragma once
#include <stdint.h>
struct PlayerData
{
int8_t use_card;
int8_t freeplay;
int8_t field_2;
int8_t field_3;
int32_t card_type;
int32_t field_8;
int32_t field_C;
int32_t field_10;
int32_t field_14;
int32_t field_18;
int32_t field_1C;
int32_t field_20;
int32_t field_24;
int32_t field_28;
int32_t field_2C;
int32_t field_30;
int32_t field_34;
int32_t field_38;
int32_t field_3C;
int32_t field_40;
int32_t field_44;
int32_t field_48;
int32_t field_4C;
int32_t field_50;
int32_t field_54;
int32_t field_58;
int32_t field_5C;
int32_t field_60;
int32_t field_64;
int32_t field_68;
int32_t field_6C;
int32_t field_70;
int32_t field_74;
int32_t field_78;
int32_t field_7C;
int32_t field_80;
int32_t field_84;
int32_t field_88;
int32_t field_8C;
int32_t field_90;
int32_t field_94;
int32_t field_98;
int32_t field_9C;
int32_t field_A0;
int32_t field_A4;
int32_t field_A8;
int32_t field_AC;
int32_t field_B0;
int32_t field_B4;
int32_t field_B8;
int32_t field_BC;
int32_t field_C0;
int32_t field_C4;
int32_t field_C8;
int32_t field_CC;
int32_t play_data_id;
int32_t accept_index;
int32_t start_index;
int32_t field_DC;
char* player_name;
int32_t field_E8;
int32_t field_EC;
int32_t field_F0;
int32_t field_F4;
int32_t field_F8;
int32_t field_FC;
char* level_name;
int32_t field_108;
int32_t field_10C;
int32_t field_110;
int32_t field_114;
int32_t field_118;
int32_t field_11C;
int32_t field_120;
int32_t level_plate_id;
int32_t field_128;
int32_t vocaloid_point;
int32_t hp_vol;
int32_t act_toggle;
int32_t act_vol;
int32_t act_slide_vol;
int32_t field_140;
int32_t field_144;
int32_t field_148;
int32_t field_14C;
int32_t field_150;
int32_t field_154;
int32_t field_158;
int32_t field_15C;
int32_t field_160;
int32_t field_164;
int32_t field_168;
int32_t field_16C;
int32_t field_170;
int32_t field_174;
int32_t field_178;
int32_t field_17C;
int32_t field_180;
int32_t field_184;
int32_t field_188;
int32_t field_18C;
int32_t field_190;
int32_t field_194;
int32_t field_198;
int32_t field_19C;
int32_t field_1A0;
int32_t field_1A4;
int32_t field_1A8;
int32_t field_1AC;
int32_t field_1B0;
int32_t field_1B4;
int32_t field_1B8;
int32_t field_1BC;
int32_t field_1C0;
int32_t field_1C4;
int32_t field_1C8;
int32_t field_1CC;
int32_t field_1D0;
int32_t field_1D4;
int32_t field_1D8;
int32_t field_1DC;
int32_t field_1E0;
int32_t field_1E4;
int32_t field_1E8;
int32_t field_1EC;
int32_t field_1F0;
int32_t field_1F4;
int32_t field_1F8;
int32_t field_1FC;
int32_t field_200;
int32_t field_204;
int32_t field_208;
int32_t field_20C;
int32_t field_210;
int32_t field_214;
int32_t field_218;
int32_t field_21C;
int32_t field_220;
int32_t field_224;
int32_t field_228;
int32_t field_22C;
int32_t field_230;
int32_t field_234;
int32_t field_238;
int32_t field_23C;
int32_t field_240;
int32_t field_244;
int32_t field_248;
int32_t field_24C;
int32_t field_250;
int32_t field_254;
int32_t field_258;
int32_t field_25C;
int32_t field_260;
int32_t field_264;
int32_t field_268;
int32_t field_26C;
int32_t field_270;
int32_t field_274;
int32_t field_278;
int32_t field_27C;
int32_t field_280;
int32_t field_284;
int32_t field_288;
int32_t field_28C;
int32_t field_290;
int32_t field_294;
int32_t field_298;
int32_t field_29C;
int32_t field_2A0;
int32_t field_2A4;
int32_t field_2A8;
int32_t field_2AC;
int8_t use_pv_module_equip;
int8_t ch_pv_module_equip;
int8_t field_2B2;
int8_t field_2B3;
int32_t module_filter_kind;
int32_t field_2B8;
int32_t field_2BC;
int32_t field_2C0;
int32_t field_2C4;
int32_t field_2C8;
int32_t field_2CC;
int32_t field_2D0;
int32_t field_2D4;
int32_t field_2D8;
int32_t field_2DC;
int32_t field_2E0;
int32_t field_2E4;
int32_t field_2E8;
int32_t field_2EC;
int32_t field_2F0;
int32_t field_2F4;
int32_t field_2F8;
int32_t field_2FC;
int32_t field_300;
int32_t field_304;
int32_t field_308;
int32_t field_30C;
int32_t field_310;
int32_t field_314;
int32_t field_318;
int32_t field_31C;
int32_t field_320;
int32_t field_324;
int32_t field_328;
int32_t field_32C;
int32_t field_330;
int32_t field_334;
int32_t field_338;
int32_t field_33C;
int32_t field_340;
int32_t field_344;
int32_t field_348;
int32_t field_34C;
int32_t field_350;
int32_t field_354;
int32_t field_358;
int32_t field_35C;
int32_t field_360;
int32_t field_364;
int32_t field_368;
int32_t field_36C;
int32_t field_370;
int32_t field_374;
int32_t field_378;
int32_t field_37C;
int32_t field_380;
int32_t field_384;
int32_t field_388;
int32_t field_38C;
int32_t field_390;
int32_t field_394;
int32_t field_398;
int32_t field_39C;
int32_t field_3A0;
int32_t field_3A4;
int32_t field_3A8;
int32_t field_3AC;
int32_t field_3B0;
int32_t field_3B4;
int32_t field_3B8;
int32_t field_3BC;
int32_t field_3C0;
int32_t field_3C4;
int32_t field_3C8;
int32_t field_3CC;
int32_t field_3D0;
int32_t field_3D4;
int32_t field_3D8;
int32_t field_3DC;
int32_t field_3E0;
int32_t field_3E4;
int32_t field_3E8;
int32_t field_3EC;
int32_t field_3F0;
int32_t field_3F4;
int32_t field_3F8;
int32_t field_3FC;
int32_t field_400;
int32_t field_404;
int32_t field_408;
int32_t field_40C;
int32_t field_410;
int32_t field_414;
int32_t field_418;
int32_t field_41C;
int32_t field_420;
int32_t field_424;
int32_t field_428;
int32_t field_42C;
int32_t field_430;
int32_t field_434;
int32_t field_438;
int32_t field_43C;
int32_t field_440;
int32_t field_444;
int32_t field_448;
int32_t field_44C;
int32_t field_450;
int32_t field_454;
int32_t field_458;
int32_t field_45C;
int32_t field_460;
int32_t field_464;
int32_t field_468;
int32_t field_46C;
int32_t field_470;
int32_t field_474;
int32_t field_478;
int32_t field_47C;
int32_t field_480;
int32_t field_484;
int32_t field_488;
int32_t field_48C;
int32_t field_490;
int32_t field_494;
int32_t field_498;
int32_t field_49C;
int32_t field_4A0;
int32_t field_4A4;
int32_t field_4A8;
int32_t field_4AC;
int32_t field_4B0;
int32_t field_4B4;
int32_t field_4B8;
int32_t field_4BC;
int32_t field_4C0;
int32_t field_4C4;
int32_t field_4C8;
int32_t field_4CC;
int32_t field_4D0;
int32_t field_4D4;
int32_t field_4D8;
int32_t field_4DC;
int32_t field_4E0;
int32_t field_4E4;
int32_t field_4E8;
int32_t field_4EC;
int32_t field_4F0;
int32_t field_4F4;
int32_t field_4F8;
int32_t field_4FC;
int32_t field_500;
int32_t field_504;
int32_t field_508;
int32_t field_50C;
int32_t field_510;
int32_t field_514;
int32_t field_518;
int32_t field_51C;
int32_t field_520;
int32_t field_524;
int32_t field_528;
int32_t field_52C;
int32_t field_530;
int32_t field_534;
int32_t field_538;
int32_t field_53C;
int32_t field_540;
int32_t field_544;
int32_t skin_equip;
int32_t skin_equip_cmn;
int32_t use_pv_skin_equip;
int32_t btn_se_equip;
int32_t btn_se_equip_cmn;
int32_t use_pv_btn_se_equip;
int32_t slide_se_equip;
int32_t slide_se_equip_cmn;
int32_t use_pv_slide_se_equip;
int32_t chainslide_se_equip;
int32_t chainslide_se_equip_cmn;
int32_t use_pv_chainslide_se_equip;
int32_t slidertouch_se_equip;
int32_t slidertouch_se_equip_cmn;
int32_t use_pv_slidertouch_se_equip;
int32_t field_584;
int32_t field_588;
int32_t field_58C;
int32_t field_590;
int32_t field_594;
int32_t field_598;
int32_t field_59C;
int32_t field_5A0;
int32_t field_5A4;
int32_t field_5A8;
int32_t field_5AC;
int32_t field_5B0;
int32_t field_5B4;
int32_t field_5B8;
int32_t field_5BC;
int32_t field_5C0;
int32_t field_5C4;
int32_t field_5C8;
int32_t field_5CC;
int32_t field_5D0;
int32_t field_5D4;
int32_t field_5D8;
int32_t field_5DC;
int32_t field_5E0;
int32_t field_5E4;
int32_t field_5E8;
int32_t field_5EC;
int32_t field_5F0;
int32_t field_5F4;
int32_t field_5F8;
int32_t field_5FC;
int32_t field_600;
int32_t field_604;
int32_t field_608;
int32_t field_60C;
int32_t field_610;
int32_t field_614;
int32_t field_618;
int32_t field_61C;
int32_t field_620;
int32_t field_624;
int32_t field_628;
int32_t field_62C;
int32_t field_630;
int32_t field_634;
int32_t field_638;
int32_t field_63C;
int32_t field_640;
int32_t field_644;
int32_t field_648;
int32_t field_64C;
int32_t field_650;
int32_t field_654;
int32_t field_658;
int32_t field_65C;
int32_t field_660;
int32_t field_664;
int32_t field_668;
int32_t field_66C;
int32_t field_670;
int32_t field_674;
int32_t field_678;
int32_t field_67C;
int32_t field_680;
int32_t field_684;
int32_t field_688;
int32_t field_68C;
int32_t field_690;
int32_t field_694;
int32_t field_698;
int32_t field_69C;
int32_t field_6A0;
int32_t field_6A4;
int32_t field_6A8;
int32_t field_6AC;
int32_t field_6B0;
int32_t field_6B4;
int32_t field_6B8;
int32_t field_6BC;
int32_t field_6C0;
int32_t field_6C4;
int32_t field_6C8;
int32_t field_6CC;
int32_t field_6D0;
int32_t field_6D4;
int32_t field_6D8;
int32_t field_6DC;
int32_t field_6E0;
int32_t field_6E4;
int32_t field_6E8;
int32_t field_6EC;
int32_t field_6F0;
int32_t field_6F4;
int32_t field_6F8;
int32_t field_6FC;
int32_t field_700;
int32_t field_704;
int32_t field_708;
int32_t field_70C;
int32_t field_710;
int32_t field_714;
int32_t field_718;
int32_t field_71C;
int32_t field_720;
int32_t field_724;
int32_t field_728;
int32_t field_72C;
int32_t field_730;
int32_t field_734;
int32_t field_738;
int32_t field_73C;
int32_t field_740;
int32_t field_744;
int32_t field_748;
int32_t field_74C;
int32_t field_750;
int32_t field_754;
int32_t field_758;
int32_t field_75C;
int32_t field_760;
int32_t field_764;
int32_t field_768;
int32_t field_76C;
int32_t field_770;
int32_t field_774;
int32_t field_778;
int32_t field_77C;
int32_t field_780;
int32_t field_784;
int32_t field_788;
int32_t field_78C;
int32_t field_790;
int32_t field_794;
int32_t field_798;
int32_t field_79C;
int32_t field_7A0;
int32_t field_7A4;
int32_t field_7A8;
int32_t field_7AC;
int32_t field_7B0;
int32_t field_7B4;
int32_t field_7B8;
int32_t field_7BC;
int32_t field_7C0;
int32_t field_7C4;
int32_t field_7C8;
int32_t field_7CC;
int32_t field_7D0;
int32_t field_7D4;
int32_t field_7D8;
int32_t field_7DC;
int32_t field_7E0;
int32_t field_7E4;
int32_t field_7E8;
int32_t field_7EC;
int32_t field_7F0;
int32_t field_7F4;
int32_t field_7F8;
int32_t field_7FC;
int32_t field_800;
int32_t field_804;
int32_t field_808;
int32_t field_80C;
int32_t field_810;
int32_t field_814;
int32_t field_818;
int32_t field_81C;
int32_t field_820;
int32_t field_824;
int32_t field_828;
int32_t field_82C;
int32_t field_830;
int32_t field_834;
int32_t field_838;
int32_t field_83C;
int32_t field_840;
int32_t field_844;
int32_t field_848;
int32_t field_84C;
int32_t field_850;
int32_t field_854;
int32_t field_858;
int32_t field_85C;
int32_t field_860;
int32_t field_864;
int32_t field_868;
int32_t field_86C;
int32_t field_870;
int32_t field_874;
int32_t field_878;
int32_t field_87C;
int32_t field_880;
int32_t field_884;
int32_t field_888;
int32_t field_88C;
int32_t field_890;
int32_t field_894;
int32_t field_898;
int32_t field_89C;
int32_t field_8A0;
int32_t field_8A4;
int32_t field_8A8;
int32_t field_8AC;
int32_t field_8B0;
int32_t field_8B4;
int32_t field_8B8;
int32_t field_8BC;
int32_t field_8C0;
int32_t field_8C4;
int32_t field_8C8;
int32_t field_8CC;
int32_t field_8D0;
int32_t field_8D4;
int32_t field_8D8;
int32_t field_8DC;
int32_t field_8E0;
int32_t field_8E4;
int32_t field_8E8;
int32_t field_8EC;
int32_t field_8F0;
int32_t field_8F4;
int32_t field_8F8;
int32_t field_8FC;
int32_t field_900;
int32_t field_904;
int32_t field_908;
int32_t field_90C;
int32_t field_910;
int32_t field_914;
int32_t field_918;
int32_t field_91C;
int32_t field_920;
int32_t field_924;
int32_t field_928;
int32_t field_92C;
int32_t field_930;
int32_t field_934;
int32_t field_938;
int32_t field_93C;
int32_t field_940;
int32_t field_944;
int32_t field_948;
int32_t field_94C;
int32_t field_950;
int32_t field_954;
int32_t field_958;
int32_t field_95C;
int32_t field_960;
int32_t field_964;
int32_t field_968;
int32_t field_96C;
int32_t field_970;
int32_t field_974;
int32_t field_978;
int32_t field_97C;
int32_t field_980;
int32_t field_984;
int32_t field_988;
int32_t field_98C;
int32_t field_990;
int32_t field_994;
int32_t field_998;
int32_t field_99C;
int32_t field_9A0;
int32_t field_9A4;
int32_t field_9A8;
int32_t field_9AC;
int32_t field_9B0;
int32_t field_9B4;
int32_t field_9B8;
int32_t field_9BC;
int32_t field_9C0;
int32_t field_9C4;
int32_t field_9C8;
int32_t field_9CC;
int32_t field_9D0;
int32_t field_9D4;
int32_t field_9D8;
int32_t field_9DC;
int32_t field_9E0;
int32_t field_9E4;
int32_t field_9E8;
int32_t field_9EC;
int32_t field_9F0;
int32_t field_9F4;
int32_t field_9F8;
int32_t field_9FC;
int32_t field_A00;
int32_t field_A04;
int32_t field_A08;
int32_t field_A0C;
int32_t field_A10;
int32_t field_A14;
int32_t field_A18;
int32_t field_A1C;
int32_t field_A20;
int32_t field_A24;
int32_t field_A28;
int32_t field_A2C;
int32_t field_A30;
int32_t field_A34;
int32_t field_A38;
int32_t field_A3C;
int32_t field_A40;
int32_t field_A44;
int32_t field_A48;
int32_t field_A4C;
int32_t field_A50;
int32_t field_A54;
int32_t field_A58;
int32_t field_A5C;
int32_t field_A60;
int32_t field_A64;
int32_t field_A68;
int32_t field_A6C;
int32_t field_A70;
int32_t field_A74;
int32_t field_A78;
int32_t field_A7C;
int32_t field_A80;
int32_t field_A84;
int32_t field_A88;
int32_t field_A8C;
int32_t field_A90;
int32_t field_A94;
int32_t field_A98;
int32_t field_A9C;
int32_t field_AA0;
int32_t field_AA4;
int32_t field_AA8;
int32_t field_AAC;
int32_t field_AB0;
int32_t field_AB4;
int32_t field_AB8;
int32_t field_ABC;
int32_t field_AC0;
int32_t field_AC4;
int32_t field_AC8;
int32_t field_ACC;
int32_t field_AD0;
int32_t field_AD4;
int32_t field_AD8;
int32_t field_ADC;
int32_t field_AE0;
int32_t field_AE4;
int32_t field_AE8;
int32_t field_AEC;
int32_t field_AF0;
int32_t field_AF4;
int32_t field_AF8;
int32_t field_AFC;
int32_t field_B00;
int32_t field_B04;
int32_t field_B08;
int32_t field_B0C;
int32_t field_B10;
int32_t field_B14;
int32_t field_B18;
int32_t field_B1C;
int32_t field_B20;
int32_t field_B24;
int32_t field_B28;
int32_t field_B2C;
int32_t field_B30;
int32_t field_B34;
int32_t field_B38;
int32_t field_B3C;
int32_t field_B40;
int32_t field_B44;
int32_t field_B48;
int32_t field_B4C;
int32_t field_B50;
int32_t field_B54;
int32_t field_B58;
int32_t field_B5C;
int32_t field_B60;
int32_t field_B64;
int32_t field_B68;
int32_t field_B6C;
int32_t field_B70;
int32_t field_B74;
int32_t field_B78;
int32_t field_B7C;
int32_t field_B80;
int32_t field_B84;
int32_t field_B88;
int32_t field_B8C;
int32_t field_B90;
int32_t field_B94;
int32_t field_B98;
int32_t field_B9C;
int32_t field_BA0;
int32_t field_BA4;
int32_t field_BA8;
int32_t field_BAC;
int32_t field_BB0;
int32_t field_BB4;
int32_t field_BB8;
int32_t field_BBC;
int32_t field_BC0;
int32_t field_BC4;
int32_t field_BC8;
int32_t field_BCC;
int32_t field_BD0;
int32_t field_BD4;
int32_t field_BD8;
int32_t field_BDC;
int32_t field_BE0;
int32_t field_BE4;
int32_t field_BE8;
int32_t field_BEC;
int32_t field_BF0;
int32_t field_BF4;
int32_t field_BF8;
int32_t field_BFC;
int32_t field_C00;
int32_t field_C04;
int32_t field_C08;
int32_t field_C0C;
int32_t field_C10;
int32_t field_C14;
int32_t field_C18;
int32_t field_C1C;
int32_t field_C20;
int32_t field_C24;
int32_t field_C28;
int32_t field_C2C;
int32_t field_C30;
int32_t field_C34;
int32_t field_C38;
int32_t field_C3C;
int32_t field_C40;
int32_t field_C44;
int32_t field_C48;
int32_t field_C4C;
int32_t field_C50;
int32_t field_C54;
int32_t field_C58;
int32_t field_C5C;
int32_t field_C60;
int32_t field_C64;
int32_t field_C68;
int32_t field_C6C;
int32_t field_C70;
int32_t field_C74;
int32_t field_C78;
int32_t field_C7C;
int32_t field_C80;
int32_t field_C84;
int32_t field_C88;
int32_t field_C8C;
int32_t field_C90;
int32_t field_C94;
int32_t field_C98;
int32_t field_C9C;
int32_t field_CA0;
int32_t field_CA4;
int32_t field_CA8;
int32_t field_CAC;
int32_t field_CB0;
int32_t field_CB4;
int32_t field_CB8;
int32_t field_CBC;
int32_t field_CC0;
int32_t field_CC4;
int32_t field_CC8;
int32_t field_CCC;
int32_t field_CD0;
int32_t field_CD4;
int32_t field_CD8;
int32_t field_CDC;
int32_t field_CE0;
int32_t field_CE4;
int32_t field_CE8;
int32_t field_CEC;
int32_t field_CF0;
int32_t field_CF4;
int32_t field_CF8;
int32_t field_CFC;
int32_t field_D00;
int32_t field_D04;
int32_t field_D08;
int32_t field_D0C;
int32_t field_D10;
int32_t field_D14;
int32_t field_D18;
int32_t field_D1C;
int32_t field_D20;
int32_t field_D24;
int32_t field_D28;
int32_t field_D2C;
int32_t field_D30;
int32_t field_D34;
int32_t field_D38;
int32_t field_D3C;
int32_t field_D40;
int32_t field_D44;
int32_t field_D48;
int32_t field_D4C;
int32_t field_D50;
int32_t field_D54;
int32_t field_D58;
int32_t field_D5C;
int32_t field_D60;
int32_t field_D64;
int32_t field_D68;
int32_t field_D6C;
int32_t field_D70;
int32_t field_D74;
int32_t field_D78;
int32_t field_D7C;
int32_t field_D80;
int32_t field_D84;
int32_t field_D88;
int32_t field_D8C;
int32_t field_D90;
int32_t field_D94;
int32_t field_D98;
int32_t field_D9C;
int32_t field_DA0;
int32_t field_DA4;
int32_t field_DA8;
int32_t field_DAC;
int32_t field_DB0;
int32_t field_DB4;
int32_t field_DB8;
int32_t field_DBC;
int32_t field_DC0;
int32_t field_DC4;
int32_t field_DC8;
int32_t field_DCC;
int32_t field_DD0;
int32_t field_DD4;
int32_t field_DD8;
int32_t field_DDC;
int32_t field_DE0;
int32_t field_DE4;
int32_t field_DE8;
int32_t field_DEC;
int32_t field_DF0;
int32_t field_DF4;
int32_t field_DF8;
int32_t field_DFC;
int32_t field_E00;
int32_t field_E04;
int32_t field_E08;
int32_t field_E0C;
int32_t field_E10;
int32_t field_E14;
int32_t field_E18;
int32_t field_E1C;
int32_t field_E20;
int32_t field_E24;
int32_t field_E28;
int32_t field_E2C;
int32_t field_E30;
int8_t field_E34;
int8_t game_opts;
int8_t field_E36;
int8_t field_E37;
int32_t field_E38;
int32_t field_E3C;
int32_t field_E40;
int32_t field_E44;
int32_t field_E48;
int32_t field_E4C;
int32_t field_E50;
int32_t field_E54;
int32_t field_E58;
int32_t field_E5C;
int32_t field_E60;
int32_t field_E64;
int32_t field_E68;
int32_t field_E6C;
int32_t field_E70;
int32_t field_E74;
int32_t field_E78;
int32_t field_E7C;
int32_t field_E80;
int32_t field_E84;
int32_t field_E88;
int32_t field_E8C;
int32_t field_E90;
int32_t field_E94;
int32_t field_E98;
int32_t field_E9C;
int32_t field_EA0;
int32_t field_EA4;
int32_t field_EA8;
int32_t field_EAC;
int32_t field_EB0;
int32_t field_EB4;
int32_t field_EB8;
int32_t field_EBC;
int32_t field_EC0;
int32_t field_EC4;
int32_t field_EC8;
int32_t field_ECC;
int32_t field_ED0;
int32_t field_ED4;
int32_t field_ED8;
int32_t field_EDC;
int32_t field_EE0;
int32_t field_EE4;
int32_t field_EE8;
int32_t field_EEC;
int32_t field_EF0;
int32_t field_EF4;
int32_t field_EF8;
int32_t field_EFC;
};
@@ -0,0 +1,342 @@
#include "PlayerDataManager.h"
#include <string>
#include "../framework.h"
#include "../Constants.h"
#include "../Input/Keyboard/Keyboard.h"
#include "../FileSystem/ConfigFile.h"
#include "../Constants.h"
const std::string PLAYER_DATA_FILE_NAME = "playerdata.ini";
namespace TLAC::Components
{
PlayerDataManager::PlayerDataManager()
{
}
PlayerDataManager::~PlayerDataManager()
{
if (customPlayerData != nullptr)
delete customPlayerData;
}
const char* PlayerDataManager::GetDisplayName()
{
return "player_data_manager";
}
void PlayerDataManager::Initialize(ComponentsManager*)
{
playerData = (PlayerData*)PLAYER_DATA_ADDRESS;
ApplyPatch();
LoadConfig();
ApplyCustomData();
}
void PlayerDataManager::Update()
{
ApplyCustomData();
if (false && Input::Keyboard::GetInstance()->IsTapped(VK_F12))
{
printf("[TLAC] PlayerDataManager::Update(): Loading config...\n");
LoadConfig();
}
if (moduleCardWorkaround) {
int* pvId = (int*)0x00000001418054C4;
int* modState = (int*)0x00000001411A9790;
if (!customPlayerData->UseCard)
{
if (*(char*)0x000000014CC5E270 == 32)
{
DWORD oldProtect, bck;
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405BC8E6 + 0) = 0x00;
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, oldProtect, &bck);
pvModuleLoaded = false;
}
else {
if (!pvModuleLoaded)
{
pvModuleLoaded = true;
DWORD oldProtect, bck;
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405BC8E6 + 0) = 0x01;
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, oldProtect, &bck);
}
}
if ((initPvId == false) || ((lastModState == 0) && (*modState == 1)))
{
if ((lastModState == 0) && (*modState == 1))
{
*(int*)0x00000001411A8A10 = *(int*)0x00000001411A8A28;
*(int*)(0x00000001411A8A10 + 4) = *(int*)(0x00000001411A8A28 + 4);
*(int*)(0x00000001411A8A10 + 8) = *(int*)(0x00000001411A8A28 + 8);
*(int*)(0x00000001411A8A10 + 12) = *(int*)(0x00000001411A8A28 + 12);
*(int*)(0x00000001411A8A10 + 16) = *(int*)(0x00000001411A8A28 + 16);
*(int*)(0x00000001411A8A10 + 18) = *(int*)(0x00000001411A8A28 + 18);
}
initPvId = true;
lastModState = *modState;
DWORD oldProtect, bck;
VirtualProtect((BYTE*)0x00000001405CBBA3, 8, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405CBBA3 + 0) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 1) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 2) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 3) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 4) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 5) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 6) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 7) = 0x90;
VirtualProtect((BYTE*)0x00000001405CBBA3, 8, oldProtect, &bck);
}
if (((*modState == 0) && (*pvId != lastPvId)) || ((lastModState == 1) && (*modState == 0)))
{
if ((lastModState == 1) && (*modState == 0))
{
*(int*)0x00000001411A8A28 = *(int*)0x00000001411A8A10;
*(int*)(0x00000001411A8A28 + 4) = *(int*)(0x00000001411A8A10 + 4);
*(int*)(0x00000001411A8A28 + 8) = *(int*)(0x00000001411A8A10 + 8);
*(int*)(0x00000001411A8A28 + 12) = *(int*)(0x00000001411A8A10 + 12);
*(int*)(0x00000001411A8A28 + 16) = *(int*)(0x00000001411A8A10 + 16);
*(int*)(0x00000001411A8A28 + 18) = *(int*)(0x00000001411A8A10 + 18);
}
initPvId = false;
lastPvId = *pvId;
lastModState = *modState;
DWORD oldProtect, bck;
VirtualProtect((BYTE*)0x00000001405CBBA3, 8, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405CBBA3 + 0) = 0x42;
*((BYTE*)0x00000001405CBBA3 + 1) = 0x89;
*((BYTE*)0x00000001405CBBA3 + 2) = 0x84;
*((BYTE*)0x00000001405CBBA3 + 3) = 0xb6;
*((BYTE*)0x00000001405CBBA3 + 4) = 0xc0;
*((BYTE*)0x00000001405CBBA3 + 5) = 0x01;
*((BYTE*)0x00000001405CBBA3 + 6) = 0x00;
*((BYTE*)0x00000001405CBBA3 + 7) = 0x00;
VirtualProtect((BYTE*)0x00000001405CBBA3, 8, oldProtect, &bck);
}
}
else {
if (*(char*)0x000000014CC5E270 == 32)
{
DWORD oldProtect, bck;
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405BC8E6 + 0) = 0x01;
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, oldProtect, &bck);
VirtualProtect((BYTE*)0x00000001405CBBA3, 8, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405CBBA3 + 0) = 0x42;
*((BYTE*)0x00000001405CBBA3 + 1) = 0x89;
*((BYTE*)0x00000001405CBBA3 + 2) = 0x84;
*((BYTE*)0x00000001405CBBA3 + 3) = 0xb6;
*((BYTE*)0x00000001405CBBA3 + 4) = 0xc0;
*((BYTE*)0x00000001405CBBA3 + 5) = 0x01;
*((BYTE*)0x00000001405CBBA3 + 6) = 0x00;
*((BYTE*)0x00000001405CBBA3 + 7) = 0x00;
VirtualProtect((BYTE*)0x00000001405CBBA3, 8, oldProtect, &bck);
VirtualProtect((BYTE*)0x00000001405BCBE3, 2, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405BCBE3 + 0) = 0x00;
VirtualProtect((BYTE*)0x00000001405BCBE3, 2, oldProtect, &bck);
pvModuleLoaded = false;
}
else {
if (!pvModuleLoaded)
{
pvModuleLoaded = true;
DWORD oldProtect, bck;
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405BC8E6 + 0) = 0x00;
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, oldProtect, &bck);
VirtualProtect((BYTE*)0x00000001405CBBA3, 8, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405CBBA3 + 0) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 1) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 2) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 3) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 4) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 5) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 6) = 0x90;
*((BYTE*)0x00000001405CBBA3 + 7) = 0x90;
VirtualProtect((BYTE*)0x00000001405CBBA3, 8, oldProtect, &bck);
VirtualProtect((BYTE*)0x00000001405BCBE3, 2, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405BCBE3 + 0) = 0x01;
VirtualProtect((BYTE*)0x00000001405BCBE3, 2, oldProtect, &bck);
}
}
}
}
}
void PlayerDataManager::ApplyPatch()
{
DWORD oldProtect;
VirtualProtect((void*)SET_DEFAULT_PLAYER_DATA_ADDRESS, sizeof(uint8_t), PAGE_EXECUTE_READWRITE, &oldProtect);
{
// prevent the PlayerData from being reset
*(uint8_t*)(SET_DEFAULT_PLAYER_DATA_ADDRESS) = RET_OPCODE;
}
VirtualProtect((void*)SET_DEFAULT_PLAYER_DATA_ADDRESS, sizeof(uint8_t), oldProtect, &oldProtect);
// allow player to select the module and extra item
VirtualProtect((void*)MODSELECTOR_CHECK_FUNCTION_ERRRET_ADDRESS, sizeof(byte) * 2, PAGE_EXECUTE_READWRITE, &oldProtect);
{
*(byte*)(MODSELECTOR_CHECK_FUNCTION_ERRRET_ADDRESS) = 0xB0; // xor al,al -> ld al,1
*(byte*)(MODSELECTOR_CHECK_FUNCTION_ERRRET_ADDRESS + 0x1) = 0x01;
}
VirtualProtect((void*)MODSELECTOR_CHECK_FUNCTION_ERRRET_ADDRESS, sizeof(byte) * 2, oldProtect, &oldProtect);
// fix annoying behavior of closing after changing module or item (don't yet know the reason, maybe NW/Card checks)
{
VirtualProtect((void*)MODSELECTOR_CLOSE_AFTER_MODULE, sizeof(uint8_t), PAGE_EXECUTE_READWRITE, &oldProtect);
{
*(uint8_t*)(MODSELECTOR_CLOSE_AFTER_MODULE) = JNE_OPCODE;
}
VirtualProtect((void*)MODSELECTOR_CLOSE_AFTER_MODULE, sizeof(uint8_t), oldProtect, &oldProtect);
VirtualProtect((void*)MODSELECTOR_CLOSE_AFTER_CUSTOMIZE, sizeof(uint8_t), PAGE_EXECUTE_READWRITE, &oldProtect);
{
*(uint8_t*)(MODSELECTOR_CLOSE_AFTER_CUSTOMIZE) = JNE_OPCODE;
}
VirtualProtect((void*)MODSELECTOR_CLOSE_AFTER_CUSTOMIZE, sizeof(uint8_t), oldProtect, &oldProtect);
}
}
void PlayerDataManager::LoadConfig()
{
if (playerData == nullptr)
return;
FileSystem::ConfigFile config(framework::GetModuleDirectory(), PLAYER_DATA_FILE_NAME);
if (!config.OpenRead())
return;
if (customPlayerData != nullptr)
delete customPlayerData;
customPlayerData = new CustomPlayerData();
config.TryGetValue("player_name", &customPlayerData->PlayerName);
config.TryGetValue("level_name", &customPlayerData->LevelName);
customPlayerData->LevelPlateId = config.GetIntegerValue("level_plate_id");
customPlayerData->SkinEquip = config.GetIntegerValue("skin_equip");
customPlayerData->BtnSeEquip = config.GetIntegerValue("btn_se_equip");
customPlayerData->SlideSeEquip = config.GetIntegerValue("slide_se_equip");
customPlayerData->ChainslideSeEquip = config.GetIntegerValue("chainslide_se_equip");
customPlayerData->ShowExcellentClearBorder = config.GetBooleanValue("border_excellent");
customPlayerData->ShowGreatClearBorder = config.GetBooleanValue("border_great");
customPlayerData->UseCard = config.GetBooleanValue("use_card");
customPlayerData->GameModifierOptions = config.GetBooleanValue("gamemode_options");
moduleCardWorkaround = config.GetBooleanValue("module_card_workaround");
if (moduleCardWorkaround) {
if (!customPlayerData->UseCard)
{
DWORD oldProtect, bck;
VirtualProtect((BYTE*)0x000000014010523F, 3, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x0000000140105239 + 0) = 0x30;
*((BYTE*)0x0000000140105239 + 1) = 0xC0;
*((BYTE*)0x0000000140105239 + 2) = 0x90;
VirtualProtect((BYTE*)0x0000000140105239, 3, oldProtect, &bck);
VirtualProtect((BYTE*)0x00000001405BCC48, 6, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405BCC48 + 0) = 0x90;
*((BYTE*)0x00000001405BCC48 + 1) = 0x90;
*((BYTE*)0x00000001405BCC48 + 2) = 0x90;
*((BYTE*)0x00000001405BCC48 + 3) = 0x90;
*((BYTE*)0x00000001405BCC48 + 4) = 0x90;
*((BYTE*)0x00000001405BCC48 + 5) = 0x90;
VirtualProtect((BYTE*)0x00000001405BCC48, 6, oldProtect, &bck);
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405BC8E6 + 0) = 0x01;
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, oldProtect, &bck);
}
else {
DWORD oldProtect, bck;
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405BC8E6 + 0) = 0x00;
VirtualProtect((BYTE*)0x00000001405BC8E6, 3, oldProtect, &bck);
VirtualProtect((BYTE*)0x00000001405BCC48, 6, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405BCC48 + 0) = 0xC7;
*((BYTE*)0x00000001405BCC48 + 1) = 0x03;
*((BYTE*)0x00000001405BCC48 + 2) = 0x00;
*((BYTE*)0x00000001405BCC48 + 3) = 0x00;
*((BYTE*)0x00000001405BCC48 + 4) = 0x00;
*((BYTE*)0x00000001405BCC48 + 5) = 0x00;
VirtualProtect((BYTE*)0x00000001405BCC48, 6, oldProtect, &bck);
VirtualProtect((BYTE*)0x000000014010523F, 3, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x0000000140105239 + 0) = 0x0F;
*((BYTE*)0x0000000140105239 + 1) = 0x94;
*((BYTE*)0x0000000140105239 + 2) = 0xC1;
VirtualProtect((BYTE*)0x0000000140105239, 3, oldProtect, &bck);
//just incase the player is reloading
VirtualProtect((BYTE*)0x00000001405CBBA3, 8, PAGE_EXECUTE_READWRITE, &oldProtect);
*((BYTE*)0x00000001405CBBA3 + 0) = 0x42;
*((BYTE*)0x00000001405CBBA3 + 1) = 0x89;
*((BYTE*)0x00000001405CBBA3 + 2) = 0x84;
*((BYTE*)0x00000001405CBBA3 + 3) = 0xb6;
*((BYTE*)0x00000001405CBBA3 + 4) = 0xc0;
*((BYTE*)0x00000001405CBBA3 + 5) = 0x01;
*((BYTE*)0x00000001405CBBA3 + 6) = 0x00;
*((BYTE*)0x00000001405CBBA3 + 7) = 0x00;
VirtualProtect((BYTE*)0x00000001405CBBA3, 8, oldProtect, &bck);
}
}
}
void PlayerDataManager::ApplyCustomData()
{
// don't want to overwrite the default values
auto setIfNotEqual = [](int *target, int value, int comparison)
{
if (value != comparison)
*target = value;
};
setIfNotEqual(&playerData->level_plate_id, customPlayerData->LevelPlateId, 0);
setIfNotEqual(&playerData->skin_equip, customPlayerData->SkinEquip, 0);
setIfNotEqual(&playerData->btn_se_equip, customPlayerData->BtnSeEquip, -1);
setIfNotEqual(&playerData->slide_se_equip, customPlayerData->SlideSeEquip, -1);
setIfNotEqual(&playerData->chainslide_se_equip, customPlayerData->ChainslideSeEquip, -1);
// Display clear borders on the progress bar
*(byte*)(PLAYER_DATA_ADDRESS + 0xD94) = (customPlayerData->ShowExcellentClearBorder << 1) | (customPlayerData->ShowGreatClearBorder);
if (customPlayerData->UseCard)
playerData->use_card = 1; // required to allow for module selection
if (customPlayerData->GameModifierOptions)
playerData->game_opts = 1; // hi-speed, etc..
memset((void*)MODULE_TABLE_START, 0xFF, 128);
memset((void*)ITEM_TABLE_START, 0xFF, 128);
if (customPlayerData->PlayerName != nullptr)
{
playerData->field_DC = 0x10;
playerData->player_name = (char*)customPlayerData->PlayerName->c_str();
}
if (customPlayerData->LevelName != nullptr)
{
playerData->level_name = (char*)customPlayerData->LevelName->c_str();
playerData->field_110 = 0xFF;
playerData->field_118 = 0x1F;
}
}
}
@@ -0,0 +1,33 @@
#pragma once
#include "EmulatorComponent.h"
#include "PlayerData.h"
#include "CustomPlayerData.h"
#include <string>
namespace TLAC::Components
{
class PlayerDataManager : public EmulatorComponent
{
public:
PlayerDataManager();
~PlayerDataManager();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
private:
PlayerData* playerData;
CustomPlayerData* customPlayerData;
int lastPvId = -1;
bool initPvId = true;
bool pvModuleLoaded = true;
bool moduleCardWorkaround = true;
int lastModState = 0;
void ApplyPatch();
void LoadConfig();
void ApplyCustomData();
};
}
@@ -0,0 +1,109 @@
#include "ScaleComponent.h"
#include <iostream>
#include <Windows.h>
#include "../Constants.h"
#include <stdio.h>
#include "../framework.h"
#include <chrono>
#include <thread>
#include <tchar.h>
#include <GL/freeglut.h>
namespace TLAC::Components
{
ScaleComponent::ScaleComponent()
{
}
ScaleComponent::~ScaleComponent()
{
}
const char* ScaleComponent::GetDisplayName()
{
return "scale_component";
}
void ScaleComponent::Initialize(ComponentsManager*)
{
{
DWORD oldProtect, bck;
VirtualProtect((BYTE*)0x00000001404ACD24, 7, PAGE_EXECUTE_READWRITE, &oldProtect);
*((byte*)0x00000001404ACD24 + 0) = 0x44;
*((byte*)0x00000001404ACD24 + 1) = 0x8B;
*((byte*)0x00000001404ACD24 + 2) = 0x0D;
*((byte*)0x00000001404ACD24 + 3) = 0xD1;
*((byte*)0x00000001404ACD24 + 4) = 0x08;
*((byte*)0x00000001404ACD24 + 5) = 0xD0;
*((byte*)0x00000001404ACD24 + 6) = 0x00;
VirtualProtect((BYTE*)0x00000001404ACD24, 7, oldProtect, &bck);
}
{
DWORD oldProtect, bck;
VirtualProtect((BYTE*)0x00000001404ACD2B, 7, PAGE_EXECUTE_READWRITE, &oldProtect);
*((byte*)0x00000001404ACD2B + 0) = 0x44;
*((byte*)0x00000001404ACD2B + 1) = 0x8B;
*((byte*)0x00000001404ACD2B + 2) = 0x05;
*((byte*)0x00000001404ACD2B + 3) = 0xC6;
*((byte*)0x00000001404ACD2B + 4) = 0x08;
*((byte*)0x00000001404ACD2B + 5) = 0xD0;
*((byte*)0x00000001404ACD2B + 6) = 0x00;
VirtualProtect((BYTE*)0x00000001404ACD2B, 7, oldProtect, &bck);
}
{
DWORD oldProtect, bck;
VirtualProtect((BYTE*)0x00000001405030A0, 6, PAGE_EXECUTE_READWRITE, &oldProtect);
*((byte*)0x00000001405030A0 + 0) = 0x90;
*((byte*)0x00000001405030A0 + 1) = 0x90;
*((byte*)0x00000001405030A0 + 2) = 0x90;
*((byte*)0x00000001405030A0 + 3) = 0x90;
*((byte*)0x00000001405030A0 + 4) = 0x90;
*((byte*)0x00000001405030A0 + 5) = 0x90;
VirtualProtect((BYTE*)0x00000001404ACD2B, 6, oldProtect, &bck);
}
}
void ScaleComponent::Update()
{
uiAspectRatio = (float*)UI_ASPECT_RATIO;
uiWidth = (float*)UI_WIDTH_ADDRESS;
uiHeight = (float*)UI_HEIGHT_ADDRESS;
fb1Height = (int*)FB1_HEIGHT_ADDRESS;
fb1Width = (int*)FB1_WIDTH_ADDRESS;
//fb2Height = (int*)FB2_HEIGHT_ADDRESS;
//fb2Width = (int*)FB2_WIDTH_ADDRESS;
fbAspectRatio = (double*)FB_ASPECT_RATIO;
RECT hWindow;
GetClientRect(TLAC::framework::DivaWindowHandle, &hWindow);
*uiAspectRatio = (float)(hWindow.right - hWindow.left) / (float)(hWindow.bottom - hWindow.top);
*fbAspectRatio = (double)(hWindow.right - hWindow.left) / (double)(hWindow.bottom - hWindow.top);
*uiWidth = hWindow.right - hWindow.left;
*uiHeight = hWindow.bottom - hWindow.top;
*fb1Width = hWindow.right - hWindow.left;
*fb1Height = hWindow.bottom - hWindow.top;
//*fb2Width = hWindow.right - hWindow.left;
//*fb2Height = hWindow.bottom - hWindow.top;
*((int*)0x00000001411AD608) = 0;
*((int*)0x0000000140EDA8E4) = *(int*)0x0000000140EDA8BC;
*((int*)0x0000000140EDA8E8) = *(int*)0x0000000140EDA8C0;
*(float*)0x00000001411A1900 = 0;
*(float*)0x00000001411A1904 = (float)*(int*)0x0000000140EDA8BC;
*(float*)0x00000001411A1908 = (float)*(int*)0x0000000140EDA8C0;
//*((int*)0x00000001411AD5F8) = hWindow.right - hWindow.left;
//*((int*)0x00000001411AD5FC) = hWindow.bottom - hWindow.top;
//*((int*)0x00000001411ABB48) = hWindow.right - hWindow.left;
//*((int*)0x00000001411ABB4C) = hWindow.bottom - hWindow.top;
//*((int*)0x00000001411ABB5C) = (int)(*((int*)0x00000001411ABB54) * ((float)8 / (float)9)); //wtf??
}
void ScaleComponent::UpdateInput()
{
return;
}
}
@@ -0,0 +1,35 @@
#pragma once
#include "EmulatorComponent.h"
#include "GameState.h"
namespace TLAC::Components
{
class ScaleComponent : public EmulatorComponent
{
public:
ScaleComponent();
~ScaleComponent();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
virtual void UpdateInput() override;
const int updatesPerFrame = 39;
float* uiAspectRatio;
float* uiWidth;
float* uiHeight;
int* fb1Width;
int* fb1Height;
int* fb2Width;
int* fb2Height;
double* fbAspectRatio;
private:
};
}
@@ -0,0 +1,41 @@
#include "StageManager.h"
#include "../Constants.h"
#include <windows.h>
namespace TLAC::Components
{
StageManager::StageManager()
{
}
StageManager::~StageManager()
{
}
const char* StageManager::GetDisplayName()
{
return "stage_manager";
}
void StageManager::Initialize(ComponentsManager*)
{
// add the offset between moving 2 into ebx and the start of the function
int32_t* playCount = (int32_t*)(((uint8_t*)PLAYS_PER_SESSION_GETTER_ADDRESS) + 0x7);
DWORD oldProtect;
VirtualProtect(playCount, sizeof(int32_t), PAGE_EXECUTE_READWRITE, &oldProtect);
// set ’Ê�탂�[ƒh per session play count
*playCount = GetPlayCount();
}
void StageManager::Update()
{
return;
}
int32_t StageManager::GetPlayCount()
{
return INT32_MAX;
}
}
@@ -0,0 +1,21 @@
#pragma once
#include "EmulatorComponent.h"
#include <stdint.h>
namespace TLAC::Components
{
class StageManager : public EmulatorComponent
{
public:
StageManager();
~StageManager();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
private:
int32_t GetPlayCount();
};
}
@@ -0,0 +1,34 @@
#include "SysTimer.h"
#include "../Constants.h"
namespace TLAC::Components
{
SysTimer::SysTimer()
{
}
SysTimer::~SysTimer()
{
}
const char* SysTimer::GetDisplayName()
{
return "sys_timer";
}
void SysTimer::Initialize(ComponentsManager*)
{
selPvTime = GetSysTimePtr((void*)SEL_PV_TIME_ADDRESS);
}
void SysTimer::Update()
{
// account for the decrement that occures during this frame
*selPvTime = SEL_PV_FREEZE_TIME * SYS_TIME_FACTOR + 1;
}
int* SysTimer::GetSysTimePtr(void *address)
{
return (int*)address;
}
}
@@ -0,0 +1,25 @@
#pragma once
#include "EmulatorComponent.h"
namespace TLAC::Components
{
class SysTimer : public EmulatorComponent
{
const int SYS_TIME_FACTOR = 60;
const int SEL_PV_FREEZE_TIME = 39;
public:
SysTimer();
~SysTimer();
virtual const char* GetDisplayName() override;
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
private:
int* selPvTime;
int* GetSysTimePtr(void *address);
};
}
+104
View File
@@ -0,0 +1,104 @@
#pragma once
#include <stdint.h>
constexpr uint8_t NOP_OPCODE = 0x90;
constexpr uint8_t RET_OPCODE = 0xC3;
constexpr uint8_t JMP_OPCODE = 0xE9;
constexpr uint8_t JNE_OPCODE = 0x85;
//constexpr uint64_t ENGINE_UPDATE_HOOK_TARGET_ADDRESS = 0x000000014018CC40;
constexpr uint64_t ENGINE_UPDATE_INPUT_ADDRESS = 0x000000014018CBB0;
constexpr uint64_t CURRENT_GAME_STATE_ADDRESS = 0x0000000140EDA810;
constexpr uint64_t RESOLUTION_WIDTH_ADDRESS = 0x0000000140EDA8BC;
constexpr uint64_t RESOLUTION_HEIGHT_ADDRESS = 0x0000000140EDA8C0;
constexpr uint64_t SYSTEM_WARNING_ELAPSED_ADDRESS = (0x00000001411A1430 + 0x68);
constexpr uint64_t DATA_INIT_STATE_ADDRESS = 0x0000000140EDA7A8;
constexpr uint64_t AET_FRAME_DURATION_ADDRESS = 0x00000001409A0A58;
constexpr uint64_t PV_FRAME_RATE_ADDRESS = 0x0000000140EDA7CC;
constexpr uint64_t FRAME_SPEED_ADDRESS = 0x0000000140EDA798;
constexpr uint64_t FRAME_RATE_ADDRESS = 0x0000000140EDA6D0;
constexpr uint64_t DW_GUI_DISPLAY_INSTANCE_PTR_ADDRESS = 0x0000000141190108;
constexpr uint64_t INPUT_STATE_PTR_ADDRESS = 0x0000000140EDA330;
constexpr uint64_t SLIDER_CTRL_TASK_ADDRESS = 0x000000014CC5DE40;
constexpr uint64_t TASK_TOUCH_ADDRESS = 0x000000014CC9EC30;
constexpr uint64_t SEL_PV_TIME_ADDRESS = 0x000000014CC12498;
constexpr uint64_t PLAYER_DATA_ADDRESS = 0x00000001411A8850;
constexpr uint64_t SET_DEFAULT_PLAYER_DATA_ADDRESS = 0x00000001404A7370;
constexpr uint64_t PLAYS_PER_SESSION_GETTER_ADDRESS = 0x000000014038AEE0;
constexpr uint64_t PV_SEL_SLOTS_TO_SCROLL = 0x000000014CC12470;
constexpr uint64_t PV_SEL_SLOTS_CONST = 0x000000014CC119C8;
constexpr uint64_t MODULE_SEL_SLOTS_TO_SCROLL = 0x00000001418047EC;
constexpr uint64_t MODULE_IS_RECOMMENDED = 0x00000001418047E0;
constexpr uint64_t CAMERA_ADDRESS = 0x0000000140FBC2C0;
constexpr uint64_t CAMERA_POS_SETTER_ADDRESS = 0x00000001401F9460;
constexpr uint64_t CAMERA_INTR_SETTER_ADDRESS = 0x00000001401F93F0;
constexpr uint64_t CAMERA_ROT_SETTER_ADDRESS = 0x00000001401F9480;
constexpr uint64_t CAMERA_PERS_SETTER_ADDRESS = 0x00000001401F9430;
constexpr uint64_t UPDATE_TASKS_ADDRESS = 0x000000014019B980;
constexpr uint64_t GLUT_SET_CURSOR_ADDRESS = 0x00000001408B68E6;
constexpr uint64_t CHANGE_MODE_ADDRESS = 0x00000001401953D0;
constexpr uint64_t CHANGE_SUB_MODE_ADDRESS = 0x0000000140195260;
constexpr uint64_t TGT_TYPE_BASE_ADDRESS = 0x0000000140D0B69C;
constexpr uint64_t TGT_REMAINING_DURATION_BASE_ADDRESS = 0x0000000140D0B6A0;
constexpr uint64_t TGT_HIT_STATE_BASE_ADDRESS = 0x0000000140D0BAE4;
constexpr uint64_t TGT_ON_SCREEN_ADDRESS = 0x0000000140D0B678;
constexpr uint64_t HOLD_STATE_ADDRESS = 0x0000000140D1E20C;
constexpr uint64_t MAX_HOLD_STATE_ADDRESS = 0x0000000140D1E234;
constexpr uint64_t CHECK_SOMETHING_SET_MODULE_ADDRESS = 0x0000000140581C78;
constexpr uint64_t MODSELECTOR_CHECK_FUNCTION_ERRRET_ADDRESS = 0x00000001405869AD;
constexpr uint64_t MODSELECTOR_CLOSE_AFTER_MODULE = 0x0000000140583B45;
constexpr uint64_t MODSELECTOR_CLOSE_AFTER_CUSTOMIZE = 0x0000000140583C8C;
constexpr uint64_t MODULE_TABLE_START = PLAYER_DATA_ADDRESS + 0x140;
constexpr uint64_t MODULE_TABLE_END = MODULE_TABLE_START + 128;
constexpr uint64_t ITEM_TABLE_START = PLAYER_DATA_ADDRESS + 0x2B8;
constexpr uint64_t ITEM_TABLE_END = ITEM_TABLE_START + 128;
constexpr uint64_t FB_WIDTH_ADDRESS = 0x00000001411ABCA8;
constexpr uint64_t FB_HEIGHT_ADDRESS = 0x00000001411ABCAC;
constexpr uint64_t FB1_WIDTH_ADDRESS = 0x00000001411AD5F8;
constexpr uint64_t FB1_HEIGHT_ADDRESS = 0x00000001411AD5FC;
constexpr uint64_t FB2_WIDTH_ADDRESS = 0x0000000140EDA8E4;
constexpr uint64_t FB2_HEIGHT_ADDRESS = 0x0000000140EDA8E8;
constexpr uint64_t FB_RESOLUTION_WIDTH_ADDRESS = 0x00000001411ABB50;
constexpr uint64_t FB_RESOLUTION_HEIGHT_ADDRESS = 0x00000001411ABB54;
constexpr uint64_t UI_WIDTH_ADDRESS = 0x000000014CC621E4;
constexpr uint64_t UI_HEIGHT_ADDRESS = 0x000000014CC621E8;
constexpr uint64_t FB_ASPECT_RATIO = 0x0000000140FBC2E8;
constexpr uint64_t UI_ASPECT_RATIO = 0x000000014CC621D0;
#define XINPUT_A 0x00
#define XINPUT_B 0x01
#define XINPUT_X 0x02
#define XINPUT_Y 0x03
#define XINPUT_UP 0x10
#define XINPUT_DOWN 0x11
#define XINPUT_LEFT 0x12
#define XINPUT_RIGHT 0x13
#define XINPUT_LS 0x20
#define XINPUT_RS 0x21
#define XINPUT_LT 0x22
#define XINPUT_RT 0x23
#define XINPUT_LSB 0x24
#define XINPUT_RSB 0x25
#define XINPUT_START 0x30
#define XINPUT_BACK 0x31
#define XINPUT_LUP 0x40
#define XINPUT_LDOWN 0x41
#define XINPUT_LLEFT 0x42
#define XINPUT_LRIGHT 0x43
#define XINPUT_RUP 0x50
#define XINPUT_RDOWN 0x51
#define XINPUT_RLEFT 0x52
#define XINPUT_RRIGHT 0x53
@@ -0,0 +1,72 @@
#include <stdio.h>
#include "ConfigFile.h"
#include "../Utilities/Operations.h"
namespace TLAC::FileSystem
{
ConfigFile::ConfigFile(const std::string &path) : TextFile(path)
{
return;
}
ConfigFile::ConfigFile(const std::string &directory, const std::string &file) : TextFile(directory, file)
{
return;
}
bool ConfigFile::TryGetValue(const std::string &key, std::string **value)
{
auto pair = ConfigMap.find(key);
bool found = pair != ConfigMap.end();
*value = found ? new std::string(pair->second) : nullptr;
return found;
}
int ConfigFile::GetIntegerValue(const std::string& key)
{
auto pair = ConfigMap.find(key);
bool found = pair != ConfigMap.end();
return found ? atoi(pair->second.c_str()) : 0;
}
bool ConfigFile::GetBooleanValue(const std::string& key)
{
auto pair = ConfigMap.find(key);
bool found = pair != ConfigMap.end();
return found ? pair->second == "true" : false;
}
float ConfigFile::GetFloatValue(const std::string & key)
{
auto pair = ConfigMap.find(key);
bool found = pair != ConfigMap.end();
return found ? (float)atof(pair->second.c_str()) : 0.0f;
}
void ConfigFile::Parse(std::ifstream &fileStream)
{
std::string line;
while (std::getline(fileStream, line))
{
if (IsComment(line))
continue;
auto splitline = Utilities::Split(line, "=");
for (auto &line : splitline)
Utilities::Trim(line);
ConfigMap.insert(std::make_pair(splitline[0], splitline[1]));
}
}
bool ConfigFile::IsComment(const std::string &line)
{
return line.size() <= 0 || line[0] == '#' || line[0] == '[' || line._Starts_with("//");
}
}
@@ -0,0 +1,28 @@
#pragma once
#include "TextFile.h"
#include <unordered_map>
namespace TLAC::FileSystem
{
class ConfigFile : public TextFile
{
public:
ConfigFile(const std::string &path);
ConfigFile(const std::string &directory, const std::string &file);
std::unordered_map<std::string, std::string> ConfigMap;
bool TryGetValue(const std::string &key, std::string **value);
int GetIntegerValue(const std::string& key);
bool GetBooleanValue(const std::string& key);
float GetFloatValue(const std::string& key);
protected:
virtual void Parse(std::ifstream &fileStream) override;
private:
bool IsComment(const std::string &line);
};
}
@@ -0,0 +1,41 @@
#include "TextFile.h"
#include <filesystem>
namespace fs = std::filesystem;
namespace TLAC::FileSystem
{
TextFile::TextFile(const std::string &path)
{
FileName = path;
}
TextFile::TextFile(const std::string &directory, const std::string &file)
{
auto fullPath = directory + "/" + file;
FileName = fullPath;
}
TextFile::~TextFile()
{
}
bool TextFile::OpenRead()
{
fs::path configPath = fs::u8path(FileName);
if (!fs::exists(configPath))
return false;
std::ifstream fileStream(configPath.wstring().c_str());
if (!fileStream.is_open())
return false;
Parse(fileStream);
fileStream.close();
return true;
}
}
@@ -0,0 +1,22 @@
#pragma once
#include <string>
#include <fstream>
namespace TLAC::FileSystem
{
class TextFile
{
public:
std::string FileName;
TextFile(const std::string &path);
TextFile(const std::string &directory, const std::string &file);
~TextFile();
bool OpenRead();
protected:
virtual void Parse(std::ifstream &fileStream) = 0;
};
}
@@ -0,0 +1,91 @@
#include "Binding.h"
namespace TLAC::Input
{
Binding::Binding()
{
}
Binding::~Binding()
{
for (auto& binding : InputBindings)
delete binding;
}
void Binding::AddBinding(IInputBinding* inputBinding)
{
InputBindings.push_back(inputBinding);
}
bool Binding::AnyDown()
{
for (const auto& binding : InputBindings)
{
if (binding->IsDown())
return true;
}
return false;
}
bool Binding::AnyTapped()
{
for (const auto& binding : InputBindings)
{
if (binding->IsTapped())
return true;
}
return false;
}
bool Binding::AnyReleased()
{
for (const auto& binding : InputBindings)
{
if (binding->IsReleased())
return true;
}
return false;
}
int Binding::GetDownCount()
{
int count = 0;
for (const auto& binding : InputBindings)
{
if (binding->IsDown())
count++;
}
return count;
}
int Binding::GetTappedCount()
{
int count = 0;
for (const auto& binding : InputBindings)
{
if (binding->IsTapped())
count++;
}
return count;
}
int Binding::GetReleasedCount()
{
int count = 0;
for (const auto& binding : InputBindings)
{
if (binding->IsReleased())
count++;
}
return count;
}
}
@@ -0,0 +1,26 @@
#pragma once
#include <vector>
#include "IInputBinding.h"
namespace TLAC::Input
{
class Binding
{
public:
std::vector<IInputBinding*> InputBindings;
Binding();
~Binding();
void AddBinding(IInputBinding* inputBinding);
bool AnyDown();
bool AnyTapped();
bool AnyReleased();
int GetDownCount();
int GetTappedCount();
int GetReleasedCount();
};
}
@@ -0,0 +1,29 @@
#include "Ds4Binding.h"
namespace TLAC::Input
{
#define Ds4InstanceCheckDefault(checkFunc) (DualShock4::InstanceInitialized() ? DualShock4::GetInstance()->checkFunc : false)
Ds4Binding::Ds4Binding(Ds4Button button) : Button(button)
{
}
Ds4Binding::~Ds4Binding()
{
}
bool Ds4Binding::IsDown()
{
return Ds4InstanceCheckDefault(IsDown(Button));
}
bool Ds4Binding::IsTapped()
{
return Ds4InstanceCheckDefault(IsTapped(Button));
}
bool Ds4Binding::IsReleased()
{
return Ds4InstanceCheckDefault(IsReleased(Button));
}
}
@@ -0,0 +1,19 @@
#pragma once
#include "IInputBinding.h"
#include "../DirectInput/Ds4/DualShock4.h"
namespace TLAC::Input
{
class Ds4Binding : public IInputBinding
{
public:
Ds4Button Button;
Ds4Binding(Ds4Button button);
~Ds4Binding();
bool IsDown() override;
bool IsTapped() override;
bool IsReleased() override;
};
}
@@ -0,0 +1,12 @@
#pragma once
namespace TLAC::Input
{
class IInputBinding
{
public:
virtual bool IsDown() = 0;
virtual bool IsTapped() = 0;
virtual bool IsReleased() = 0;
};
}
@@ -0,0 +1,27 @@
#include "KeyboardBinding.h"
namespace TLAC::Input
{
KeyboardBinding::KeyboardBinding(BYTE keycode) : Keycode(keycode)
{
}
KeyboardBinding::~KeyboardBinding()
{
}
bool KeyboardBinding::IsDown()
{
return Keyboard::GetInstance()->IsDown(Keycode);
}
bool KeyboardBinding::IsTapped()
{
return Keyboard::GetInstance()->IsTapped(Keycode);
}
bool KeyboardBinding::IsReleased()
{
return Keyboard::GetInstance()->IsReleased(Keycode);
}
}
@@ -0,0 +1,19 @@
#pragma once
#include "IInputBinding.h"
#include "../Keyboard/Keyboard.h"
namespace TLAC::Input
{
class KeyboardBinding : public IInputBinding
{
public:
BYTE Keycode;
KeyboardBinding(BYTE keycode);
~KeyboardBinding();
bool IsDown() override;
bool IsTapped() override;
bool IsReleased() override;
};
}
@@ -0,0 +1,70 @@
#include "MouseBinding.h"
#include "../Keyboard/Keyboard.h"
namespace TLAC::Input
{
MouseBinding::MouseBinding(MouseAction action) : Action(action)
{
}
MouseBinding::~MouseBinding()
{
}
bool MouseBinding::IsDown()
{
switch (Action)
{
case MouseAction_LeftButton:
return Keyboard::GetInstance()->IsDown(MK_LBUTTON);
case MouseAction_RightButton:
return Keyboard::GetInstance()->IsDown(MK_RBUTTON);
case MouseAction_MiddleButton:
return Keyboard::GetInstance()->IsDown(MK_MBUTTON);
case MouseAction_ScrollUp:
return Mouse::GetInstance()->GetIsScrolledUp();
case MouseAction_ScrollDown:
return Mouse::GetInstance()->GetIsScrolledDown();
default:
return false;
}
}
bool MouseBinding::IsTapped()
{
switch (Action)
{
case MouseAction_LeftButton:
return Keyboard::GetInstance()->IsTapped(MK_LBUTTON);
case MouseAction_RightButton:
return Keyboard::GetInstance()->IsTapped(MK_RBUTTON);
case MouseAction_MiddleButton:
return Keyboard::GetInstance()->IsTapped(MK_MBUTTON);
case MouseAction_ScrollUp:
return Mouse::GetInstance()->GetIsScrolledUp();
case MouseAction_ScrollDown:
return Mouse::GetInstance()->GetIsScrolledDown();
default:
return false;
}
}
bool MouseBinding::IsReleased()
{
switch (Action)
{
case MouseAction_LeftButton:
return Keyboard::GetInstance()->IsReleased(MK_LBUTTON);
case MouseAction_RightButton:
return Keyboard::GetInstance()->IsReleased(MK_RBUTTON);
case MouseAction_MiddleButton:
return Keyboard::GetInstance()->IsReleased(MK_MBUTTON);
case MouseAction_ScrollUp:
return Mouse::GetInstance()->GetWasScrolledUp();
case MouseAction_ScrollDown:
return Mouse::GetInstance()->GetWasScrolledDown();
default:
return false;
}
}
}
@@ -0,0 +1,28 @@
#pragma once
#include "IInputBinding.h"
#include "../Mouse/Mouse.h"
namespace TLAC::Input
{
enum MouseAction
{
MouseAction_LeftButton,
MouseAction_RightButton,
MouseAction_MiddleButton,
MouseAction_ScrollUp,
MouseAction_ScrollDown,
};
class MouseBinding : public IInputBinding
{
public:
MouseAction Action;
MouseBinding(MouseAction action);
~MouseBinding();
bool IsDown() override;
bool IsTapped() override;
bool IsReleased() override;
};
}
@@ -0,0 +1,33 @@
#include "XinputBinding.h"
#include "..\Xinput\Xinput.h"
namespace TLAC::Input
{
XinputBinding::XinputBinding(BYTE keycode) : Keycode(keycode)
{
}
XinputBinding::~XinputBinding()
{
}
bool XinputBinding::IsDown()
{
return Xinput::GetInstance()->IsDown(Keycode);
}
bool XinputBinding::IsTapped()
{
return Xinput::GetInstance()->IsTapped(Keycode);
}
bool XinputBinding::IsReleased()
{
return Xinput::GetInstance()->IsReleased(Keycode);
}
bool XinputBinding::IsDoubleTapped()
{
return Xinput::GetInstance()->IsDoubleTapped(Keycode);
}
}
@@ -0,0 +1,21 @@
#pragma once
#include "IInputBinding.h"
#include <windows.h>
#include <vector>
namespace TLAC::Input
{
class XinputBinding : public IInputBinding
{
public:
BYTE Keycode;
XinputBinding(BYTE keycode);
~XinputBinding();
bool IsDown() override;
bool IsTapped() override;
bool IsReleased() override;
bool IsDoubleTapped();
};
}
@@ -0,0 +1,13 @@
#include "Controller.h"
namespace TLAC::Input
{
Controller::Controller()
{
}
Controller::~Controller()
{
}
}
@@ -0,0 +1,12 @@
#pragma once
#include "DirectInputDevice.h"
namespace TLAC::Input
{
class Controller : public DirectInputDevice
{
protected:
Controller();
~Controller();
};
}
@@ -0,0 +1,26 @@
#include "DirectInput.h"
namespace TLAC::Input
{
IDirectInput8 *IDirectInputInstance = nullptr;
HRESULT InitializeDirectInput(HMODULE module)
{
HRESULT result = DirectInput8Create(module, DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&IDirectInputInstance, nullptr);
return result;
}
bool DirectInputInitialized()
{
return IDirectInputInstance != nullptr;
}
void DisposeDirectInput()
{
if (IDirectInputInstance == nullptr)
return;
IDirectInputInstance->Release();
IDirectInputInstance = nullptr;
}
}
@@ -0,0 +1,12 @@
#pragma once
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
namespace TLAC::Input
{
extern IDirectInput8 *IDirectInputInstance;
HRESULT InitializeDirectInput(HMODULE module);
bool DirectInputInitialized();
void DisposeDirectInput();
}
@@ -0,0 +1,66 @@
#include "DirectInputDevice.h"
namespace TLAC::Input
{
HRESULT DirectInputDevice::DI_CreateDevice(const GUID &guid)
{
if (!DirectInputInitialized())
return DIERR_NOTINITIALIZED;
HRESULT result = IDirectInputInstance->CreateDevice(guid, &directInputdevice, NULL);
return result;
}
HRESULT DirectInputDevice::DI_SetDataFormat(LPCDIDATAFORMAT dataFormat)
{
HRESULT result = directInputdevice->SetDataFormat(dataFormat);
return result;
}
HRESULT DirectInputDevice::DI_SetCooperativeLevel(HWND windowHandle, DWORD flags)
{
HRESULT result = directInputdevice->SetCooperativeLevel(windowHandle, flags);
return result;
}
HRESULT DirectInputDevice::DI_Acquire()
{
HRESULT result = directInputdevice->Acquire();
return result;
}
HRESULT DirectInputDevice::DI_Unacquire()
{
HRESULT result = directInputdevice->Unacquire();
return result;
}
HRESULT DirectInputDevice::DI_Release()
{
HRESULT result = directInputdevice->Release();
return result;
}
HRESULT DirectInputDevice::DI_Poll()
{
HRESULT result = directInputdevice->Poll();
return result;
}
HRESULT DirectInputDevice::DI_GetDeviceState(DWORD size, LPVOID data)
{
HRESULT result = directInputdevice->GetDeviceState(size, data);
return result;
}
void DirectInputDevice::DI_Dispose()
{
if (directInputdevice == nullptr)
return;
HRESULT result = NULL;
result = DI_Unacquire();
result = DI_Release();
}
}
@@ -0,0 +1,22 @@
#pragma once
#include "DirectInput.h"
namespace TLAC::Input
{
class DirectInputDevice
{
protected:
IDirectInputDevice8 *directInputdevice;
HRESULT DI_CreateDevice(const GUID& guid);
HRESULT DI_SetDataFormat(LPCDIDATAFORMAT dataFormat);
HRESULT DI_SetCooperativeLevel(HWND windowHandle, DWORD flags);
HRESULT DI_Acquire();
HRESULT DI_Unacquire();
HRESULT DI_Release();
HRESULT DI_Poll();
HRESULT DI_GetDeviceState(DWORD size, LPVOID data);
void DI_Dispose();
};
}
@@ -0,0 +1,35 @@
#include "DirectInputMouse.h"
namespace TLAC::Input
{
DirectInputMouse::DirectInputMouse()
{
HRESULT result = NULL;
result = DI_CreateDevice(GUID_SysMouse);
if (FAILED(result))
return;
result = DI_SetDataFormat(&c_dfDIMouse);
result = DI_Acquire();
}
DirectInputMouse::~DirectInputMouse()
{
DI_Dispose();
}
bool DirectInputMouse::Poll()
{
if (!DirectInputInitialized())
return FALSE;
HRESULT result = NULL;
result = DI_Poll();
result = DI_GetDeviceState(sizeof(mouseState), &mouseState);
return !FAILED(result);
}
}
@@ -0,0 +1,21 @@
#pragma once
#include "DirectInputDevice.h"
namespace TLAC::Input
{
class DirectInputMouse : public DirectInputDevice
{
public:
DirectInputMouse();
~DirectInputMouse();
bool Poll();
inline long GetXPosition() { return mouseState.lX; };
inline long GetYPosition() { return mouseState.lY; };
inline long GetMouseWheel() { return mouseState.lZ; };
private:
DIMOUSESTATE mouseState;
};
}
@@ -0,0 +1,52 @@
#pragma once
namespace TLAC::Input
{
enum Direction
{
DIR_UP,
DIR_RIGHT,
DIR_DOWN,
DIR_LEFT
};
enum Ds4Button : int
{
DS4_SQUARE = 0,
DS4_CROSS = 1,
DS4_CIRCLE = 2,
DS4_TRIANGLE = 3,
DS4_L1 = 4,
DS4_R1 = 5,
DS4_L_TRIGGER = 6,
DS4_R_TRIGGER = 7,
DS4_SHARE = 8,
DS4_OPTIONS = 9,
DS4_L3 = 10,
DS4_R3 = 11,
DS4_PS = 12,
DS4_TOUCH = 13,
DS4_DPAD_UP,
DS4_DPAD_RIGHT,
DS4_DPAD_DOWN,
DS4_DPAD_LEFT,
DS4_L_STICK_UP,
DS4_L_STICK_RIGHT,
DS4_L_STICK_DOWN,
DS4_L_STICK_LEFT,
DS4_R_STICK_UP,
DS4_R_STICK_RIGHT,
DS4_R_STICK_DOWN,
DS4_R_STICK_LEFT,
DS4_BUTTON_MAX,
};
}
@@ -0,0 +1,14 @@
#include "Ds4State.h"
namespace TLAC::Input
{
Joystick::Joystick() : XAxis(0.0f), YAxis(0.0f)
{
return;
};
Joystick::Joystick(float xAxis, float yAxis) : XAxis(xAxis), YAxis(yAxis)
{
return;
};
}
@@ -0,0 +1,39 @@
#pragma once
#include "../DirectInput.h"
#include "Ds4Button.h"
namespace TLAC::Input
{
struct Joystick
{
FLOAT XAxis, YAxis;
Joystick();
Joystick(float xAxis, float yAxis);
};
struct Dpad
{
BOOL IsDown;
FLOAT Angle;
Joystick Stick;
};
struct Trigger
{
FLOAT Axis;
};
struct Ds4State
{
DIJOYSTATE2 DI_JoyState;
BYTE Buttons[DS4_BUTTON_MAX];
Dpad Dpad;
Joystick LeftStick;
Joystick RightStick;
Trigger LeftTrigger;
Trigger RightTrigger;
};
}
@@ -0,0 +1,169 @@
#include "DualShock4.h"
#include "../../../Utilities/Math.h"
#include "../../../framework.h"
#include <stdio.h>
namespace TLAC::Input
{
DualShock4* DualShock4::instance;
DualShock4::DualShock4()
{
}
DualShock4::~DualShock4()
{
DI_Dispose();
}
bool DualShock4::TryInitializeInstance()
{
if (InstanceInitialized())
return true;
if (!DirectInputInitialized())
return false;
DualShock4 *dualShock4 = new DualShock4();
bool success = dualShock4->Initialize();
instance = success ? dualShock4 : nullptr;
if (!success)
delete dualShock4;
return success;
}
bool DualShock4::Initialize()
{
HRESULT result = NULL;
const size_t guidCount = sizeof(GUID_Ds4) / sizeof(GUID);
for (size_t i = 0; i < guidCount; i++)
{
result = DI_CreateDevice(GUID_Ds4[i]);
if (!FAILED(result))
break;
else if (i == guidCount - 1)
return false;
}
if (FAILED(result = DI_SetDataFormat(&c_dfDIJoystick2)))
return false;
result = DI_Acquire();
return true;
}
bool DualShock4::PollInput()
{
lastState = currentState;
HRESULT result = NULL;
result = DI_Poll();
result = DI_GetDeviceState(sizeof(DIJOYSTATE2), &currentState.DI_JoyState);
if (result != DI_OK)
return false;
UpdateInternalDs4State(currentState);
for (int button = 0; button < DS4_BUTTON_MAX; button++)
currentState.Buttons[button] = GetButtonState(currentState, (Ds4Button)button);
return true;
}
void DualShock4::UpdateInternalDs4State(Ds4State &state)
{
if (state.Dpad.IsDown = state.DI_JoyState.rgdwPOV[0] != -1)
{
state.Dpad.Angle = (state.DI_JoyState.rgdwPOV[0] / 100.0f);
auto direction = Utilities::GetDirection(state.Dpad.Angle);
state.Dpad.Stick = { direction.Y, -direction.X };
}
else
{
state.Dpad.Angle = 0;
state.Dpad.Stick = Joystick();
}
state.LeftStick = NormalizeStick(state.DI_JoyState.lX, state.DI_JoyState.lY);
state.RightStick = NormalizeStick(state.DI_JoyState.lZ, state.DI_JoyState.lRz);
state.LeftTrigger = { NormalizeTrigger(state.DI_JoyState.lRx) };
state.RightTrigger = { NormalizeTrigger(state.DI_JoyState.lRy) };
}
bool DualShock4::IsDown(Ds4Button button)
{
return currentState.Buttons[button];
}
bool DualShock4::IsUp(Ds4Button button)
{
return !IsDown(button);
}
bool DualShock4::IsTapped(Ds4Button button)
{
return IsDown(button) && WasUp(button);
}
bool DualShock4::IsReleased(Ds4Button button)
{
return IsUp(button) && WasDown(button);
}
bool DualShock4::WasDown(Ds4Button button)
{
return lastState.Buttons[button];
}
bool DualShock4::WasUp(Ds4Button button)
{
return !WasDown(button);
}
bool DualShock4::MatchesDirection(Joystick joystick, Direction directionEnum, float threshold)
{
switch (directionEnum)
{
case TLAC::Input::DIR_UP:
return joystick.YAxis <= -threshold;
case TLAC::Input::DIR_RIGHT:
return joystick.XAxis >= +threshold;
case TLAC::Input::DIR_DOWN:
return joystick.YAxis >= +threshold;
case TLAC::Input::DIR_LEFT:
return joystick.XAxis <= -threshold;
default:
return false;
}
}
bool DualShock4::GetButtonState(Ds4State &state, Ds4Button button)
{
if (button >= DS4_SQUARE && button <= DS4_TOUCH)
return state.DI_JoyState.rgbButtons[button];
if (button >= DS4_DPAD_UP && button <= DS4_DPAD_LEFT)
return state.Dpad.IsDown ? MatchesDirection(state.Dpad.Stick, (Direction)(button - DS4_DPAD_UP), dpadThreshold) : false;
if (button >= DS4_L_STICK_UP && button <= DS4_L_STICK_LEFT)
return MatchesDirection(state.LeftStick, (Direction)(button - DS4_L_STICK_UP), joystickThreshold);
if (button >= DS4_R_STICK_UP && button <= DS4_R_STICK_LEFT)
return MatchesDirection(state.RightStick, (Direction)(button - DS4_R_STICK_UP), joystickThreshold);
return false;
}
}
@@ -0,0 +1,62 @@
#pragma once
#include "../Controller.h"
#include "../../IInputDevice.h"
#include "Ds4State.h"
namespace TLAC::Input
{
// DualShock 4 Wireless Controller Product GUIDs:
const GUID GUID_Ds4[2] =
{
// First Generation: {05C4054C-0000-0000-0000-504944564944}
{ 0x05C4054C, 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } },
// Second Generation: {09CC054C-0000-0000-0000-504944564944}
{ 0x09CC054C, 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } },
};
class DualShock4 : public Controller, public IInputDevice
{
public:
DualShock4();
~DualShock4();
static bool TryInitializeInstance();
bool Initialize();
bool PollInput() override;
bool IsDown(Ds4Button button);
bool IsUp(Ds4Button button);
bool IsTapped(Ds4Button button);
bool IsReleased(Ds4Button button);
bool WasDown(Ds4Button button);
bool WasUp(Ds4Button button);
inline Joystick GetLeftStick() { return currentState.LeftStick; };
inline Joystick GetRightStick() { return currentState.RightStick; };
inline Joystick GetDpad() { return currentState.Dpad.Stick; };
static inline bool InstanceInitialized() { return instance != nullptr; };
static inline DualShock4* GetInstance() { return instance; };
static inline void DeleteInstance() { delete instance; instance = nullptr; };
private:
static DualShock4* instance;
Ds4State lastState;
Ds4State currentState;
const float triggerThreshold = 0.5f;
const float joystickThreshold = 0.5f;
const float dpadThreshold = 0.5f;
inline float NormalizeTrigger(long value) { return (float)value / USHRT_MAX; };
inline float NormalizeStick(long value) { return (float)value / USHRT_MAX * 2.0f - 1.0f; };
inline Joystick NormalizeStick(long x, long y) { return Joystick(NormalizeStick(x), NormalizeStick(y)); };
void UpdateInternalDs4State(Ds4State &state);
bool MatchesDirection(Joystick joystick, Direction directionEnum, float threshold);
bool GetButtonState(Ds4State &state, Ds4Button button);
};
}
@@ -0,0 +1,10 @@
#pragma once
namespace TLAC::Input
{
class IInputDevice
{
public:
virtual bool PollInput() = 0;
};
}
@@ -0,0 +1,275 @@
#include "Config.h"
#include "windows.h"
#include "../Bindings/KeyboardBinding.h"
#include "../Bindings/Ds4Binding.h"
#include "../../Utilities/Operations.h"
#include "../Bindings/XinputBinding.h"
#include "../../Constants.h"
namespace TLAC::Input::KeyConfig
{
KeycodeMap Config::Keymap =
{
// NumPad Keys
{ "NumPad0", VK_NUMPAD0 },
{ "NumPad1", VK_NUMPAD1 },
{ "NumPad2", VK_NUMPAD2 },
{ "NumPad3", VK_NUMPAD3 },
{ "NumPad4", VK_NUMPAD4 },
{ "NumPad5", VK_NUMPAD5 },
{ "NumPad6", VK_NUMPAD6 },
{ "NumPad7", VK_NUMPAD7 },
{ "NumPad8", VK_NUMPAD8 },
{ "NumPad9", VK_NUMPAD9 },
{ "Plus", VK_ADD },
{ "Minus", VK_SUBTRACT },
{ "Divide", VK_DIVIDE },
{ "Multiply", VK_MULTIPLY },
{ "Comma", VK_OEM_COMMA },
{ "Period", VK_OEM_PERIOD },
{ "Slash", VK_OEM_2 },
// F-Keys
{ "F1", VK_F1 },
{ "F2", VK_F2 },
{ "F3", VK_F3 },
{ "F4", VK_F4 },
{ "F5", VK_F5 },
{ "F6", VK_F6 },
{ "F7", VK_F7 },
{ "F8", VK_F8 },
{ "F9", VK_F9 },
{ "F10", VK_F10 },
{ "F11", VK_F11 },
{ "F12", VK_F12 },
{ "F13", VK_F13 },
{ "F14", VK_F14 },
{ "F15", VK_F15 },
{ "F16", VK_F16 },
{ "F17", VK_F17 },
{ "F18", VK_F18 },
{ "F19", VK_F19 },
{ "F20", VK_F20 },
{ "F21", VK_F21 },
{ "F22", VK_F22 },
{ "F23", VK_F23 },
{ "F24", VK_F24 },
// Shift Keys
{ "LeftShift", VK_LSHIFT },
{ "LShift", VK_LSHIFT },
{ "RightShift", VK_RSHIFT },
{ "RShift", VK_RSHIFT },
// Control Keys
{ "LeftControl", VK_LCONTROL },
{ "LControl", VK_LCONTROL },
{ "LCtrl", VK_LCONTROL },
{ "RightControl", VK_RCONTROL },
{ "RControl", VK_RCONTROL },
{ "RCtrl", VK_RCONTROL },
// Arrow Keys
{ "Up", VK_UP },
{ "Down", VK_DOWN },
{ "Left", VK_LEFT },
{ "Right", VK_RIGHT },
// Special Keys
{ "Enter", VK_RETURN },
{ "Return", VK_RETURN },
{ "Tab", VK_TAB },
{ "Back", VK_BACK },
{ "Backspace", VK_BACK },
{ "Insert", VK_INSERT },
{ "Ins", VK_INSERT },
{ "Delete", VK_DELETE },
{ "Del", VK_DELETE },
{ "Home", VK_HOME },
{ "End", VK_END },
{ "PageUp", VK_PRIOR },
{ "PageDown", VK_NEXT },
{ "ESC", VK_ESCAPE },
{ "Escape", VK_ESCAPE },
{ "Comma", VK_OEM_COMMA },
{ "Period", VK_OEM_PERIOD },
{ "Slash", VK_OEM_2 },
// Mouse buttons
{ "MouseLeft", VK_LBUTTON },
{ "MouseMiddle", VK_MBUTTON },
{ "MouseRight", VK_RBUTTON },
{ "MouseX1", VK_XBUTTON1 },
{ "MouseX2", VK_XBUTTON2 },
};
KeycodeMap Config::XinputMap =
{
//XINPUT
{ "XINPUT_A", XINPUT_A},
{ "XINPUT_B", XINPUT_B},
{ "XINPUT_X", XINPUT_X},
{ "XINPUT_Y", XINPUT_Y},
{ "XINPUT_UP", XINPUT_UP},
{ "XINPUT_DOWN", XINPUT_DOWN},
{ "XINPUT_LEFT", XINPUT_LEFT},
{ "XINPUT_RIGHT", XINPUT_RIGHT},
{ "XINPUT_START", XINPUT_START},
{ "XINPUT_BACK", XINPUT_BACK},
{ "XINPUT_LS", XINPUT_LS},
{ "XINPUT_RS", XINPUT_RS},
{ "XINPUT_LB", XINPUT_LS},
{ "XINPUT_RB", XINPUT_RS},
{ "XINPUT_LT", XINPUT_LT},
{ "XINPUT_RT", XINPUT_RT},
{ "XINPUT_LSB", XINPUT_LSB},
{ "XINPUT_RSB", XINPUT_RSB},
{ "XINPUT_LLEFT", XINPUT_LLEFT},
{ "XINPUT_LRIGHT", XINPUT_LRIGHT},
{ "XINPUT_RLEFT", XINPUT_RLEFT},
{ "XINPUT_RRIGHT", XINPUT_RRIGHT},
};
Ds4ButtonMap Config::Ds4Map =
{
// Face Buttons
{ "DS4_SQUARE", DS4_SQUARE },
{ "Ds4_Square", DS4_SQUARE },
{ "DS4_CROSS", DS4_CROSS },
{ "Ds4_Cross", DS4_CROSS },
{ "DS4_CIRCLE", DS4_CIRCLE },
{ "Ds4_Circle", DS4_CIRCLE },
{ "DS4_TRIANGLE", DS4_TRIANGLE },
{ "Ds4_Triangle", DS4_TRIANGLE },
// Standard Buttons
{ "DS4_SHARE", DS4_SHARE },
{ "Ds4_Share", DS4_SHARE },
{ "DS4_OPTIONS", DS4_OPTIONS },
{ "Ds4_Options", DS4_OPTIONS },
{ "DS4_PS", DS4_PS },
{ "Ds4_PS", DS4_PS },
{ "DS4_TOUCH", DS4_TOUCH },
{ "Ds4_Touch", DS4_TOUCH },
{ "DS4_L1", DS4_L1 },
{ "Ds4_L1", DS4_L1 },
{ "DS4_R1", DS4_R1 },
{ "Ds4_R1", DS4_R1 },
// D-Pad Directions
{ "DS4_DPAD_UP", DS4_DPAD_UP },
{ "Ds4_DPad_Up", DS4_DPAD_UP },
{ "DS4_DPAD_RIGHT", DS4_DPAD_RIGHT },
{ "Ds4_DPad_Right", DS4_DPAD_RIGHT },
{ "DS4_DPAD_DOWN", DS4_DPAD_DOWN },
{ "Ds4_DPad_Down", DS4_DPAD_DOWN },
{ "DS4_DPAD_LEFT", DS4_DPAD_LEFT },
{ "Ds4_DPad_Left", DS4_DPAD_LEFT },
// Trigger Buttons
{ "DS4_L_TRIGGER", DS4_L_TRIGGER },
{ "Ds4_L_Trigger", DS4_L_TRIGGER },
{ "DS4_R_TRIGGER", DS4_R_TRIGGER },
{ "Ds4_R_Trigger", DS4_R_TRIGGER },
// Joystick Buttons
{ "DS4_L3", DS4_L3 },
{ "Ds4_L3", DS4_L3 },
{ "DS4_R3", DS4_R3 },
{ "Ds4_R3", DS4_R3 },
// Left Joystick
{ "DS4_L_STICK_UP", DS4_L_STICK_UP },
{ "Ds4_L_Stick_Up", DS4_L_STICK_UP },
{ "DS4_L_STICK_RIGHT", DS4_L_STICK_RIGHT },
{ "Ds4_L_Stick_Right", DS4_L_STICK_RIGHT },
{ "DS4_L_STICK_DOWN", DS4_L_STICK_DOWN },
{ "Ds4_L_Stick_Down", DS4_L_STICK_DOWN },
{ "DS4_L_STICK_LEFT", DS4_L_STICK_LEFT },
{ "Ds4_L_Stick_Left", DS4_L_STICK_LEFT },
// Right Joystick
{ "DS4_R_STICK_UP", DS4_R_STICK_UP },
{ "Ds4_R_Stick_Up", DS4_R_STICK_UP },
{ "DS4_R_STICK_RIGHT", DS4_R_STICK_RIGHT },
{ "Ds4_R_Stick_Right", DS4_R_STICK_RIGHT },
{ "DS4_R_STICK_DOWN", DS4_R_STICK_DOWN },
{ "Ds4_R_Stick_Down", DS4_R_STICK_DOWN },
{ "DS4_R_STICK_LEFT", DS4_R_STICK_LEFT },
{ "Ds4_R_Stick_Left", DS4_R_STICK_LEFT },
};
void Config::BindConfigKeys(std::unordered_map<std::string, std::string> &configMap, const char *configKeyName, Binding &bindObj, std::vector<std::string> defaultKeys)
{
std::vector<std::string> keys;
auto configPair = configMap.find(configKeyName);
// config variable was found in the ini
if (configPair != configMap.end())
{
keys = Utilities::Split(configPair->second, ",");
}
else
{
keys = defaultKeys;
}
for (std::string key : keys)
{
Utilities::Trim(key);
// Applies only for Single-Character keys
if (key.length() == 1)
{
bindObj.AddBinding(new KeyboardBinding(key[0]));
}
else // for special key names
{
auto keycode = Config::Keymap.find(key.c_str());
// name is known in the special keys map
if (keycode != Config::Keymap.end())
{
bindObj.AddBinding(new KeyboardBinding(keycode->second));
}
else
{
auto xinputBtn = Config::XinputMap.find(key.c_str());
if (xinputBtn != Config::XinputMap.end())
{
bindObj.AddBinding(new XinputBinding(xinputBtn->second));
}
else
{
// just gonna be lazy for now and put this inside an else statement
auto ds4Button = Config::Ds4Map.find(key.c_str());
if (ds4Button != Config::Ds4Map.end())
{
bindObj.AddBinding(new Ds4Binding(ds4Button->second));
}
else
{
printf("[TLAC] Config::BindConfigKeys(): Unable to parse key: '%s'\n", key.c_str());
}
}
}
}
}
}
}
@@ -0,0 +1,23 @@
#pragma once
#include <unordered_map>
#include "KeyString.h"
#include "KeyStringHash.h"
#include "../Bindings/Binding.h"
#include "../DirectInput/Ds4/Ds4Button.h"
namespace TLAC::Input::KeyConfig
{
typedef std::unordered_map<KeyString, uint8_t, KeyStringHash> KeycodeMap;
typedef std::unordered_map<KeyString, Ds4Button, KeyStringHash> Ds4ButtonMap;
class Config
{
public:
static KeycodeMap Keymap;
static Ds4ButtonMap Ds4Map;
static KeycodeMap XinputMap;
static void BindConfigKeys(std::unordered_map<std::string, std::string> &configMap, const char *configKeyName, Binding &bindObj, std::vector<std::string> defaultKeys);
};
}
@@ -0,0 +1,13 @@
#include "KeyString.h"
namespace TLAC::Input::KeyConfig
{
KeyString::KeyString(const char* str) : value(str)
{
}
bool KeyString::operator==(const KeyString& rsv) const
{
return !_strcmpi(value.c_str(), rsv.value.c_str());
}
}
@@ -0,0 +1,14 @@
#pragma once
#include <string>
namespace TLAC::Input::KeyConfig
{
struct KeyString
{
std::string value;
KeyString(const char* str);
bool operator==(const KeyString& rsv) const;
};
}
@@ -0,0 +1,13 @@
#include "KeyStringHash.h"
#include <filesystem>
namespace TLAC::Input::KeyConfig
{
size_t KeyStringHash::operator()(const KeyString& key) const
{
std::string ret = key.value;
std::transform(ret.begin(), ret.end(), ret.begin(),
[](unsigned char c) { return std::tolower(c, std::locale()); });
return std::hash<std::string>()(ret);
}
}
@@ -0,0 +1,10 @@
#pragma once
#include "KeyString.h"
namespace TLAC::Input::KeyConfig
{
struct KeyStringHash
{
size_t operator()(const KeyString& key) const;
};
}
@@ -0,0 +1,100 @@
#include "Keyboard.h"
namespace TLAC::Input
{
Keyboard* Keyboard::instance;
Keyboard::Keyboard()
{
}
Keyboard* Keyboard::GetInstance()
{
if (instance == nullptr)
instance = new Keyboard();
return instance;
}
bool Keyboard::PollInput()
{
lastState = currentState;
float elapsed = keyIntervalWatch.Restart();
for (BYTE i = 0; i < KEYBOARD_KEYS; i++)
{
// DOWN
bool isDown = GetAsyncKeyState(i) < 0;
currentState.KeyStates[i] = isDown;
// DOUBLE TAPPED
bool isTapped = IsTapped(i);
keyDoubleTapStates[i] = isTapped ? keyDoubleTapWatches[i].Restart() <= DOUBLE_TAP_THRESHOLD : false;
// INTERVAL TAPPED
keyIntervalTapStates[i] = isTapped;
if (isTapped)
{
keyIntervalTapTimes[i] = 0;
keyIntervalInitials[i] = true;
}
else if (isDown)
{
float threshold = keyIntervalInitials[i] ? INTERVAL_TAP_DELAY_THRESHOLD : INTERVAL_TAP_THRESHOLD;
bool intervalTapped = (keyIntervalTapTimes[i] += elapsed) > threshold;
keyIntervalTapStates[i] = intervalTapped;
if (intervalTapped)
{
keyIntervalTapTimes[i] = 0;
keyIntervalInitials[i] = false;
}
}
}
return true;
}
bool Keyboard::IsDown(BYTE keycode)
{
return currentState.IsDown(keycode);
}
bool Keyboard::IsUp(BYTE keycode)
{
return !IsDown(keycode);
}
bool Keyboard::IsTapped(BYTE keycode)
{
return IsDown(keycode) && WasUp(keycode);
}
bool Keyboard::IsDoubleTapped(BYTE keycode)
{
return keyDoubleTapStates[keycode];
}
bool Keyboard::IsReleased(BYTE keycode)
{
return IsUp(keycode) && WasDown(keycode);
}
inline bool Keyboard::WasDown(BYTE keycode)
{
return lastState.IsDown(keycode);
}
inline bool Keyboard::WasUp(BYTE keycode)
{
return !WasDown(keycode);
}
bool Keyboard::IsIntervalTapped(BYTE keycode)
{
return keyIntervalTapStates[keycode];
}
}
@@ -0,0 +1,47 @@
#pragma once
#include "../IInputDevice.h"
#include "KeyboardState.h"
#include "../../Utilities/Stopwatch.h"
using Stopwatch = TLAC::Utilities::Stopwatch;
namespace TLAC::Input
{
constexpr float DOUBLE_TAP_THRESHOLD = 200.0f;
constexpr float INTERVAL_TAP_DELAY_THRESHOLD = 500.0f;
constexpr float INTERVAL_TAP_THRESHOLD = 75.0f;
class Keyboard : public IInputDevice
{
public:
static Keyboard* GetInstance();
bool PollInput() override;
bool IsDown(BYTE keycode);
bool IsUp(BYTE keycode);
bool IsTapped(BYTE keycode);
bool IsDoubleTapped(BYTE keycode);
bool IsReleased(BYTE keycode);
bool IsIntervalTapped(BYTE keycode);
bool WasDown(BYTE keycode);
bool WasUp(BYTE keycode);
private:
Keyboard();
KeyboardState lastState;
KeyboardState currentState;
Stopwatch keyIntervalWatch;
BYTE keyDoubleTapStates[KEYBOARD_KEYS];
Stopwatch keyDoubleTapWatches[KEYBOARD_KEYS];
BOOL keyIntervalInitials[KEYBOARD_KEYS];
BYTE keyIntervalTapStates[KEYBOARD_KEYS];
FLOAT keyIntervalTapTimes[KEYBOARD_KEYS];
static Keyboard* instance;
};
}
@@ -0,0 +1,9 @@
#include "KeyboardState.h"
namespace TLAC::Input
{
bool KeyboardState::IsDown(BYTE keycode)
{
return KeyStates[keycode];
}
}
@@ -0,0 +1,15 @@
#pragma once
#include <windows.h>
namespace TLAC::Input
{
const int KEYBOARD_KEYS = 0xFF;
struct KeyboardState
{
BYTE KeyStates[KEYBOARD_KEYS];
bool IsDown(BYTE keycode);
};
}
@@ -0,0 +1,135 @@
#include "Mouse.h"
#include "../../framework.h"
#include "../../Constants.h"
namespace TLAC::Input
{
Mouse* Mouse::instance;
Mouse::Mouse()
{
directInputMouse = new DirectInputMouse();
}
Mouse::~Mouse()
{
if (directInputMouse != nullptr)
delete directInputMouse;
}
Mouse* Mouse::GetInstance()
{
if (instance == nullptr)
instance = new Mouse();
return instance;
}
POINT Mouse::GetPosition()
{
return currentState.Position;
}
POINT Mouse::GetRelativePosition()
{
return currentState.RelativePosition;
}
POINT Mouse::GetDeltaPosition()
{
return
{
currentState.Position.x - lastState.Position.x,
currentState.Position.y - lastState.Position.y
};
}
long Mouse::GetMouseWheel()
{
return currentState.MouseWheel;
}
long Mouse::GetDeltaMouseWheel()
{
return currentState.MouseWheel - lastState.MouseWheel;
}
bool Mouse::HasMoved()
{
POINT delta = GetDeltaPosition();
return delta.x != 0 || delta.y != 0;
}
bool Mouse::GetIsScrolledUp()
{
return currentState.ScrolledUp;
}
bool Mouse::GetIsScrolledDown()
{
return currentState.ScrolledDown;
}
bool Mouse::GetWasScrolledUp()
{
return lastState.ScrolledUp;
}
bool Mouse::GetWasScrolledDown()
{
return lastState.ScrolledDown;
}
void Mouse::SetPosition(int x, int y)
{
lastState.Position.x = x;
lastState.Position.y = y;
SetCursorPos(x, y);
}
bool Mouse::PollInput()
{
lastState = currentState;
GetCursorPos(&currentState.Position);
currentState.RelativePosition = currentState.Position;
if (framework::DivaWindowHandle != NULL)
ScreenToClient(framework::DivaWindowHandle, &currentState.RelativePosition);
RECT hWindow;
GetClientRect(TLAC::framework::DivaWindowHandle, &hWindow);
gameHeight = (int*)RESOLUTION_HEIGHT_ADDRESS;
gameWidth = (int*)RESOLUTION_WIDTH_ADDRESS;
fbWidth = (int*)FB_WIDTH_ADDRESS;
fbHeight = (int*)FB_HEIGHT_ADDRESS;
if (directInputMouse != nullptr)
{
if (directInputMouse->Poll())
currentState.MouseWheel += directInputMouse->GetMouseWheel();
currentState.ScrolledUp = (GetDeltaMouseWheel() > 0);
currentState.ScrolledDown = (GetDeltaMouseWheel() < 0);
}
if ((fbWidth != gameWidth) && (fbHeight != gameHeight)) {
xoffset = ((float)16 / (float)9) * (hWindow.bottom - hWindow.top);
if (xoffset != (hWindow.right - hWindow.left))
{
scale = xoffset / (hWindow.right - hWindow.left);
xoffset = ((hWindow.right - hWindow.left) / 2) - (xoffset / 2);
}
else {
xoffset = 0;
scale = 1;
}
currentState.RelativePosition.x = ((currentState.RelativePosition.x - round(xoffset)) * *gameWidth / (hWindow.right - hWindow.left)) / scale;
currentState.RelativePosition.y = currentState.RelativePosition.y * *gameHeight / (hWindow.bottom - hWindow.top);
}
return true;
}
}
@@ -0,0 +1,49 @@
#pragma once
#include "../IInputDevice.h"
#include "../DirectInput/DirectInputMouse.h"
#include "MouseState.h"
namespace TLAC::Input
{
class Mouse : public IInputDevice
{
public:
~Mouse();
static Mouse* GetInstance();
bool PollInput() override;
POINT GetPosition();
POINT GetRelativePosition();
POINT GetDeltaPosition();
long GetMouseWheel();
long GetDeltaMouseWheel();
bool HasMoved();
bool GetIsScrolledUp();
bool GetIsScrolledDown();
bool GetWasScrolledUp();
bool GetWasScrolledDown();
void SetPosition(int x, int y);
private:
Mouse();
MouseState lastState;
MouseState currentState;
DirectInputMouse* directInputMouse = nullptr;
int* gameWidth;
int* gameHeight;
int* fbWidth;
int* fbHeight;
float xoffset;
float scale;
static Mouse* instance;
};
}
@@ -0,0 +1,15 @@
#pragma once
#include <windows.h>
namespace TLAC::Input
{
struct MouseState
{
POINT Position;
POINT RelativePosition;
long MouseWheel;
bool ScrolledUp;
bool ScrolledDown;
};
}
@@ -0,0 +1,266 @@
#include <windows.h>
#include "Xinput.h"
#include "../../Constants.h"
namespace TLAC::Input
{
Xinput* Xinput::instance;
Xinput::Xinput()
{
}
Xinput* Xinput::GetInstance()
{
if (instance == nullptr)
{
instance = new Xinput();
}
return instance;
}
void Xinput::SetTapStates(BYTE keycode, float elapsed)
{
KeyDoubleTapStates[keycode] = IsTapped(keycode) ? KeyDoubleTapWatches[keycode].Restart() <= DOUBLE_TAP_THRESHOLD : false;
bool isDown = currentState.KeyStates[keycode];
bool isTapped = IsTapped(keycode);
keyIntervalTapStates[keycode] = isTapped;
if (isTapped)
{
keyIntervalTapTimes[keycode] = 0;
keyIntervalInitials[keycode] = true;
}
else if (isDown)
{
float threshold = keyIntervalInitials[keycode] ? INTERVAL_TAP_DELAY_THRESHOLD : INTERVAL_TAP_THRESHOLD;
bool intervalTapped = (keyIntervalTapTimes[keycode] += elapsed) > threshold;
keyIntervalTapStates[keycode] = intervalTapped;
if (intervalTapped)
{
keyIntervalTapTimes[keycode] = 0;
keyIntervalInitials[keycode] = false;
}
}
}
bool Xinput::PollInput()
{
lastState = currentState;
ZeroMemory(&state, sizeof(XINPUT_STATE));
float elapsed = keyIntervalWatch.Restart();
if (XInputGetState(0, &state) == ERROR_SUCCESS)
{
BYTE i = XINPUT_A;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_DOWN;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_B;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_B)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_RIGHT;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_X;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_X)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_LEFT;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_Y;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_Y)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_UP;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_LS;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_RS;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_LSB;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_RSB;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_START;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_START)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_BACK;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_LT;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.bLeftTrigger > 230)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_RT;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.bRightTrigger > 230)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
{
//float normLX = fmaxf(-1, (float)state.Gamepad.sThumbLX / 32767);
i = XINPUT_LRIGHT;
currentState.KeyStates[i] = false;
if (state.Gamepad.sThumbLX > 10000)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
i = XINPUT_LLEFT;
currentState.KeyStates[i] = false;
if (state.Gamepad.sThumbLX < -10000)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
{
//float normLX = fmaxf(-1, (float)state.Gamepad.sThumbRX / 32767);
i = XINPUT_RRIGHT;
currentState.KeyStates[i] = false;
if (state.Gamepad.sThumbRX > 10000)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
i = XINPUT_RLEFT;
currentState.KeyStates[i] = false;
if (state.Gamepad.sThumbRX < -10000)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
}
else {
ZeroMemory(&state, sizeof(XINPUT_STATE));
ZeroMemory(&currentState, sizeof(currentState));
}
return TRUE;
}
bool Xinput::IsDown(BYTE keycode)
{
return currentState.IsDown(keycode);
}
bool Xinput::IsUp(BYTE keycode)
{
return !IsDown(keycode);
}
bool Xinput::IsTapped(BYTE keycode)
{
return IsDown(keycode) && WasUp(keycode);
}
bool Xinput::IsDoubleTapped(BYTE keycode)
{
return KeyDoubleTapStates[keycode];
}
bool Xinput::IsReleased(BYTE keycode)
{
return IsUp(keycode) && WasDown(keycode);
}
inline bool Xinput::WasDown(BYTE keycode)
{
return lastState.IsDown(keycode);
}
inline bool Xinput::WasUp(BYTE keycode)
{
return !WasDown(keycode);
}
bool Xinput::IsIntervalTapped(BYTE keycode)
{
return keyIntervalTapStates[keycode];
}
}
@@ -0,0 +1,51 @@
#pragma once
#include "../IInputDevice.h"
#include <xinput.h>
#include "../../Utilities/Stopwatch.h"
#include "XinputState.h"
using Stopwatch = TLAC::Utilities::Stopwatch;
namespace TLAC::Input
{
class Xinput : public IInputDevice
{
const float DOUBLE_TAP_THRESHOLD = 200.0f;
const float INTERVAL_TAP_DELAY_THRESHOLD = 500.0f;
const float INTERVAL_TAP_THRESHOLD = 75.0f;
public:
static Xinput* GetInstance();
bool PollInput() override;
bool IsDown(BYTE keycode);
bool IsUp(BYTE keycode);
bool IsTapped(BYTE keycode);
bool IsReleased(BYTE keycode);
bool IsDoubleTapped(BYTE keycode);
bool IsIntervalTapped(BYTE keycode);
bool WasDown(BYTE keycode);
bool WasUp(BYTE keycode);
private:
Xinput();
XinputState lastState;
XinputState currentState;
XINPUT_STATE state;
BYTE KeyDoubleTapStates[0xFF];
Utilities::Stopwatch KeyDoubleTapWatches[0xFF];
Stopwatch keyIntervalWatch;
BOOL keyIntervalInitials[0xFF];
BYTE keyIntervalTapStates[0xFF];
FLOAT keyIntervalTapTimes[0xFF];
static Xinput* instance;
void SetTapStates(BYTE keycode, float elapsed);
};
}
@@ -0,0 +1,9 @@
#include "XinputState.h"
namespace TLAC::Input
{
bool XinputState::IsDown(BYTE keycode)
{
return KeyStates[keycode];
}
}
@@ -0,0 +1,12 @@
#pragma once
#include <windows.h>
namespace TLAC::Input
{
struct XinputState
{
bool KeyStates[0x8F];
bool IsDown(BYTE keycode);
};
}
@@ -0,0 +1,285 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{2B5533BB-04A1-424F-9BCA-1CA963B46B7F}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>TLAC</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<TargetName>$(ProjectName)</TargetName>
<TargetExt>.dva</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<TargetName>$(ProjectName)</TargetName>
<TargetExt>.dva</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;TLAC_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>..\..\..\dependencies\detours\include;..\..\..\dependencies\freeglut\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>XINPUT9_1_0.LIB;dinput8.lib;dxguid.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>Xinput.h</IgnoreSpecificDefaultLibraries>
<AdditionalLibraryDirectories>..\..\..\dependencies\detours\lib;..\..\..\dependencies\freeglut\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;TLAC_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;TLAC_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>..\..\..\dependencies\detours\include;..\..\..\dependencies\freeglut\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalLibraryDirectories>..\..\..\dependencies\detours\lib;..\..\..\dependencies\freeglut\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>XINPUT9_1_0.LIB;dinput8.lib;dxguid.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>Xinput.h</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;TLAC_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="Components\CameraController.h" />
<ClInclude Include="Components\ComponentsManager.h" />
<ClInclude Include="Components\CustomPlayerData.h" />
<ClInclude Include="Components\DebugComponent.h" />
<ClInclude Include="Components\EmulatorComponent.h" />
<ClInclude Include="Components\FastLoader.h" />
<ClInclude Include="Components\FPSLimiter.h" />
<ClInclude Include="Components\FrameRateManager.h" />
<ClInclude Include="Components\GameState.h" />
<ClInclude Include="Components\GameTargets\HoldState.h" />
<ClInclude Include="Components\GameTargets\TargetHitStates.h" />
<ClInclude Include="Components\GameTargets\TargetInspector.h" />
<ClInclude Include="Components\GameTargets\TargetState.h" />
<ClInclude Include="Components\GameTargets\TargetTypes.h" />
<ClInclude Include="Components\Input\InputBufferType.h" />
<ClInclude Include="Components\Input\InputEmulator.h" />
<ClInclude Include="Components\Input\InputState.h" />
<ClInclude Include="Components\Input\JvsButtons.h" />
<ClInclude Include="Components\Input\TouchPanelEmulator.h" />
<ClInclude Include="Components\Input\TouchPanelState.h" />
<ClInclude Include="Components\Input\TouchSliderEmulator.h" />
<ClInclude Include="Components\Input\TouchSliderState.h" />
<ClInclude Include="Components\PlayerData.h" />
<ClInclude Include="Components\PlayerDataManager.h" />
<ClInclude Include="Components\ScaleComponent.h" />
<ClInclude Include="Components\StageManager.h" />
<ClInclude Include="Components\SysTimer.h" />
<ClInclude Include="Constants.h" />
<ClInclude Include="FileSystem\ConfigFile.h" />
<ClInclude Include="FileSystem\TextFile.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="Input\Bindings\Binding.h" />
<ClInclude Include="Input\Bindings\Ds4Binding.h" />
<ClInclude Include="Input\Bindings\IInputBinding.h" />
<ClInclude Include="Input\Bindings\KeyboardBinding.h" />
<ClInclude Include="Input\Bindings\MouseBinding.h" />
<ClInclude Include="Input\Bindings\XinputBinding.h" />
<ClInclude Include="Input\DirectInput\Controller.h" />
<ClInclude Include="Input\DirectInput\DirectInput.h" />
<ClInclude Include="Input\DirectInput\DirectInputDevice.h" />
<ClInclude Include="Input\DirectInput\DirectInputMouse.h" />
<ClInclude Include="Input\DirectInput\Ds4\Ds4Button.h" />
<ClInclude Include="Input\DirectInput\Ds4\Ds4State.h" />
<ClInclude Include="Input\DirectInput\Ds4\DualShock4.h" />
<ClInclude Include="Input\IInputDevice.h" />
<ClInclude Include="Input\Keyboard\Keyboard.h" />
<ClInclude Include="Input\Keyboard\KeyboardState.h" />
<ClInclude Include="Input\KeyConfig\Config.h" />
<ClInclude Include="Input\KeyConfig\KeyString.h" />
<ClInclude Include="Input\KeyConfig\KeyStringHash.h" />
<ClInclude Include="Input\Mouse\Mouse.h" />
<ClInclude Include="Input\Mouse\MouseState.h" />
<ClInclude Include="Input\Xinput\Xinput.h" />
<ClInclude Include="Input\Xinput\XinputState.h" />
<ClInclude Include="Utilities\EnumBitwiseOperations.h" />
<ClInclude Include="Utilities\Math.h" />
<ClInclude Include="Utilities\Operations.h" />
<ClInclude Include="Utilities\Stopwatch.h" />
<ClInclude Include="Utilities\Vec2.h" />
<ClInclude Include="Utilities\Vec3.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Components\CameraController.cpp" />
<ClCompile Include="Components\ComponentsManager.cpp" />
<ClCompile Include="Components\DebugComponent.cpp" />
<ClCompile Include="Components\EmulatorComponent.cpp" />
<ClCompile Include="Components\FastLoader.cpp" />
<ClCompile Include="Components\FPSLimiter.cpp" />
<ClCompile Include="Components\FrameRateManager.cpp" />
<ClCompile Include="Components\GameTargets\TargetInspector.cpp" />
<ClCompile Include="Components\Input\InputEmulator.cpp" />
<ClCompile Include="Components\Input\InputState.cpp" />
<ClCompile Include="Components\Input\TouchPanelEmulator.cpp" />
<ClCompile Include="Components\Input\TouchSliderEmulator.cpp" />
<ClCompile Include="Components\Input\TouchSliderState.cpp" />
<ClCompile Include="Components\PlayerDataManager.cpp" />
<ClCompile Include="Components\ScaleComponent.cpp" />
<ClCompile Include="Components\StageManager.cpp" />
<ClCompile Include="Components\SysTimer.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="FileSystem\ConfigFile.cpp" />
<ClCompile Include="FileSystem\TextFile.cpp" />
<ClCompile Include="framework.cpp" />
<ClCompile Include="Input\Bindings\Binding.cpp" />
<ClCompile Include="Input\Bindings\Ds4Binding.cpp" />
<ClCompile Include="Input\Bindings\KeyboardBinding.cpp" />
<ClCompile Include="Input\Bindings\MouseBinding.cpp" />
<ClCompile Include="Input\Bindings\XinputBinding.cpp" />
<ClCompile Include="Input\DirectInput\Controller.cpp" />
<ClCompile Include="Input\DirectInput\DirectInput.cpp" />
<ClCompile Include="Input\DirectInput\DirectInputDevice.cpp" />
<ClCompile Include="Input\DirectInput\DirectInputMouse.cpp" />
<ClCompile Include="Input\DirectInput\Ds4\Ds4State.cpp" />
<ClCompile Include="Input\DirectInput\Ds4\DualShock4.cpp" />
<ClCompile Include="Input\Keyboard\Keyboard.cpp" />
<ClCompile Include="Input\Keyboard\KeyboardState.cpp" />
<ClCompile Include="Input\KeyConfig\Config.cpp" />
<ClCompile Include="Input\KeyConfig\KeyString.cpp" />
<ClCompile Include="Input\KeyConfig\KeyStringHash.cpp" />
<ClCompile Include="Input\Mouse\Mouse.cpp" />
<ClCompile Include="Input\Xinput\Xinput.cpp" />
<ClCompile Include="Input\Xinput\XinputState.cpp" />
<ClCompile Include="Utilities\Math.cpp" />
<ClCompile Include="Utilities\Operations.cpp" />
<ClCompile Include="Utilities\Stopwatch.cpp" />
<ClCompile Include="Utilities\Vec2.cpp" />
<ClCompile Include="Utilities\Vec3.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,336 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Constants.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\CameraController.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\ComponentsManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\CustomPlayerData.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\DebugComponent.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\EmulatorComponent.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\FastLoader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\FrameRateManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\GameState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\PlayerData.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\PlayerDataManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\StageManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\SysTimer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\Input\InputBufferType.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\Input\InputEmulator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\Input\InputState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\Input\JvsButtons.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\Input\TouchPanelEmulator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\Input\TouchPanelState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\Input\TouchSliderEmulator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\Input\TouchSliderState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FileSystem\ConfigFile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FileSystem\TextFile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Bindings\Binding.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Bindings\Ds4Binding.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Bindings\IInputBinding.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Bindings\KeyboardBinding.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Bindings\MouseBinding.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\DirectInput\Ds4\Ds4Button.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\DirectInput\Ds4\Ds4State.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\DirectInput\Ds4\DualShock4.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\DirectInput\Controller.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\DirectInput\DirectInput.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\DirectInput\DirectInputDevice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\DirectInput\DirectInputMouse.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Keyboard\Keyboard.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Keyboard\KeyboardState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\KeyConfig\Config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\KeyConfig\KeyString.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\KeyConfig\KeyStringHash.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Mouse\Mouse.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Mouse\MouseState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\IInputDevice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utilities\EnumBitwiseOperations.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utilities\Math.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utilities\Operations.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utilities\Stopwatch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utilities\Vec2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utilities\Vec3.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\ScaleComponent.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Bindings\XinputBinding.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Xinput\Xinput.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Input\Xinput\XinputState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\FPSLimiter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\GameTargets\HoldState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\GameTargets\TargetHitStates.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\GameTargets\TargetInspector.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\GameTargets\TargetState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\GameTargets\TargetTypes.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="framework.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\CameraController.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\ComponentsManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\DebugComponent.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\EmulatorComponent.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\FastLoader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\FrameRateManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\PlayerDataManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\StageManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\SysTimer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\Input\InputEmulator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\Input\InputState.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\Input\TouchPanelEmulator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\Input\TouchSliderEmulator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\Input\TouchSliderState.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FileSystem\ConfigFile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FileSystem\TextFile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\Bindings\Binding.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\Bindings\Ds4Binding.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\Bindings\KeyboardBinding.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\Bindings\MouseBinding.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\DirectInput\Ds4\Ds4State.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\DirectInput\Ds4\DualShock4.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\DirectInput\Controller.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\DirectInput\DirectInput.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\DirectInput\DirectInputDevice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\DirectInput\DirectInputMouse.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\Keyboard\Keyboard.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\Keyboard\KeyboardState.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\KeyConfig\Config.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\KeyConfig\KeyString.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\KeyConfig\KeyStringHash.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\Mouse\Mouse.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utilities\Math.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utilities\Operations.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utilities\Stopwatch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utilities\Vec2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utilities\Vec3.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\ScaleComponent.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\Bindings\XinputBinding.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\Xinput\Xinput.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Input\Xinput\XinputState.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\FPSLimiter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Components\GameTargets\TargetInspector.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
@@ -0,0 +1,12 @@
#pragma once
namespace TLAC::Utilities
{
template<class T> inline T operator~ (T a) { return (T)~(int)a; }
template<class T> inline T operator| (T a, T b) { return (T)((int)a | (int)b); }
template<class T> inline T operator& (T a, T b) { return (T)((int)a & (int)b); }
template<class T> inline T operator^ (T a, T b) { return (T)((int)a ^ (int)b); }
template<class T> inline T& operator|= (T& a, T b) { return (T&)((int&)a |= (int)b); }
template<class T> inline T& operator&= (T& a, T b) { return (T&)((int&)a &= (int)b); }
template<class T> inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int)b); }
}
@@ -0,0 +1,37 @@
#define _USE_MATH_DEFINES
#include "Math.h"
namespace TLAC::Utilities
{
float ToDegrees(float radians)
{
return radians * (180.0f / M_PI);
}
float ToRadians(float degrees)
{
return (degrees * M_PI) / 180.0f;
}
Vec2 GetDirection(float degrees)
{
float radians = ToRadians(degrees);
return Vec2(cos(radians), sin(radians));
}
Vec2 PointFromAngle(float degrees, float distance)
{
float radians = ToRadians(degrees + 90.0f);
return Vec2(-1 * std::cos(radians) * distance, -1 * std::sin(radians) * distance);
}
float AngleFromPoints(Vec2 p0, Vec2 p1)
{
return (float)(std::atan2(p1.Y - p0.Y, p1.X - p0.X) * 180.0 / M_PI) + 90.0f;
}
float ConvertRange(float originalStart, float originalEnd, float newStart, float newEnd, float value)
{
return newStart + ((value - originalStart) * (newEnd - newStart) / (originalEnd - originalStart));
}
}
@@ -0,0 +1,15 @@
#pragma once
#include <cmath>
#include "Vec2.h"
#include "Vec3.h"
namespace TLAC::Utilities
{
float ToDegrees(float radians);
float ToRadians(float degrees);
Vec2 GetDirection(float degrees);
Vec2 PointFromAngle(float degrees, float distance);
float AngleFromPoints(Vec2 p0, Vec2 p1);
float ConvertRange(float originalStart, float originalEnd, float newStart, float newEnd, float value);
}
@@ -0,0 +1,60 @@
#pragma once
#include "Operations.h"
namespace TLAC::Utilities
{
std::vector<std::string> Split(const std::string& str, const std::string& delim)
{
std::vector<std::string> tokens;
size_t prev = 0, pos = 0;
do
{
pos = str.find(delim, prev);
if (pos == std::string::npos)
pos = str.length();
std::string token = str.substr(prev, pos - prev);
if (!token.empty())
tokens.push_back(token);
prev = pos + delim.length();
} while (pos < str.length() && prev < str.length());
return tokens;
}
void LeftTrim(std::string &s)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch)
{
return !std::isspace(ch);
}));
}
void RightTrim(std::string &s)
{
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch)
{
return !std::isspace(ch);
}).base(), s.end());
}
void Trim(std::string &s)
{
s = trim(s);
}
std::string trim(const std::string& str, const std::string& whitespace)
{
const size_t strBegin = str.find_first_not_of(whitespace);
if (strBegin == std::string::npos)
return "";
const size_t strEnd = str.find_last_not_of(whitespace);
const size_t strRange = strEnd - strBegin + 1;
return str.substr(strBegin, strRange);
}
}
@@ -0,0 +1,16 @@
#pragma once
#include <algorithm>
#include <cctype>
#include <locale>
#include <vector>
namespace TLAC::Utilities
{
std::vector<std::string> Split(const std::string& str, const std::string& delim);
void LeftTrim(std::string &s);
void RightTrim(std::string &s);
void Trim(std::string &s);
std::string trim(const std::string& str, const std::string& whitespace = " \t");
}
@@ -0,0 +1,36 @@
#include "Stopwatch.h"
namespace TLAC::Utilities
{
Stopwatch::Stopwatch()
{
}
Stopwatch::~Stopwatch()
{
}
void Stopwatch::Start()
{
start = high_resolution_clock::now();
}
float Stopwatch::Stop()
{
end = high_resolution_clock::now();
return GetElapsed();
}
float Stopwatch::Restart()
{
float elapsed = Stop();
Start();
return elapsed;
}
float Stopwatch::GetElapsed()
{
return (float)(chrono::duration_cast<std::chrono::microseconds>(end - start).count() / TIME_FACTOR);
}
}
@@ -0,0 +1,30 @@
#pragma once
#include <chrono>
namespace chrono = std::chrono;
typedef chrono::time_point<chrono::steady_clock> steady_clock;
typedef chrono::high_resolution_clock high_resolution_clock;
namespace TLAC::Utilities
{
class Stopwatch
{
const float TIME_FACTOR = 1000.0f;
public:
Stopwatch();
~Stopwatch();
void Start();
float Stop();
float Restart();
float GetElapsed();
private:
steady_clock start;
steady_clock end;
};
}

Some files were not shown because too many files have changed in this diff Show More