Merge branch 'master' of somewhatlurker/PD-Loader into master

This commit is contained in:
somewhatlurker
2019-10-18 08:06:22 +00:00
committed by Gogs
2 changed files with 141 additions and 35 deletions
@@ -23,6 +23,11 @@ namespace TLAC::Components
ScoreSaver::~ScoreSaver() ScoreSaver::~ScoreSaver()
{ {
for (int diff = 0; diff < 4; diff++)
{
*(DivaScore**)(PLAYER_DATA_ADDRESS + diff * 0x18 + 0x5d0) = 0;
*(DivaScore**)(PLAYER_DATA_ADDRESS + diff * 0x18 + 0x5d8) = 0;
}
} }
const char* ScoreSaver::GetDisplayName() const char* ScoreSaver::GetDisplayName()
@@ -30,18 +35,13 @@ namespace TLAC::Components
return "score_saver"; return "score_saver";
} }
bool ScoreSaver::initCacheFinished = false;
void ScoreSaver::initCache() void ScoreSaver::initCache()
{ {
// build the score cache // build the score cache
UpdateScoreCache(); UpdateScoreCache();
UpdateClearCounts(); UpdateClearCounts();
initCacheFinished = true;
// update score begin and end vars from game
for (int diff = 0; diff < 4; diff++)
{
*(DivaScore**)(PLAYER_DATA_ADDRESS + diff * 0x18 + 0x5d0) = &ScoreCache[diff][0][0];
*(DivaScore**)(PLAYER_DATA_ADDRESS + diff * 0x18 + 0x5d8) = &ScoreCache[diff][1000][0]; // deliberately use 1000 to get past end of cache
}
} }
bool(__stdcall* ScoreSaver::divaInitResults)(void* cls) = (bool(__stdcall*)(void* cls))RESULTS_INIT_ADDRESS; bool(__stdcall* ScoreSaver::divaInitResults)(void* cls) = (bool(__stdcall*)(void* cls))RESULTS_INIT_ADDRESS;
@@ -307,19 +307,60 @@ namespace TLAC::Components
} }
} }
UpdateSingleScoreCacheEntry(pvNum, pvDifficulty, pvDifficultyIsEx); UpdateSingleScoreCacheEntry(pvNum, pvDifficulty, pvDifficultyIsEx, true);
UpdateClearCounts(); if (initCacheFinished) // don't update clear counts if they're not ready yet
UpdateClearCounts();
if (didInitialAddressUpdate) // don't set the addresses if they're not ready yet
FixScoreCacheAddresses(pvDifficulty);
return result; return result;
} }
bool ScoreSaver::didInitialAddressUpdate = false;
void ScoreSaver::Update() void ScoreSaver::Update()
{ {
if (*(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME && *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS == SUB_SELECTOR && initThread.joinable()) // the below stuff is only verified for operating in menus
if (*(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME && (*(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS == SUB_SELECTOR || *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS == SUB_GAME_SEL))
{ {
// it's actually fine to let the init happen in the background after reaching game state, but this is probably safer if (!didInitialAddressUpdate)
printf("[ScoreSaver] Waiting for initialisation..."); {
initThread.join(); if (initCacheFinished) // check for initThread to be done
{
// fix the addresses here instead of doing it unsafely in initThread
FixScoreCacheAddresses(0);
FixScoreCacheAddresses(1);
FixScoreCacheAddresses(2);
FixScoreCacheAddresses(3);
didInitialAddressUpdate = true;
}
}
else
{
// it probably doesn't really matter whether the initial address update is done first if I add some locks,
// but I feel better knowing that there won't be multiple things racing to modify the vector
// this does mean that with a lot of scores you can beat the loading into the game, thus not getting the new record banner etc. after a song....
int pvNum = *(int*)SELPV_CURRENT_SONG_ADDRESS;
int diff = *(int*)(GAME_INFO_ADDRESS);
int diffIsEx = *(int*)(GAME_INFO_ADDRESS + 0x4);
byte insurance = *(byte*)(GAME_INFO_ADDRESS + 0x14);
if (pvNum != currentPv || diff != currentDifficulty || diffIsEx != currentDifficultyIsEx || insurance != currentInsurance)
{
DivaScore* cachedScore = GetCachedScore(pvNum, diff, diffIsEx);
if (cachedScore == nullptr)
{
// create a score cache entry if none exists for current song
ScoreCache[diff].push_back(DivaScore(pvNum, diffIsEx));
// update score begin and end vars from game
FixScoreCacheAddresses(diff);
}
currentPv = pvNum;
currentDifficulty = diff;
currentDifficultyIsEx = diffIsEx;
currentInsurance = insurance;
}
}
} }
} }
@@ -338,8 +379,27 @@ namespace TLAC::Components
VirtualProtect(address, byteCount, oldProtect, nullptr); VirtualProtect(address, byteCount, oldProtect, nullptr);
} }
ScoreSaver::DivaScore ScoreSaver::ScoreCache[4][1000][2]; // 4 difficulties * 1000 pvs * extra or not std::vector<ScoreSaver::DivaScore> ScoreSaver::ScoreCache[4] = { // * 4 difficulties
void ScoreSaver::UpdateSingleScoreCacheEntry(int pvNum, int diff, int exDiff) {},
{},
{},
{}
};
ScoreSaver::DivaScore* ScoreSaver::GetCachedScore(int pvNum, int diff, int exDiff)
{
if (pvNum < 0 || diff < 0 || exDiff < 0 || pvNum > 999 || diff > 3 || exDiff > 1)
return nullptr;
for (DivaScore &scoreinfo : ScoreCache[diff])
{
if (scoreinfo.pvNum == pvNum && scoreinfo.exDifficulty == exDiff)
return &scoreinfo;
}
return nullptr;
}
void ScoreSaver::UpdateSingleScoreCacheEntry(int pvNum, int diff, int exDiff, bool doDefaultsReset)
{ {
if (pvNum < 0 || diff < 0 || exDiff < 0 || pvNum > 999 || diff > 3 || exDiff > 1) if (pvNum < 0 || diff < 0 || exDiff < 0 || pvNum > 999 || diff > 3 || exDiff > 1)
return; return;
@@ -392,13 +452,34 @@ namespace TLAC::Components
modifiers = modifiers > 0 ? 1 << (modifiers - 1) : 0; modifiers = modifiers > 0 ? 1 << (modifiers - 1) : 0;
} }
DivaScore* cachedScore = &ScoreCache[diff][pvNum][exDiff]; DivaScore* cachedScore = GetCachedScore(pvNum, diff, exDiff);
cachedScore->score = score; if (cachedScore == nullptr)
cachedScore->percent = percent; {
cachedScore->clearRank = allTimeRank; ScoreCache[diff].push_back(DivaScore(pvNum, exDiff));
if (modifiers & 1) cachedScore->optionA = 1; cachedScore = GetCachedScore(pvNum, diff, exDiff);
if (modifiers & 2) cachedScore->optionB = 1; }
if (modifiers & 4) cachedScore->optionC = 1; if (cachedScore != nullptr)
{
cachedScore->score = score;
cachedScore->percent = percent;
cachedScore->clearRank = allTimeRank;
if (modifiers & 1) cachedScore->optionA = 1;
if (modifiers & 2) cachedScore->optionB = 1;
if (modifiers & 4) cachedScore->optionC = 1;
}
}
else if (doDefaultsReset) // reset to defaults if not valid
{
DivaScore* cachedScore = GetCachedScore(pvNum, diff, exDiff);
if (cachedScore != nullptr)
{
cachedScore->score = 0;
cachedScore->percent = 0;
cachedScore->clearRank = -1;
cachedScore->optionA = 0;
cachedScore->optionB = 0;
cachedScore->optionC = 0;
}
} }
} }
@@ -443,10 +524,28 @@ namespace TLAC::Components
allTimeRank = GetPrivateProfileIntW(section, key, -1, rival_configPath); allTimeRank = GetPrivateProfileIntW(section, key, -1, rival_configPath);
} }
DivaScore* cachedScore = &ScoreCache[diff][pvNum][exDiff]; if (score > 0 || percent > 0)
cachedScore->rival_clearRank = allTimeRank; {
cachedScore->rival_score = score; DivaScore* cachedScore = GetCachedScore(pvNum, diff, exDiff);
cachedScore->rival_percent = percent; if (cachedScore == nullptr)
{
ScoreCache[diff].push_back(DivaScore(pvNum, exDiff));
cachedScore = GetCachedScore(pvNum, diff, exDiff);
}
if (cachedScore != nullptr)
{
cachedScore->rival_clearRank = allTimeRank;
cachedScore->rival_score = score;
cachedScore->rival_percent = percent;
}
}
}
void ScoreSaver::FixScoreCacheAddresses(int diff)
{
// update score begin and end vars from game
*(DivaScore**)(PLAYER_DATA_ADDRESS + diff * 0x18 + 0x5d0) = ScoreCache[diff].begin()._Ptr;
*(DivaScore**)(PLAYER_DATA_ADDRESS + diff * 0x18 + 0x5d8) = ScoreCache[diff].end()._Ptr;
} }
void ScoreSaver::UpdateScoreCache() void ScoreSaver::UpdateScoreCache()
@@ -457,8 +556,7 @@ namespace TLAC::Components
{ {
for (int exDiff = 0; exDiff < 2; exDiff++) for (int exDiff = 0; exDiff < 2; exDiff++)
{ {
ScoreCache[diff][pvNum][exDiff] = DivaScore(pvNum, exDiff); UpdateSingleScoreCacheEntry(pvNum, diff, exDiff, false);
UpdateSingleScoreCacheEntry(pvNum, diff, exDiff);
UpdateSingleScoreCacheRivalEntry(pvNum, diff, exDiff); UpdateSingleScoreCacheRivalEntry(pvNum, diff, exDiff);
} }
} }
@@ -475,9 +573,8 @@ namespace TLAC::Components
for (int diff = 0; diff < 4; diff++) for (int diff = 0; diff < 4; diff++)
{ {
for (int pvNum = 0; pvNum < 1000; pvNum++) for (DivaScore &scoreinfo : ScoreCache[diff])
{ {
DivaScore &scoreinfo = ScoreCache[diff][pvNum][0];
if (scoreinfo.clearRank > 1 && scoreinfo.clearRank <= 5 && scoreinfo.exDifficulty == 0) // at least clear and no greater than perfect and not ex if (scoreinfo.clearRank > 1 && scoreinfo.clearRank <= 5 && scoreinfo.exDifficulty == 0) // at least clear and no greater than perfect and not ex
{ {
counts[diff * 4 + scoreinfo.clearRank - 2] += 1; counts[diff * 4 + scoreinfo.clearRank - 2] += 1;
@@ -486,10 +583,9 @@ namespace TLAC::Components
} }
// exex special case // exex special case
for (int pvNum = 0; pvNum < 1000; pvNum++) for (DivaScore &scoreinfo : ScoreCache[3])
{ {
DivaScore &scoreinfo = ScoreCache[3][pvNum][1]; if (scoreinfo.clearRank > 1 && scoreinfo.clearRank <= 5 && scoreinfo.exDifficulty == 1) // at least clear and no greater than perfect and IS ex
if (scoreinfo.clearRank > 1 && scoreinfo.clearRank <= 5 && scoreinfo.exDifficulty == 1) // at least clear and no greater than perfect and not ex
{ {
counts[4 * 4 + scoreinfo.clearRank - 2] += 1; counts[4 * 4 + scoreinfo.clearRank - 2] += 1;
} }
@@ -99,11 +99,13 @@ namespace TLAC::Components
}; };
static DivaScore ScoreCache[4][1000][2]; // 4 difficulties * 1000 pvs * extra or not static std::vector<ScoreSaver::DivaScore> ScoreCache[4]; // * 4 difficulties
static void UpdateScoreCache(); static void UpdateScoreCache();
static void UpdateSingleScoreCacheEntry(int pvNum, int diff, int exDiff); static void UpdateSingleScoreCacheEntry(int pvNum, int diff, int exDiff, bool doDefaultsReset);
static void UpdateSingleScoreCacheRivalEntry(int pvNum, int diff, int exDiff); static void UpdateSingleScoreCacheRivalEntry(int pvNum, int diff, int exDiff);
static void FixScoreCacheAddresses(int diff); // only call this from the main thread
static DivaScore* GetCachedScore(int pvNum, int diff, int exDiff);
static void UpdateClearCounts(); static void UpdateClearCounts();
private: private:
@@ -117,5 +119,13 @@ namespace TLAC::Components
static WCHAR configPath[256]; static WCHAR configPath[256];
static WCHAR rival_configPath[256]; static WCHAR rival_configPath[256];
static std::thread initThread; static std::thread initThread;
int currentPv;
int currentDifficulty;
int currentDifficultyIsEx;
byte currentInsurance;
static bool initCacheFinished;
static bool didInitialAddressUpdate;
}; };
} }