Merge branch 'feature-highscores' of https://github.com/stella-emu/stella into feature-highscores

This commit is contained in:
thrust26 2020-07-31 10:50:36 +02:00
commit d43d8c6730
5 changed files with 56 additions and 53 deletions

View File

@ -120,8 +120,9 @@ bool HighScoresManager::enabled() const
uInt32 HighScoresManager::numVariations(const Properties& props) const uInt32 HighScoresManager::numVariations(const Properties& props) const
{ {
string numVariations = getPropIdx(props, PropType::Cart_Variations); string numVariations = getPropIdx(props, PropType::Cart_Variations);
uInt32 maxVariations = MAX_VARIATIONS;
return min(uInt32(stringToInt(numVariations, DEFAULT_VARIATION)), MAX_VARIATIONS); return min(uInt32(stringToInt(numVariations, DEFAULT_VARIATION)), maxVariations);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -161,8 +162,9 @@ void HighScoresManager::set(Properties& props, uInt32 numVariations,
{ {
ostringstream buf; ostringstream buf;
string output; string output;
uInt32 maxVariations = MAX_VARIATIONS;
props.set(PropType::Cart_Variations, to_string(min(numVariations, MAX_VARIATIONS))); props.set(PropType::Cart_Variations, to_string(min(numVariations, maxVariations)));
// fill from the back to skip default values // fill from the back to skip default values
if (output.length() || !info.notes.empty()) if (output.length() || !info.notes.empty())
@ -211,16 +213,18 @@ void HighScoresManager::set(Properties& props, uInt32 numVariations,
uInt32 HighScoresManager::numDigits(const Properties& props) const uInt32 HighScoresManager::numDigits(const Properties& props) const
{ {
string digits = getPropIdx(props, PropType::Cart_Formats, IDX_SCORE_DIGITS); string digits = getPropIdx(props, PropType::Cart_Formats, IDX_SCORE_DIGITS);
uInt32 maxScoreDigits = MAX_SCORE_DIGITS;
return min(uInt32(stringToInt(digits, DEFAULT_DIGITS)), MAX_SCORE_DIGITS); return min(uInt32(stringToInt(digits, DEFAULT_DIGITS)), maxScoreDigits);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 HighScoresManager::trailingZeroes(const Properties& props) const uInt32 HighScoresManager::trailingZeroes(const Properties& props) const
{ {
string trailing = getPropIdx(props, PropType::Cart_Formats, IDX_TRAILING_ZEROES); string trailing = getPropIdx(props, PropType::Cart_Formats, IDX_TRAILING_ZEROES);
const uInt32 maxTrailing = MAX_TRAILING;
return min(uInt32(stringToInt(trailing, DEFAULT_TRAILING)), MAX_TRAILING); return min(uInt32(stringToInt(trailing, DEFAULT_TRAILING)), maxTrailing);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -357,11 +361,12 @@ Int32 HighScoresManager::variation() const
Properties props; Properties props;
uInt16 addr = varAddress(properties(props)); uInt16 addr = varAddress(properties(props));
if(addr == DEFAULT_ADDRESS) if(addr == DEFAULT_ADDRESS) {
if(numVariations() == 1) if(numVariations() == 1)
return DEFAULT_VARIATION; return DEFAULT_VARIATION;
else else
return NO_VALUE; return NO_VALUE;
}
return variation(addr, varBCD(props), varZeroBased(props), numVariations(props)); return variation(addr, varBCD(props), varZeroBased(props), numVariations(props));
} }
@ -378,7 +383,7 @@ Int32 HighScoresManager::score(uInt32 numAddrBytes, uInt32 trailingZeroes,
for (uInt32 b = 0; b < numAddrBytes; ++b) for (uInt32 b = 0; b < numAddrBytes; ++b)
{ {
uInt16 addr = scoreAddr[b]; uInt16 addr = scoreAddr[b];
uInt32 score; Int32 score;
totalScore *= isBCD ? 100 : 256; totalScore *= isBCD ? 100 : 256;
score = peek(addr); score = peek(addr);
@ -486,7 +491,7 @@ string HighScoresManager::notes() const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int32 HighScoresManager::convert(uInt32 val, uInt32 maxVal, bool isBCD, bool zeroBased) const Int32 HighScoresManager::convert(Int32 val, uInt32 maxVal, bool isBCD, bool zeroBased) const
{ {
maxVal += zeroBased ? 0 : 1; maxVal += zeroBased ? 0 : 1;
Int32 bits = isBCD Int32 bits = isBCD

View File

@ -29,16 +29,16 @@ class OSystem;
*/ */
namespace HSM { namespace HSM {
static const uInt32 MAX_SCORE_DIGITS = 8; static constexpr uInt32 MAX_SCORE_DIGITS = 8;
static const uInt32 MAX_ADDR_CHARS = MAX_SCORE_DIGITS / 2; static constexpr uInt32 MAX_ADDR_CHARS = MAX_SCORE_DIGITS / 2;
static const uInt32 MAX_SCORE_ADDR = 4; static constexpr uInt32 MAX_SCORE_ADDR = 4;
static const uInt32 MAX_SPECIAL_NAME = 5; static constexpr uInt32 MAX_SPECIAL_NAME = 5;
static const uInt32 MAX_SPECIAL_DIGITS = 3; static constexpr uInt32 MAX_SPECIAL_DIGITS = 3;
static const uInt32 DEFAULT_VARIATION = 1; static constexpr uInt32 DEFAULT_VARIATION = 1;
static const uInt32 DEFAULT_ADDRESS = 0; static constexpr uInt32 DEFAULT_ADDRESS = 0;
static const Int32 NO_VALUE = -1; static constexpr Int32 NO_VALUE = -1;
using ScoreAddresses = array<Int16, MAX_SCORE_ADDR>; using ScoreAddresses = array<Int16, MAX_SCORE_ADDR>;
@ -62,9 +62,6 @@ namespace HSM {
}; };
} // namespace HSM } // namespace HSM
using namespace HSM;
/** /**
This class provides an interface to define, load and save scores. It is meant This class provides an interface to define, load and save scores. It is meant
for games which do not support saving highscores. for games which do not support saving highscores.
@ -88,12 +85,12 @@ class HighScoresManager
@return True if highscore data exists, else false @return True if highscore data exists, else false
*/ */
bool get(const Properties& props, uInt32& numVariations, bool get(const Properties& props, uInt32& numVariations,
ScoresInfo& info) const; HSM::ScoresInfo& info) const;
/** /**
Set the highscore data of game's properties Set the highscore data of game's properties
*/ */
void set(Properties& props, uInt32 numVariations, void set(Properties& props, uInt32 numVariations,
const ScoresInfo& info) const; const HSM::ScoresInfo& info) const;
/** /**
Calculate the number of bytes for one player's score from given parameters Calculate the number of bytes for one player's score from given parameters
@ -110,7 +107,7 @@ class HighScoresManager
@return The current score or -1 if no valid data exists @return The current score or -1 if no valid data exists
*/ */
Int32 score(uInt32 numAddrBytes, uInt32 trailingZeroes, bool isBCD, Int32 score(uInt32 numAddrBytes, uInt32 trailingZeroes, bool isBCD,
const ScoreAddresses& scoreAddr) const; const HSM::ScoreAddresses& scoreAddr) const;
Int32 special(uInt16 addr, bool varBCD, bool zeroBased) const; Int32 special(uInt16 addr, bool varBCD, bool zeroBased) const;
@ -126,7 +123,7 @@ class HighScoresManager
// converts the given value, using only the maximum bits required by maxVal // converts the given value, using only the maximum bits required by maxVal
// and adjusted for BCD and zero based data // and adjusted for BCD and zero based data
Int32 convert(uInt32 val, uInt32 maxVal, bool isBCD, bool zeroBased) const; Int32 convert(Int32 val, uInt32 maxVal, bool isBCD, bool zeroBased) const;
// Peek into memory // Peek into memory
Int16 peek(uInt16 addr) const; Int16 peek(uInt16 addr) const;
@ -150,18 +147,18 @@ class HighScoresManager
IDX_SPECIAL_ADDRESS IDX_SPECIAL_ADDRESS
}; };
static const uInt32 MAX_VARIATIONS = 256; static constexpr uInt32 MAX_VARIATIONS = 256;
static const uInt32 MAX_TRAILING = 3; static constexpr uInt32 MAX_TRAILING = 3;
static const bool DEFAULT_ARM_RAM = false; static constexpr bool DEFAULT_ARM_RAM = false;
static const uInt32 DEFAULT_DIGITS = 4; static constexpr uInt32 DEFAULT_DIGITS = 4;
static const uInt32 DEFAULT_TRAILING = 0; static constexpr uInt32 DEFAULT_TRAILING = 0;
static const bool DEFAULT_SCORE_BCD = true; static constexpr bool DEFAULT_SCORE_BCD = true;
static const bool DEFAULT_SCORE_REVERSED = false; static constexpr bool DEFAULT_SCORE_REVERSED = false;
static const bool DEFAULT_VARS_BCD = true; static constexpr bool DEFAULT_VARS_BCD = true;
static const bool DEFAULT_VARS_ZERO_BASED = false; static constexpr bool DEFAULT_VARS_ZERO_BASED = false;
static const bool DEFAULT_SPECIAL_BCD = true; static constexpr bool DEFAULT_SPECIAL_BCD = true;
static const bool DEFAULT_SPECIAL_ZERO_BASED = false; static constexpr bool DEFAULT_SPECIAL_ZERO_BASED = false;
private: private:
// Get individual highscore info from properties // Get individual highscore info from properties

View File

@ -37,11 +37,12 @@ CommandMenu::~CommandMenu()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dialog* CommandMenu::baseDialog() Dialog* CommandMenu::baseDialog()
{ {
if (myBaseDialog == nullptr) if (myBaseDialog == nullptr) {
if (myOSystem.settings().getBool("minimal_ui")) if (myOSystem.settings().getBool("minimal_ui"))
myBaseDialog = new MinUICommandDialog(myOSystem, *this); myBaseDialog = new MinUICommandDialog(myOSystem, *this);
else else
myBaseDialog = new CommandDialog(myOSystem, *this); myBaseDialog = new CommandDialog(myOSystem, *this);
}
return myBaseDialog; return myBaseDialog;
} }

View File

@ -536,7 +536,7 @@ void GameInfoDialog::addHighScoresTab()
vwidth = _font.getStringWidth("AB") + 3; vwidth = _font.getStringWidth("AB") + 3;
items.clear(); items.clear();
for (int i = 1; i <= HSM::MAX_SCORE_DIGITS; ++i) for (uInt32 i = 1; i <= HSM::MAX_SCORE_DIGITS; ++i)
VarList::push_back(items, std::to_string(i), std::to_string(i)); VarList::push_back(items, std::to_string(i), std::to_string(i));
myScoreDigitsLabel = new StaticTextWidget(myTab, _font, xpos, ypos + 1, "Digits "); myScoreDigitsLabel = new StaticTextWidget(myTab, _font, xpos, ypos + 1, "Digits ");
@ -545,7 +545,7 @@ void GameInfoDialog::addHighScoresTab()
wid.push_back(myScoreDigits); wid.push_back(myScoreDigits);
items.clear(); items.clear();
for (int i = 0; i <= HSM::MAX_SCORE_DIGITS - 3; ++i) for (uInt32 i = 0; i <= HSM::MAX_SCORE_DIGITS - 3; ++i)
VarList::push_back(items, std::to_string(i), std::to_string(i)); VarList::push_back(items, std::to_string(i), std::to_string(i));
pwidth = _font.getStringWidth("0"); pwidth = _font.getStringWidth("0");
@ -837,12 +837,12 @@ void GameInfoDialog::loadHighScoresProperties(const Properties& props)
myHighScoreNotes->setText(info.notes); myHighScoreNotes->setText(info.notes);
ss.str(""); ss.str("");
ss << hex << right //<< setw(HSM::MAX_ADDR_CHARS) << setfill(' ') ss << hex << right // << setw(HSM::MAX_ADDR_CHARS) << setfill(' ')
<< uppercase << info.varsAddr; << uppercase << info.varsAddr;
myVarAddress->setText(ss.str()); myVarAddress->setText(ss.str());
ss.str(""); ss.str("");
ss << hex << right //<< setw(HSM::MAX_ADDR_CHARS) << setfill(' ') ss << hex << right // << setw(HSM::MAX_ADDR_CHARS) << setfill(' ')
<< uppercase << info.specialAddr; << uppercase << info.specialAddr;
mySpecialAddress->setText(ss.str()); mySpecialAddress->setText(ss.str());
@ -852,7 +852,7 @@ void GameInfoDialog::loadHighScoresProperties(const Properties& props)
ss.str(""); ss.str("");
if(a < instance().highScores().numAddrBytes(info.numDigits, info.trailingZeroes)) if(a < instance().highScores().numAddrBytes(info.numDigits, info.trailingZeroes))
{ {
ss << hex << right //<< setw(HSM::MAX_ADDR_CHARS) << setfill(' ') ss << hex << right // << setw(HSM::MAX_ADDR_CHARS) << setfill(' ')
<< uppercase << info.scoreAddr[a]; << uppercase << info.scoreAddr[a];
} }
myScoreAddress[a]->setText(ss.str()); myScoreAddress[a]->setText(ss.str());
@ -1268,9 +1268,9 @@ void GameInfoDialog::setAddressVal(EditTextWidget* addressWidget, EditTextWidget
val = instance().highScores().convert(val, maxVal, isBCD, zeroBased); val = instance().highScores().convert(val, maxVal, isBCD, zeroBased);
// format output and display in value widget // format output and display in value widget
//if (isBCD) // if (isBCD)
// ss << hex; // ss << hex;
ss << right //<< setw(2) << setfill(' ') ss << right // << setw(2) << setfill(' ')
<< uppercase << uInt16(val); << uppercase << uInt16(val);
valWidget->setText(ss.str()); valWidget->setText(ss.str());
} }

View File

@ -62,13 +62,13 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
int max_w, int max_h, int max_w, int max_h,
Menu::AppMode mode) Menu::AppMode mode)
: Dialog(osystem, parent, osystem.frameBuffer().font(), "High Scores"), : Dialog(osystem, parent, osystem.frameBuffer().font(), "High Scores"),
myMode(mode), myDirty(false),
myHighScoreSaved(false),
_max_w(max_w), _max_w(max_w),
_max_h(max_h), _max_h(max_h),
myVariation(HSM::DEFAULT_VARIATION), myVariation(HSM::DEFAULT_VARIATION),
myInitials(""), myInitials(""),
myDirty(false), myMode(mode)
myHighScoreSaved(false)
{ {
const GUI::Font& ifont = instance().frameBuffer().infoFont(); const GUI::Font& ifont = instance().frameBuffer().infoFont();
const int lineHeight = _font.getLineHeight(), const int lineHeight = _font.getLineHeight(),
@ -328,7 +328,7 @@ void HighScoresDialog::updateWidgets(bool init)
myPrevVarButton->setEnabled(myVariation > 1); myPrevVarButton->setEnabled(myVariation > 1);
myNextVarButton->setEnabled(myVariation < instance().highScores().numVariations()); myNextVarButton->setEnabled(myVariation < instance().highScores().numVariations());
for (Int32 r = 0; r < NUM_RANKS; ++r) for (uInt32 r = 0; r < NUM_RANKS; ++r)
{ {
ostringstream buf; ostringstream buf;
@ -354,7 +354,7 @@ void HighScoresDialog::updateWidgets(bool init)
myNameWidgets[r]->setLabel(myNames[r]); myNameWidgets[r]->setLabel(myNames[r]);
myDateWidgets[r]->setLabel(myDates[r]); myDateWidgets[r]->setLabel(myDates[r]);
if (r == myEditRank) if (static_cast<Int32>(r) == myEditRank)
{ {
myNameWidgets[r]->setFlags(EditTextWidget::FLAG_INVISIBLE); myNameWidgets[r]->setFlags(EditTextWidget::FLAG_INVISIBLE);
myEditNameWidgets[r]->clearFlags(EditTextWidget::FLAG_INVISIBLE); myEditNameWidgets[r]->clearFlags(EditTextWidget::FLAG_INVISIBLE);
@ -384,7 +384,7 @@ void HighScoresDialog::handlePlayedVariation()
Int32 newSpecial = instance().highScores().special(); Int32 newSpecial = instance().highScores().special();
bool scoreInvert = instance().highScores().scoreInvert(); bool scoreInvert = instance().highScores().scoreInvert();
for (myHighScoreRank = 0; myHighScoreRank < NUM_RANKS; ++myHighScoreRank) for (myHighScoreRank = 0; myHighScoreRank < static_cast<Int32>(NUM_RANKS); ++myHighScoreRank)
{ {
if ((!scoreInvert && newScore > myHighScores[myHighScoreRank]) || if ((!scoreInvert && newScore > myHighScores[myHighScoreRank]) ||
((scoreInvert && newScore < myHighScores[myHighScoreRank]) || myHighScores[myHighScoreRank] == 0)) ((scoreInvert && newScore < myHighScores[myHighScoreRank]) || myHighScores[myHighScoreRank] == 0))
@ -393,10 +393,10 @@ void HighScoresDialog::handlePlayedVariation()
break; break;
} }
if (myHighScoreRank < NUM_RANKS) if (myHighScoreRank < static_cast<Int32>(NUM_RANKS))
{ {
myEditRank = myHighScoreRank; myEditRank = myHighScoreRank;
for (Int32 r = NUM_RANKS - 1; r > myHighScoreRank; --r) for (uInt32 r = NUM_RANKS - 1; static_cast<Int32>(r) > myHighScoreRank; --r)
{ {
myHighScores[r] = myHighScores[r - 1]; myHighScores[r] = myHighScores[r - 1];
mySpecials[r] = mySpecials[r - 1]; mySpecials[r] = mySpecials[r - 1];
@ -416,7 +416,7 @@ void HighScoresDialog::handlePlayedVariation()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void HighScoresDialog::deleteRank(int rank) void HighScoresDialog::deleteRank(int rank)
{ {
for (Int32 r = rank; r < NUM_RANKS - 1; ++r) for (uInt32 r = rank; r < NUM_RANKS - 1; ++r)
{ {
myHighScores[r] = myHighScores[r + 1]; myHighScores[r] = myHighScores[r + 1];
mySpecials[r] = mySpecials[r + 1]; mySpecials[r] = mySpecials[r + 1];
@ -510,7 +510,7 @@ void HighScoresDialog::saveHighScores(Int32 variation) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void HighScoresDialog::loadHighScores(Int32 variation) void HighScoresDialog::loadHighScores(Int32 variation)
{ {
for (Int32 r = 0; r < NUM_RANKS; ++r) for (uInt32 r = 0; r < NUM_RANKS; ++r)
{ {
myHighScores[r] = 0; myHighScores[r] = 0;
mySpecials[r] = 0; mySpecials[r] = 0;
@ -562,7 +562,7 @@ bool HighScoresDialog::save(Serializer& out, Int32 variation) const
out.putString(myMD5); out.putString(myMD5);
out.putInt(variation); out.putInt(variation);
for (Int32 r = 0; r < NUM_RANKS; ++r) for (uInt32 r = 0; r < NUM_RANKS; ++r)
{ {
out.putInt(myHighScores[r]); out.putInt(myHighScores[r]);
out.putInt(mySpecials[r]); out.putInt(mySpecials[r]);
@ -588,7 +588,7 @@ bool HighScoresDialog::load(Serializer& in, Int32 variation)
if (Int32(in.getInt()) != variation) if (Int32(in.getInt()) != variation)
return false; return false;
for (Int32 r = 0; r < NUM_RANKS; ++r) for (uInt32 r = 0; r < NUM_RANKS; ++r)
{ {
myHighScores[r] = in.getInt(); myHighScores[r] = in.getInt();
mySpecials[r] = in.getInt(); mySpecials[r] = in.getInt();