diff --git a/source-code/data/plugins/components.ini b/source-code/data/plugins/components.ini index 0f82b96..369be77 100644 --- a/source-code/data/plugins/components.ini +++ b/source-code/data/plugins/components.ini @@ -48,3 +48,6 @@ debug_component = false # allows the usage of hold transfer target_inspector = true + +# saves high scores to plugins/scores.ini +score_saver = true diff --git a/source-code/source/plugins/Launcher/framework.h b/source-code/source/plugins/Launcher/framework.h index dafe78e..2828972 100644 --- a/source-code/source/plugins/Launcher/framework.h +++ b/source-code/source/plugins/Launcher/framework.h @@ -233,6 +233,8 @@ ConfigOptionBase* componentsArray[] = { new BooleanOption(L"debug_component", COMPONENTS_SECTION, COMPONENTS_FILE, L"Debug Component", L"Allows for changing game state (F4-F8 keys), using dev GUI and tests, and speeding up 2d animations/menus (hold SHIFT+TAB).", false, true), new BooleanOption(L"target_inspector", COMPONENTS_SECTION, COMPONENTS_FILE, L"Target Inspector", L"Enables hold transfers.", false, true), + + new BooleanOption(L"score_saver", COMPONENTS_SECTION, COMPONENTS_FILE, L"Score Saver", L"Saves high scores to plugins/scores.ini.", false, true), }; bool IsLineInFile(LPCSTR searchLine, LPCWSTR fileName) diff --git a/source-code/source/plugins/TLAC/Components/ComponentsManager.cpp b/source-code/source/plugins/TLAC/Components/ComponentsManager.cpp index 2a0deb2..8bac123 100644 --- a/source-code/source/plugins/TLAC/Components/ComponentsManager.cpp +++ b/source-code/source/plugins/TLAC/Components/ComponentsManager.cpp @@ -12,6 +12,7 @@ #include "CameraController.h" #include "DebugComponent.h" #include "ScaleComponent.h" +#include "ScoreSaver.h" #include "GameTargets/TargetInspector.h" using ConfigFile = TLAC::FileSystem::ConfigFile; @@ -41,6 +42,7 @@ namespace TLAC::Components new FrameRateManager(), new FastLoader(), new ScaleComponent(), + new ScoreSaver(), new StageManager(), new CameraController(), new DebugComponent(), diff --git a/source-code/source/plugins/TLAC/Components/ScoreSaver.cpp b/source-code/source/plugins/TLAC/Components/ScoreSaver.cpp new file mode 100644 index 0000000..a5b0b3c --- /dev/null +++ b/source-code/source/plugins/TLAC/Components/ScoreSaver.cpp @@ -0,0 +1,113 @@ +#include "ScoreSaver.h" +#include "../Constants.h" +#include "../framework.h" +#include +#include +#include +#pragma comment(lib, "detours.lib") + +namespace TLAC::Components +{ + WCHAR ScoreSaver::configPath[256]; + ScoreSaver::ScoreSaver() + { + std::string utf8path = TLAC::framework::GetModuleDirectory() + "/scores.ini"; + MultiByteToWideChar(CP_UTF8, 0, utf8path.c_str(), -1, ScoreSaver::configPath, 256); + } + + ScoreSaver::~ScoreSaver() + { + } + + const char* ScoreSaver::GetDisplayName() + { + return "score_saver"; + } + + void(__stdcall* ScoreSaver::divaInitResults)(void* cls) = (void(__stdcall*)(void* cls))RESULTS_INIT_ADDRESS; + void ScoreSaver::Initialize(ComponentsManager*) + { + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourAttach(&(PVOID&)ScoreSaver::divaInitResults, (PVOID)(ScoreSaver::hookedInitResults)); + DetourTransactionCommit(); + } + + void ScoreSaver::hookedInitResults(void* cls) + { + divaInitResults(cls); + + int clearRank = *(int*)(RESULTS_BASE_ADDRESS + 0xe8); + int insurance = *(int*)RESULTS_INSURANCE_ADDRESS; + + if (clearRank < 2 || insurance !=0) + return; + + // get the base for this specific set of results + uint64_t resultBase = *(uint64_t*)(RESULTS_BASE_ADDRESS + 0x100); + + int pvNum = *(int*)(resultBase + 0x2c); + int pvDifficulty = *(int*)(resultBase + 0x34); + int modifier = *(int*)(resultBase + 0x70); + + int* cntHitTypes = (int*)(resultBase + 0x158); + int combo = *(int*)(resultBase + 0x180); + int score = *(int*)(resultBase + 0x18c); + int percent = *(int*)(resultBase + 0x190); + + int checkField = ((short)score ^ ((short)cntHitTypes[0] << 16) ^ ((short)cntHitTypes[1]) ^ ((short)percent << 16) ^ ((short)combo)) * clearRank; + + + WCHAR keyBase[16]; // needs to be big enough to store pv.999.diff.4 + WCHAR key[32]; // needs to be big enough to store pv.999.diff.4.modifier + WCHAR val[16]; // needs to be big enough to store any int + + const WCHAR section[] = L"scores"; + + swprintf(keyBase, 16, L"pv.%03d.diff.%01d", pvNum, pvDifficulty); + + swprintf(key, 32, L"%ls.%ls", keyBase, L"score"); + int oldScore = GetPrivateProfileIntW(section, key, 0, ScoreSaver::configPath); + + if (score <= oldScore) + return; + + swprintf(key, 32, L"%ls.%ls", keyBase, L"combo"); + swprintf(val, 16, L"%d", combo); + WritePrivateProfileStringW(section, key, val, ScoreSaver::configPath); + + swprintf(key, 32, L"%ls.%ls", keyBase, L"cools"); + swprintf(val, 16, L"%d", cntHitTypes[0]); + WritePrivateProfileStringW(section, key, val, ScoreSaver::configPath); + + swprintf(key, 32, L"%ls.%ls", keyBase, L"modifier"); + swprintf(val, 16, L"%d", modifier); + WritePrivateProfileStringW(section, key, val, ScoreSaver::configPath); + + swprintf(key, 32, L"%ls.%ls", keyBase, L"percent"); + swprintf(val, 16, L"%d", percent); + WritePrivateProfileStringW(section, key, val, ScoreSaver::configPath); + + swprintf(key, 32, L"%ls.%ls", keyBase, L"rank"); + swprintf(val, 16, L"%d", clearRank); + WritePrivateProfileStringW(section, key, val, ScoreSaver::configPath); + + swprintf(key, 32, L"%ls.%ls", keyBase, L"score"); + swprintf(val, 16, L"%d", score); + WritePrivateProfileStringW(section, key, val, ScoreSaver::configPath); + + swprintf(key, 32, L"%ls.%ls", keyBase, L"check"); + swprintf(val, 16, L"%d", checkField); + WritePrivateProfileStringW(section, key, val, ScoreSaver::configPath); + } + + void ScoreSaver::Update() + { + return; + } + + void ScoreSaver::UpdateInput() + { + return; + } +} diff --git a/source-code/source/plugins/TLAC/Components/ScoreSaver.h b/source-code/source/plugins/TLAC/Components/ScoreSaver.h new file mode 100644 index 0000000..ee08765 --- /dev/null +++ b/source-code/source/plugins/TLAC/Components/ScoreSaver.h @@ -0,0 +1,26 @@ +#pragma once +#include "EmulatorComponent.h" +#include "../Constants.h" +#include + +namespace TLAC::Components +{ + class ScoreSaver : public EmulatorComponent + { + public: + ScoreSaver(); + ~ScoreSaver(); + + virtual const char* GetDisplayName() override; + + virtual void Initialize(ComponentsManager*) override; + virtual void Update() override; + virtual void UpdateInput() override; + + private: + static void(__stdcall* divaInitResults)(void* cls); + static void hookedInitResults(void* cls); + + static WCHAR configPath[256]; + }; +} diff --git a/source-code/source/plugins/TLAC/Constants.h b/source-code/source/plugins/TLAC/Constants.h index 4fdaf06..cc901ec 100644 --- a/source-code/source/plugins/TLAC/Constants.h +++ b/source-code/source/plugins/TLAC/Constants.h @@ -88,6 +88,10 @@ constexpr uint64_t GET_SLIDER_DOWN_ADDRESS = 0x0000000140618C20; constexpr uint64_t SHOULD_EXIT_BOOL_ADDRESS = 0x0000000140EDA6B0; constexpr uint64_t DOEXIT_ADDRESS = 0x000000014085B574; +constexpr uint64_t RESULTS_INIT_ADDRESS = 0x000000014065BBC0; +constexpr uint64_t RESULTS_BASE_ADDRESS = 0x000000014CC93830; +constexpr uint64_t RESULTS_INSURANCE_ADDRESS = 0x0000000141197E14; + #define XINPUT_A 0x00 #define XINPUT_B 0x01 #define XINPUT_X 0x02 diff --git a/source-code/source/plugins/TLAC/TLAC.vcxproj b/source-code/source/plugins/TLAC/TLAC.vcxproj index da181a9..6d8cf0f 100644 --- a/source-code/source/plugins/TLAC/TLAC.vcxproj +++ b/source-code/source/plugins/TLAC/TLAC.vcxproj @@ -1,4 +1,4 @@ - + @@ -195,6 +195,7 @@ + @@ -246,6 +247,7 @@ + diff --git a/source-code/source/plugins/TLAC/TLAC.vcxproj.filters b/source-code/source/plugins/TLAC/TLAC.vcxproj.filters index f131383..33c5ee7 100644 --- a/source-code/source/plugins/TLAC/TLAC.vcxproj.filters +++ b/source-code/source/plugins/TLAC/TLAC.vcxproj.filters @@ -192,6 +192,9 @@ Header Files + + Header Files + @@ -326,5 +329,8 @@ Source Files + + Source Files + \ No newline at end of file