mirror of https://github.com/stella-emu/stella.git
fixed high scores hashing
This commit is contained in:
parent
ba8132b10d
commit
4d2edc2922
|
@ -564,6 +564,24 @@ Int32 HighScoresManager::fromBCD(uInt8 bcd) const
|
||||||
return (bcd >> 4) * 10 + bcd % 16;
|
return (bcd >> 4) * 10 + bcd % 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
string HighScoresManager::hash(ScoresData& data) const
|
||||||
|
{
|
||||||
|
ostringstream buf;
|
||||||
|
|
||||||
|
buf << HIGHSCORE_HEADER << data.md5 << md5Props() << data.variation;
|
||||||
|
|
||||||
|
for(uInt32 r = 0; r < NUM_RANKS && data.scores[r].score; ++r)
|
||||||
|
{
|
||||||
|
buf << data.scores[r].score
|
||||||
|
<< data.scores[r].special
|
||||||
|
<< data.scores[r].name
|
||||||
|
<< data.scores[r].date;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MD5::hash(buf.str());
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void HighScoresManager::saveHighScores(ScoresData& data) const
|
void HighScoresManager::saveHighScores(ScoresData& data) const
|
||||||
{
|
{
|
||||||
|
@ -571,14 +589,13 @@ void HighScoresManager::saveHighScores(ScoresData& data) const
|
||||||
{
|
{
|
||||||
json hsObject = json::object();
|
json hsObject = json::object();
|
||||||
json hsData = json::object();
|
json hsData = json::object();
|
||||||
|
json jScores = json::array();
|
||||||
|
|
||||||
// Add header so that if the high score format changes in the future,
|
// Add header so that if the high score format changes in the future,
|
||||||
// we'll know right away, without having to parse the rest of the data
|
// we'll know right away, without having to parse the rest of the data
|
||||||
hsData[VERSION] = HIGHSCORE_HEADER;
|
hsObject[VERSION] = HIGHSCORE_HEADER;
|
||||||
hsData[MD5] = data.md5;
|
hsObject[MD5] = data.md5;
|
||||||
hsData[VARIATION] = data.variation;
|
hsObject[PROPCHECK] = md5Props();
|
||||||
|
|
||||||
json jScores = json::array();
|
|
||||||
|
|
||||||
for(uInt32 r = 0; r < NUM_RANKS && data.scores[r].score; ++r)
|
for(uInt32 r = 0; r < NUM_RANKS && data.scores[r].score; ++r)
|
||||||
{
|
{
|
||||||
|
@ -592,10 +609,10 @@ void HighScoresManager::saveHighScores(ScoresData& data) const
|
||||||
jScores.push_back(jScore);
|
jScores.push_back(jScore);
|
||||||
}
|
}
|
||||||
hsData[SCORES] = jScores;
|
hsData[SCORES] = jScores;
|
||||||
hsData[PROPCHECK] = md5Props();
|
hsData[VARIATION] = data.variation;
|
||||||
|
|
||||||
hsObject[DATA] = hsData;
|
hsObject[DATA] = hsData;
|
||||||
hsObject[CHECKSUM] = MD5::hash(hsData.dump());
|
hsObject[CHECKSUM] = hash(data);
|
||||||
|
|
||||||
myHighscoreRepository->save(data.md5, to_string(data.variation), hsObject.dump(2));
|
myHighscoreRepository->save(data.md5, to_string(data.variation), hsObject.dump(2));
|
||||||
}
|
}
|
||||||
|
@ -608,11 +625,11 @@ void HighScoresManager::saveHighScores(ScoresData& data) const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void HighScoresManager::loadHighScores(ScoresData& data)
|
void HighScoresManager::loadHighScores(ScoresData& data)
|
||||||
{
|
{
|
||||||
|
bool invalid = false;
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
|
|
||||||
clearHighScores(data);
|
clearHighScores(data);
|
||||||
|
|
||||||
bool invalid = false;
|
|
||||||
try {
|
try {
|
||||||
Variant serializedHighscore;
|
Variant serializedHighscore;
|
||||||
|
|
||||||
|
@ -620,27 +637,27 @@ void HighScoresManager::loadHighScores(ScoresData& data)
|
||||||
{
|
{
|
||||||
const json hsObject = json::parse(serializedHighscore.toString());
|
const json hsObject = json::parse(serializedHighscore.toString());
|
||||||
|
|
||||||
if(hsObject.contains(DATA))
|
// First test if we have a valid header
|
||||||
|
// If so, do a complete high score data load
|
||||||
|
if(!hsObject.contains(VERSION) || hsObject.at(VERSION) != HIGHSCORE_HEADER)
|
||||||
|
buf << "Error: Incompatible high scores data for variation " << data.variation << ".";
|
||||||
|
else if(hsObject.contains(DATA))
|
||||||
{
|
{
|
||||||
const json hsData = hsObject.at(DATA);
|
const json hsData = hsObject.at(DATA);
|
||||||
|
|
||||||
// First test if we have a valid header
|
if(!load(hsData, data)
|
||||||
// If so, do a complete high score data load
|
|| !hsObject.contains(MD5) || hsObject.at(MD5) != data.md5
|
||||||
if(!hsData.contains(VERSION) || hsData.at(VERSION) != HIGHSCORE_HEADER)
|
|| !hsObject.contains(PROPCHECK) || hsObject.at(PROPCHECK) != md5Props()
|
||||||
buf << "Error: Incompatible high scores data for variation " << data.variation << ".";
|
|| !hsObject.contains(CHECKSUM) || hsObject.at(CHECKSUM) != hash(data))
|
||||||
|
invalid = true;
|
||||||
else
|
else
|
||||||
{
|
return; // scores loaded OK
|
||||||
if(!load(hsData, data)
|
|
||||||
|| !hsData.contains(PROPCHECK) || hsData.at(PROPCHECK) != md5Props()
|
|
||||||
|| !hsObject.contains(CHECKSUM) || hsObject.at(CHECKSUM) != MD5::hash(hsData.dump()))
|
|
||||||
invalid = true;
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
invalid = true;
|
invalid = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return; // no scores for variation found
|
||||||
}
|
}
|
||||||
catch(...) { invalid = true; }
|
catch(...) { invalid = true; }
|
||||||
|
|
||||||
|
@ -655,8 +672,7 @@ void HighScoresManager::loadHighScores(ScoresData& data)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool HighScoresManager::load(const json& hsData, ScoresData& data)
|
bool HighScoresManager::load(const json& hsData, ScoresData& data)
|
||||||
{
|
{
|
||||||
if(!hsData.contains(MD5) || hsData.at(MD5) != data.md5
|
if(!hsData.contains(VARIATION) || hsData.at(VARIATION) != data.variation
|
||||||
|| !hsData.contains(VARIATION) || hsData.at(VARIATION) != data.variation
|
|
||||||
|| !hsData.contains(SCORES))
|
|| !hsData.contains(SCORES))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#ifndef HIGHSCORES_MANAGER_HXX
|
#ifndef HIGHSCORES_MANAGER_HXX
|
||||||
#define HIGHSCORES_MANAGER_HXX
|
#define HIGHSCORES_MANAGER_HXX
|
||||||
|
|
||||||
#define HIGHSCORE_HEADER "06010000highscores"
|
#define HIGHSCORE_HEADER "06050000highscores"
|
||||||
|
|
||||||
class OSystem;
|
class OSystem;
|
||||||
|
|
||||||
|
@ -232,6 +232,7 @@ class HighScoresManager
|
||||||
|
|
||||||
uInt16 fromHexStr(const string& addr) const;
|
uInt16 fromHexStr(const string& addr) const;
|
||||||
Int32 fromBCD(uInt8 bcd) const;
|
Int32 fromBCD(uInt8 bcd) const;
|
||||||
|
string hash(HSM::ScoresData& data) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Loads the current high scores for this game and variation from the given JSON object.
|
Loads the current high scores for this game and variation from the given JSON object.
|
||||||
|
|
|
@ -204,6 +204,8 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
addDefaultsOKCancelBGroup(wid, _font, "Save", "Cancel", " Reset ");
|
addDefaultsOKCancelBGroup(wid, _font, "Save", "Cancel", " Reset ");
|
||||||
_defaultWidget->setToolTip("Click to reset all high scores of this variation.");
|
_defaultWidget->setToolTip("Click to reset all high scores of this variation.");
|
||||||
addToFocusList(wid);
|
addToFocusList(wid);
|
||||||
|
|
||||||
|
_focusedWidget = _okWidget; // start with focus on 'Save' button
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
Loading…
Reference in New Issue