score saver: trying the vector-based cache again
This commit is contained in:
@@ -23,6 +23,11 @@ namespace TLAC::Components
|
||||
|
||||
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()
|
||||
@@ -35,13 +40,6 @@ namespace TLAC::Components
|
||||
// build the score cache
|
||||
UpdateScoreCache();
|
||||
UpdateClearCounts();
|
||||
|
||||
// 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;
|
||||
@@ -307,7 +305,7 @@ namespace TLAC::Components
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSingleScoreCacheEntry(pvNum, pvDifficulty, pvDifficultyIsEx);
|
||||
UpdateSingleScoreCacheEntry(pvNum, pvDifficulty, pvDifficultyIsEx, true);
|
||||
UpdateClearCounts();
|
||||
|
||||
return result;
|
||||
@@ -315,11 +313,38 @@ namespace TLAC::Components
|
||||
|
||||
void ScoreSaver::Update()
|
||||
{
|
||||
if (*(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME && *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS == SUB_SELECTOR && initThread.joinable())
|
||||
if (*(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME && *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS == SUB_SELECTOR)
|
||||
{
|
||||
// it's actually fine to let the init happen in the background after reaching game state, but this is probably safer
|
||||
printf("[ScoreSaver] Waiting for initialisation...");
|
||||
initThread.join();
|
||||
if (initThread.joinable())
|
||||
{
|
||||
// it's actually fine to let the init happen in the background after reaching game state,
|
||||
// but this is safer because it means the begin and end addresses aren't changed in a different thread
|
||||
printf("[ScoreSaver] Waiting for initialisation...");
|
||||
initThread.join();
|
||||
}
|
||||
|
||||
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
|
||||
*(DivaScore**)(PLAYER_DATA_ADDRESS + diff * 0x18 + 0x5d0) = ScoreCache[diff].begin()._Ptr;
|
||||
*(DivaScore**)(PLAYER_DATA_ADDRESS + diff * 0x18 + 0x5d8) = ScoreCache[diff].end()._Ptr;
|
||||
}
|
||||
|
||||
currentPv = pvNum;
|
||||
currentDifficulty = diff;
|
||||
currentDifficultyIsEx = diffIsEx;
|
||||
currentInsurance = insurance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,8 +363,27 @@ namespace TLAC::Components
|
||||
VirtualProtect(address, byteCount, oldProtect, nullptr);
|
||||
}
|
||||
|
||||
ScoreSaver::DivaScore ScoreSaver::ScoreCache[4][1000][2]; // 4 difficulties * 1000 pvs * extra or not
|
||||
void ScoreSaver::UpdateSingleScoreCacheEntry(int pvNum, int diff, int exDiff)
|
||||
std::vector<ScoreSaver::DivaScore> ScoreSaver::ScoreCache[4] = { // * 4 difficulties
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
};
|
||||
|
||||
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)
|
||||
return;
|
||||
@@ -392,13 +436,38 @@ namespace TLAC::Components
|
||||
modifiers = modifiers > 0 ? 1 << (modifiers - 1) : 0;
|
||||
}
|
||||
|
||||
DivaScore* cachedScore = &ScoreCache[diff][pvNum][exDiff];
|
||||
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;
|
||||
DivaScore* cachedScore = GetCachedScore(pvNum, diff, exDiff);
|
||||
if (cachedScore == nullptr)
|
||||
{
|
||||
ScoreCache[diff].push_back(DivaScore(pvNum, exDiff));
|
||||
cachedScore = GetCachedScore(pvNum, diff, exDiff);
|
||||
|
||||
// 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;
|
||||
}
|
||||
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 +512,25 @@ namespace TLAC::Components
|
||||
allTimeRank = GetPrivateProfileIntW(section, key, -1, rival_configPath);
|
||||
}
|
||||
|
||||
DivaScore* cachedScore = &ScoreCache[diff][pvNum][exDiff];
|
||||
cachedScore->rival_clearRank = allTimeRank;
|
||||
cachedScore->rival_score = score;
|
||||
cachedScore->rival_percent = percent;
|
||||
if (score > 0 || percent > 0)
|
||||
{
|
||||
DivaScore* cachedScore = GetCachedScore(pvNum, diff, exDiff);
|
||||
if (cachedScore == nullptr)
|
||||
{
|
||||
ScoreCache[diff].push_back(DivaScore(pvNum, exDiff));
|
||||
cachedScore = GetCachedScore(pvNum, diff, exDiff);
|
||||
|
||||
// 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;
|
||||
}
|
||||
if (cachedScore != nullptr)
|
||||
{
|
||||
cachedScore->rival_clearRank = allTimeRank;
|
||||
cachedScore->rival_score = score;
|
||||
cachedScore->rival_percent = percent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScoreSaver::UpdateScoreCache()
|
||||
@@ -457,8 +541,7 @@ namespace TLAC::Components
|
||||
{
|
||||
for (int exDiff = 0; exDiff < 2; exDiff++)
|
||||
{
|
||||
ScoreCache[diff][pvNum][exDiff] = DivaScore(pvNum, exDiff);
|
||||
UpdateSingleScoreCacheEntry(pvNum, diff, exDiff);
|
||||
UpdateSingleScoreCacheEntry(pvNum, diff, exDiff, false);
|
||||
UpdateSingleScoreCacheRivalEntry(pvNum, diff, exDiff);
|
||||
}
|
||||
}
|
||||
@@ -475,9 +558,8 @@ namespace TLAC::Components
|
||||
|
||||
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
|
||||
{
|
||||
counts[diff * 4 + scoreinfo.clearRank - 2] += 1;
|
||||
@@ -486,10 +568,9 @@ namespace TLAC::Components
|
||||
}
|
||||
|
||||
// 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 not ex
|
||||
if (scoreinfo.clearRank > 1 && scoreinfo.clearRank <= 5 && scoreinfo.exDifficulty == 1) // at least clear and no greater than perfect and IS ex
|
||||
{
|
||||
counts[4 * 4 + scoreinfo.clearRank - 2] += 1;
|
||||
}
|
||||
|
||||
@@ -99,11 +99,12 @@ 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 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 DivaScore* GetCachedScore(int pvNum, int diff, int exDiff);
|
||||
static void UpdateClearCounts();
|
||||
|
||||
private:
|
||||
@@ -117,5 +118,10 @@ namespace TLAC::Components
|
||||
static WCHAR configPath[256];
|
||||
static WCHAR rival_configPath[256];
|
||||
static std::thread initThread;
|
||||
|
||||
int currentPv;
|
||||
int currentDifficulty;
|
||||
int currentDifficultyIsEx;
|
||||
byte currentInsurance;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user