diff --git a/src/common/HighScoresManager.cxx b/src/common/HighScoresManager.cxx index a30888937..397d93be9 100644 --- a/src/common/HighScoresManager.cxx +++ b/src/common/HighScoresManager.cxx @@ -96,7 +96,8 @@ uInt32 HighScoresManager::numPlayers(const Properties& props) const { string numPlayers = getPropIdx(props, PropType::Cart_Players); - return numPlayers == EmptyString ? 1 : std::min(uInt32(stoi(numPlayers)), MAX_PLAYERS); + return numPlayers == EmptyString ? + DEFAULT_PLAYER : std::min(uInt32(stoi(numPlayers)), MAX_PLAYERS); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -104,35 +105,40 @@ uInt32 HighScoresManager::numVariations(const Properties& props) const { string numVariations = getPropIdx(props, PropType::Cart_Variations); - return numVariations == EmptyString ? 1 : std::min(stoi(numVariations), 256); + return numVariations == EmptyString ? + DEFAULT_VARIATION : std::min(uInt32(stoi(numVariations)), MAX_VARIATIONS); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool HighScoresManager::get(const Properties& props, Formats& formats, Addresses& addresses) const +bool HighScoresManager::get(const Properties& props, uInt32& numPlayersR, uInt32& numVariationsR, + Formats& formats, Addresses& addresses) const { + numPlayersR = numPlayers(props); + numVariationsR = numVariations(props); + formats.numDigits = numDigits(props); formats.trailingZeroes = trailingZeroes(props); formats.scoreBCD = scoreBCD(props); - formats.varBCD = varBCD(props); - formats.varZeroBased = varZeroBased(props); + formats.varsBCD = varBCD(props); + formats.varsZeroBased = varZeroBased(props); - addresses.playerAddr = playerAddress(props); - addresses.varAddr = varAddress(props); + addresses.playersAddr = playerAddress(props); + addresses.varsAddr = varAddress(props); for (uInt32 p = 0; p < MAX_PLAYERS; ++p) { - if (p < numPlayers(props)) + if (p < numPlayersR) { for (uInt32 a = 0; a < numAddrBytes(props); ++a) { uInt32 idx = p * numAddrBytes(props) + a; string addr = getPropIdx(props, PropType::Cart_Addresses, idx); - addresses.scoreAddr[p][a] = (addr == EmptyString ? 0 : stoi(addr, nullptr, 16)); + addresses.scoresAddr[p][a] = (addr == EmptyString ? 0 : stoi(addr, nullptr, 16)); } } else for (uInt32 a = 0; a < numAddrBytes(props); ++a) - addresses.scoreAddr[p][a] = -1; + addresses.scoresAddr[p][a] = -1; } return (EmptyString != getPropIdx(props, PropType::Cart_Addresses, 0)); @@ -145,23 +151,25 @@ void HighScoresManager::set(Properties& props, uInt32 numPlayers, uInt32 numVari ostringstream buf; props.set(PropType::Cart_Players, std::to_string(numPlayers)); - props.set(PropType::Cart_Variations, std::to_string(numVariations)); + props.set(PropType::Cart_Variations, std::to_string(std::min(numVariations, MAX_VARIATIONS))); + + buf << formats.numDigits << "," << formats.trailingZeroes << "," << (formats.scoreBCD ? "B" : "H") << "," - << (formats.varBCD ? "B" : "D") << "," - << formats.varZeroBased; + << (formats.varsBCD ? "B" : "D") << "," + << formats.varsZeroBased; props.set(PropType::Cart_Formats, buf.str()); buf.str(""); for (uInt32 p = 0; p < numPlayers; ++p) { for (uInt32 a = 0; a < numAddrBytes(formats.numDigits, formats.trailingZeroes); ++a) - buf << std::hex << addresses.scoreAddr[p][a] << ","; + buf << std::hex << addresses.scoresAddr[p][a] << ","; } - buf << addresses.varAddr << ","; - buf << addresses.playerAddr; + buf << addresses.varsAddr << ","; + buf << addresses.playersAddr; props.set(PropType::Cart_Addresses, buf.str()); } @@ -170,7 +178,7 @@ uInt32 HighScoresManager::numDigits(const Properties& props) const { string digits = getPropIdx(props, PropType::Cart_Formats, 0); - return digits == EmptyString ? 4 : stoi(digits); + return digits == EmptyString ? DEFAULT_DIGITS : stoi(digits); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -178,14 +186,14 @@ uInt32 HighScoresManager::trailingZeroes(const Properties& props) const { string trailing = getPropIdx(props, PropType::Cart_Formats, 1); - return trailing == EmptyString ? 0 : stoi(trailing);} + return trailing == EmptyString ? DEFAULT_TRAILING : stoi(trailing);} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool HighScoresManager::scoreBCD(const Properties& props) const { string bcd = getPropIdx(props, PropType::Cart_Formats, 2); - return bcd == EmptyString ? true : bcd == "B"; + return bcd == EmptyString ? DEFAULT_SCORE_BCD : bcd == "B"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -193,7 +201,7 @@ bool HighScoresManager::varBCD(const Properties& props) const { string bcd = getPropIdx(props, PropType::Cart_Formats, 3); - return bcd == EmptyString ? true : bcd == "B"; + return bcd == EmptyString ? DEFAULT_VARS_BCD : bcd == "B"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -201,16 +209,23 @@ bool HighScoresManager::varZeroBased(const Properties& props) const { string zeroBased = getPropIdx(props, PropType::Cart_Formats, 4); - return zeroBased == EmptyString ? false : zeroBased != "0"; + return zeroBased == EmptyString ? DEFAULT_VARS_ZERO_BASED : zeroBased != "0"; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool HighScoresManager::playerZeroBased(const Properties& props) const +{ + return DEFAULT_PLAYERS_ZERO_BASED; +} + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt16 HighScoresManager::playerAddress(const Properties& props) const { uInt32 idx = numAddrBytes(props) * numPlayers(props) + 1; string addr = getPropIdx(props, PropType::Cart_Addresses, idx); - return addr == EmptyString ? 0 : stoi(addr, nullptr, 16); + return addr == EmptyString ? DEFAULT_ADDRESS : stoi(addr, nullptr, 16); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -219,7 +234,7 @@ uInt16 HighScoresManager::varAddress(const Properties& props) const uInt32 idx = numAddrBytes(props) * numPlayers(props); string addr = getPropIdx(props, PropType::Cart_Addresses, idx); - return addr == EmptyString ? 0 : stoi(addr, nullptr, 16); + return addr == EmptyString ? DEFAULT_ADDRESS : stoi(addr, nullptr, 16); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -235,33 +250,27 @@ uInt32 HighScoresManager::numAddrBytes(const Properties& props) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Int32 HighScoresManager::score(uInt32 player, uInt32 numAddrBytes, uInt32 trailingZeroes, bool isBCD) const +Int32 HighScoresManager::score(uInt32 player, uInt32 numAddrBytes, uInt32 trailingZeroes, bool isBCD, + const ScoreAddresses& scoreAddr) const { if (!myOSystem.hasConsole()) return -1; - Properties props; // TODO: remove and replace adddress with real data - - System& system = myOSystem.console().system(); Int32 totalScore = 0; for (uInt32 b = 0; b < numAddrBytes; ++b) { - uInt32 idx = player * numAddrBytes + b; - string strAddr = getPropIdx(properties(props), PropType::Cart_Addresses, idx); - uInt16 addr = (strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16)); + uInt16 addr = scoreAddr[b]; uInt32 score; totalScore *= isBCD ? 100 : 256; - score = system.peek(addr); + score = peek(addr); if (isBCD) { // verify if score is legit if (score >= 160) - { - totalScore = -1; - break; - } + return -1; + score = (score >> 4) * 10 + score % 16; } totalScore += score; @@ -275,127 +284,46 @@ Int32 HighScoresManager::score(uInt32 player, uInt32 numAddrBytes, uInt32 traili } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Int32 HighScoresManager::score(const Properties& props, uInt32 player) const +Int32 HighScoresManager::player() const { - return score(player, numAddrBytes(props), trailingZeroes(props), scoreBCD(props)); + Properties props; + uInt16 addr = playerAddress(properties(props)); + + if (addr == DEFAULT_ADDRESS) + return DEFAULT_PLAYER; + + return peek(addr) + playerZeroBased(props) ? 1 : 0; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Int32 HighScoresManager::variation() const +{ + Properties props; + uInt16 addr = varAddress(properties(props)); + + if (addr == DEFAULT_ADDRESS) + return DEFAULT_VARIATION; + + return peek(addr) + varZeroBased(props) ? 1 : 0; +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool HighScoresManager::parseAddresses(uInt32& variation, uInt32& player, uInt32 scores[]) +Int32 HighScoresManager::score() const { - variation = 1; player = 0; scores[0] = 0; - - if (!myOSystem.hasConsole()) - return false; - - System& system = myOSystem.console().system(); - Properties props; - string formats = properties(props).get(PropType::Cart_Formats); - string addresses = properties(props).get(PropType::Cart_Addresses); - char scoreFormat; - char varFormat; - Int16 addr; - Int32 varAdd, numScoreAddr, scoreMult; + uInt32 numBytes = numAddrBytes(properties(props)); + uInt32 currentPlayer = player() - playerZeroBased(props) ? 1 : 0; + uInt32 idx = numBytes * currentPlayer; + ScoreAddresses scoreAddr; - // Since istringstream swallows whitespace, we have to make the - // delimiters be spaces - std::replace(formats.begin(), formats.end(), ',', ' '); - std::replace(formats.begin(), formats.end(), '|', ' '); - std::replace(addresses.begin(), addresses.end(), ',', ' '); - std::replace(addresses.begin(), addresses.end(), '|', ' '); - istringstream addrBuf(addresses); - istringstream formatBuf(formats); - - // 1. retrieve formats - if (!(formatBuf >> numScoreAddr)) - numScoreAddr = 2; - if (!(formatBuf >> scoreMult)) - scoreMult = 1; - if (!(formatBuf >> scoreFormat)) - scoreFormat = 'B'; - if (!(formatBuf >> varFormat)) - varFormat = 'B'; - if (!(formatBuf >> varAdd)) - varAdd = 0; - - // 2. retrieve current scores for all players - for (uInt32 i = 0; i < numPlayers(props); ++i) + for (uInt32 b = 0; b < numBytes; ++b) { - Int32 totalScore = 0; + string addr = getPropIdx(props, PropType::Cart_Addresses, idx + b); - for (int j = 0; j < numScoreAddr; ++j) - { - Int32 score; - - if (!(addrBuf >> std::hex >> addr)) - return false; - - totalScore *= (scoreFormat == 'B') ? 100 : 256; - - score = system.peek(addr); - if (scoreFormat == 'B') - score = (score >> 4) * 10 + score % 16; - totalScore += score; - } - scores[i] = totalScore * scoreMult; + if (addr == EmptyString) + return -1; + scoreAddr[b] = stoi(addr, nullptr, 16); } - // 3. retrieve current variation (0..255) - if (numVariations(props) == 1) - return true; - - if (!(addrBuf >> std::hex >> addr)) - return false; - variation = system.peek(addr); - if (varFormat == 'B') - variation = (variation >> 4) * 10 + variation % 16; - variation += varAdd; - variation = std::min(variation, numVariations(props)); - - // 4. retrieve current player (0..3) - if (numPlayers(props) == 1) - return true; - - if (!(addrBuf >> std::hex >> addr)) - return false; - - player = system.peek(addr); - player = std::min(player, numPlayers(props) - 1); - - return true; + return score(currentPlayer, numBytes, trailingZeroes(props), scoreBCD(props), scoreAddr); } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Int32 HighScoresManager::variation() -{ - uInt32 variation, player, scores[4]; - - if (parseAddresses(variation, player, scores)) - return variation; - - return -1; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Int32 HighScoresManager::player() -{ - uInt32 variation, player, scores[4]; - - if (parseAddresses(variation, player, scores)) - return player; - - return -1; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Int32 HighScoresManager::score() -{ - uInt32 variation, player, scores[4]; - - if (parseAddresses(variation, player, scores)) - return scores[std::min(player, uInt32(MAX_PLAYERS))]; - - return -1; -} \ No newline at end of file diff --git a/src/common/HighScoresManager.hxx b/src/common/HighScoresManager.hxx index def2733c3..74167827b 100644 --- a/src/common/HighScoresManager.hxx +++ b/src/common/HighScoresManager.hxx @@ -18,8 +18,6 @@ #ifndef HIGHSCORES_MANAGER_HXX #define HIGHSCORES_MANAGER_HXX -//#include "bspf.hxx" - class OSystem; class HighScoresManager @@ -29,21 +27,21 @@ public: static const uInt32 MAX_PLAYERS = 4; static const uInt32 MAX_SCORE_ADDR = 3; - using ScoreAddresses = BSPF::array2D; + using ScoreAddresses = array; + using ScoresAddresses = array; struct Formats { uInt32 numDigits; uInt32 trailingZeroes; bool scoreBCD; - bool varBCD; - bool varZeroBased; + bool varsBCD; + bool varsZeroBased; }; - struct Addresses { - ScoreAddresses scoreAddr; - uInt16 varAddr; - uInt16 playerAddr; + ScoresAddresses scoresAddr; + uInt16 varsAddr; + uInt16 playersAddr; }; HighScoresManager(OSystem& osystem); @@ -52,38 +50,50 @@ public: /* Methods for returning high scores related variables */ - uInt32 numVariations(const Properties& props) const; - uInt32 numPlayers(const Properties& props) const; - - bool get(const Properties& props, Formats& formats, Addresses& addresses) const; + bool get(const Properties& props, uInt32& numPlayers, uInt32& numVariations, + Formats& formats, Addresses& addresses) const; void set(Properties& props, uInt32 numPlayers, uInt32 numVariations, const Formats& formats, const Addresses& addresses) const; + uInt32 numAddrBytes(Int32 digits, Int32 trailing) const; + + Int32 score(uInt32 player, uInt32 numAddrBytes, uInt32 trailingZeroes, bool isBCD, + const ScoreAddresses& scoreAddr) const; + + // retrieve current values + Int32 player() const; + Int32 variation() const; + Int32 score() const; + +private: + static const uInt32 MAX_VARIATIONS = 256; + static const uInt32 DEFAULT_PLAYER = 1; + static const uInt32 DEFAULT_VARIATION = 1; + static const uInt32 DEFAULT_DIGITS = 4; + static const uInt32 DEFAULT_TRAILING = 0; + static const bool DEFAULT_SCORE_BCD = true; + static const bool DEFAULT_VARS_BCD = true; + static const bool DEFAULT_VARS_ZERO_BASED = false; + static const bool DEFAULT_PLAYERS_ZERO_BASED = true; + static const uInt32 DEFAULT_ADDRESS = 0; + +private: + uInt32 numVariations(const Properties& props) const; + uInt32 numPlayers(const Properties& props) const; + uInt16 varAddress(const Properties& props) const; + uInt16 playerAddress(const Properties& props) const; uInt32 numDigits(const Properties& props) const; uInt32 trailingZeroes(const Properties& props) const; bool scoreBCD(const Properties& props) const; bool varBCD(const Properties& props) const; bool varZeroBased(const Properties& props) const; + bool playerZeroBased(const Properties& props) const; - uInt16 varAddress(const Properties& props) const; - uInt16 playerAddress(const Properties& props) const; - - uInt32 numAddrBytes(Int32 digits, Int32 trailing) const; uInt32 numAddrBytes(const Properties& props) const; - // current values - Int32 player(); - Int32 variation(); - Int32 score(); - - Int32 score(uInt32 player, uInt32 numAddrBytes, uInt32 trailingZeroes, bool isBCD) const; - Int32 score(const Properties& props, uInt32 player) const; - -private: Properties& properties(Properties& props) const; string getPropIdx(const Properties& props, PropType type, uInt32 idx = 0) const; Int16 peek(uInt16 addr) const; - bool parseAddresses(uInt32& variation, uInt32& player, uInt32 scores[]); private: // Reference to the osystem object diff --git a/src/emucore/Props.cxx b/src/emucore/Props.cxx index ccad01646..e96a3f60b 100644 --- a/src/emucore/Props.cxx +++ b/src/emucore/Props.cxx @@ -265,6 +265,14 @@ void Properties::print() const << endl; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Properties::reset(PropType key) +{ + size_t pos = static_cast(key); + + myProperties[pos] = ourDefaultProperties[pos]; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Properties::setDefaults() { diff --git a/src/emucore/Props.hxx b/src/emucore/Props.hxx index dacc099e9..f40a3ba98 100644 --- a/src/emucore/Props.hxx +++ b/src/emucore/Props.hxx @@ -124,6 +124,13 @@ class Properties */ void setDefaults(); + /** + Resets the property of the given key to its default + + @param key The key of the property to set + */ + void reset(PropType key); + /** Overloaded equality operator(s) diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 033d6c218..26b56fdcf 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -352,6 +352,12 @@ GameInfoDialog::GameInfoDialog( wid.clear(); tabID = myTab->addTab("High Scores", TabWidget::AUTO_WIDTH); + EditableWidget::TextFilter fAddr = [](char c) { + return (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9'); + }; + EditableWidget::TextFilter fVars = [](char c) { + return (c >= '0' && c <= '9'); + }; xpos = HBORDER; ypos = VBORDER; lwidth = font.getStringWidth("Variations "); @@ -371,9 +377,6 @@ GameInfoDialog::GameInfoDialog( wid.push_back(myPlayers); int awidth = font.getStringWidth("FFFF") + 4; - EditableWidget::TextFilter fAddr = [](char c) { - return (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9'); - }; int vwidth = font.getStringWidth("123") + 4; myPlayersAddressLabel = new StaticTextWidget(myTab, font, myPlayers->getRight() + 16, ypos + 1, "Address "); @@ -389,6 +392,7 @@ GameInfoDialog::GameInfoDialog( vwidth = font.getStringWidth("123") + 4; myVariationsLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, lwidth, fontHeight, "Variations"); myVariations = new EditTextWidget(myTab, font, xpos + lwidth, ypos - 1, fwidth, lineHeight); + myVariations->setTextFilter(fVars); wid.push_back(myVariations); myVarAddressLabel = new StaticTextWidget(myTab, font, myPlayersAddressLabel->getLeft(), ypos + 1, "Address "); @@ -398,11 +402,11 @@ GameInfoDialog::GameInfoDialog( myVarAddressVal = new EditTextWidget(myTab, font, myVarAddress->getRight() + 2, ypos - 1, vwidth, lineHeight); myVarAddressVal->setEditable(false); - myVarBCD = new CheckboxWidget(myTab, font, myVarAddressVal->getRight() + 16, ypos + 1, "BCD", kVarBcdChanged); - wid.push_back(myVarBCD); + myVarsBCD = new CheckboxWidget(myTab, font, myVarAddressVal->getRight() + 16, ypos + 1, "BCD", kVarBcdChanged); + wid.push_back(myVarsBCD); - myVarZeroBased = new CheckboxWidget(myTab, font, myVarBCD->getRight() + 16, ypos + 1, "0-based", kVarZeroBasedChanged); - wid.push_back(myVarZeroBased); + myVarsZeroBased = new CheckboxWidget(myTab, font, myVarsBCD->getRight() + 16, ypos + 1, "0-based", kVarZeroBasedChanged); + wid.push_back(myVarsZeroBased); ypos += lineHeight + VGAP; @@ -436,7 +440,7 @@ GameInfoDialog::GameInfoDialog( items, "", 0, kScoreZeroesChanged); wid.push_back(myTrailingZeroes); - myScoreBCD = new CheckboxWidget(myTab, font, myVarBCD->getLeft(), ypos + 1, "BCD", kScoreBcdChanged); + myScoreBCD = new CheckboxWidget(myTab, font, myVarsBCD->getLeft(), ypos + 1, "BCD", kScoreBcdChanged); wid.push_back(myScoreBCD); @@ -658,40 +662,42 @@ void GameInfoDialog::loadHighScoresProperties(const Properties& props) { HighScoresManager::Formats formats; HighScoresManager::Addresses addresses; - bool enable = instance().highScores().get(props, formats, addresses); + uInt32 numPlayers, numVariations; + bool enable = instance().highScores().get(props, numPlayers, numVariations, + formats, addresses); myHighScores->setState(enable); - myPlayers->setSelected(instance().highScores().numPlayers(props)); - myVariations->setText(std::to_string(instance().highScores().numVariations(props))); + myPlayers->setSelected(numPlayers); + myVariations->setText(std::to_string(numVariations)); ostringstream ss; myScoreDigits->setSelected(formats.numDigits); myTrailingZeroes->setSelected(formats.trailingZeroes); myScoreBCD->setState(formats.scoreBCD); - myVarBCD->setState(formats.varBCD); - myVarZeroBased->setState(formats.varZeroBased); + myVarsBCD->setState(formats.varsBCD); + myVarsZeroBased->setState(formats.varsZeroBased); ss.str(""); ss << std::hex << std::right << std::setw(4) << std::setfill('0') - << std::uppercase << addresses.playerAddr; + << std::uppercase << addresses.playersAddr; myPlayersAddress->setText(ss.str()); ss.str(""); ss << std::hex << std::right << std::setw(4) << std::setfill('0') - << std::uppercase << addresses.varAddr; + << std::uppercase << addresses.varsAddr; myVarAddress->setText(ss.str()); for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p) { - for (uInt32 a = 0; a < instance().highScores().numAddrBytes(props); ++a) + for (uInt32 a = 0; a < instance().highScores().numAddrBytes(formats.numDigits, formats.trailingZeroes); ++a) { - if (p < instance().highScores().numPlayers(props)) + if (p < numPlayers) { ss.str(""); ss << std::hex << std::right << std::setw(4) << std::setfill('0') - << std::uppercase << addresses.scoreAddr[p][a]; + << std::uppercase << addresses.scoresAddr[p][a]; myScoreAddress[p][a]->setText(ss.str()); } else @@ -777,37 +783,45 @@ void GameInfoDialog::saveHighScoresProperties() HighScoresManager::Formats formats; HighScoresManager::Addresses addresses; - //myGameProperties.set(PropType::Cart_Players, myPlayers->getSelectedTag().toString()); - //myGameProperties.set(PropType::Cart_Variations, myVariations->getText()); - - //TODO: fill formats & addresses - formats.varZeroBased = myVarBCD->getState(); - formats.varBCD = myVarBCD->getState(); - formats.numDigits = myScoreDigits->getSelected() + 1; - formats.trailingZeroes = myTrailingZeroes->getSelected(); - formats.scoreBCD = myScoreBCD->getState(); - - string strAddr; - uInt16 addr; - - strAddr = myPlayersAddress->getText(); - addresses.playerAddr = strAddr == EmptyString ? 1 : stoi(strAddr, nullptr, 16); - strAddr = myVarAddress->getText(); - addresses.varAddr = strAddr == EmptyString ? 1 : stoi(strAddr, nullptr, 16); - - for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p) + if (myHighScores->getState()) { - for (uInt32 a = 0; a < HighScoresManager::MAX_SCORE_ADDR; ++a) - { - strAddr = myScoreAddress[p][a]->getText(); - addresses.scoreAddr[p][a] = strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16); - } - } + // fill formats + formats.varsZeroBased = myVarsZeroBased->getState(); + formats.varsBCD = myVarsBCD->getState(); + formats.numDigits = myScoreDigits->getSelected() + 1; + formats.trailingZeroes = myTrailingZeroes->getSelected(); + formats.scoreBCD = myScoreBCD->getState(); - strAddr = myVariations->getText(); - instance().highScores().set(myGameProperties, myPlayers->getSelected() + 1, - strAddr == EmptyString ? 1 : stoi(strAddr), - formats, addresses); + // fill addresses + string strAddr; + + strAddr = myPlayersAddress->getText(); + addresses.playersAddr = strAddr == EmptyString ? 1 : stoi(strAddr, nullptr, 16); + strAddr = myVarAddress->getText(); + addresses.varsAddr = strAddr == EmptyString ? 1 : stoi(strAddr, nullptr, 16); + + for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p) + { + for (uInt32 a = 0; a < HighScoresManager::MAX_SCORE_ADDR; ++a) + { + strAddr = myScoreAddress[p][a]->getText(); + addresses.scoresAddr[p][a] = strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16); + } + } + + string strVars = myVariations->getText(); + + instance().highScores().set(myGameProperties, myPlayers->getSelected() + 1, + strVars == EmptyString ? 1 : stoi(strVars), + formats, addresses); + } + else + { + myGameProperties.reset(PropType::Cart_Players); + myGameProperties.reset(PropType::Cart_Variations); + myGameProperties.reset(PropType::Cart_Formats); + myGameProperties.reset(PropType::Cart_Addresses); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -961,6 +975,7 @@ void GameInfoDialog::handleHighScoresWidgets() uInt32 numAddr = instance().highScores().numAddrBytes(myScoreDigits->getSelected() + 1, myTrailingZeroes->getSelected()); + // enable widgets myPlayersLabel->setEnabled(enable); myPlayers->setEnabled(enable); myPlayersAddressLabel->setEnabled(enablePlayers); @@ -975,8 +990,8 @@ void GameInfoDialog::handleHighScoresWidgets() myVarAddress->setEnabled(enableVars); myVarAddress->setEditable(enableVars); myVarAddressVal->setEnabled(enableVars); - myVarBCD->setEnabled(enableVars); - myVarZeroBased->setEnabled(enableVars); + myVarsBCD->setEnabled(enableVars); + myVarsZeroBased->setEnabled(enableVars); myScoresLabel->setEnabled(enable); myScoreDigitsLabel->setEnabled(enable); @@ -999,18 +1014,34 @@ void GameInfoDialog::handleHighScoresWidgets() myCurrentScore[p]->setEnabled(enable); } - setAddressVal(myPlayersAddress, myPlayersAddressVal); - setAddressVal(myVarAddress, myVarAddressVal, myVarBCD->getState(), myVarZeroBased->getState() ? 1 : 0); + // verify and update widget data + string strVars; + // limit variants size + strVars = myVariations->getText(); + strVars = strVars.substr(0, 3); + myVariations->setText(strVars); + + // update players and variations RAM values + setAddressVal(myPlayersAddress, myPlayersAddressVal); + setAddressVal(myVarAddress, myVarAddressVal, myVarsBCD->getState(), myVarsZeroBased->getState() ? 1 : 0); + + // update score RAM values and resulting scores for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p) { if (p < players) { + HighScoresManager::ScoreAddresses scoreAddr; + for (uInt32 a = 0; a < numAddr; ++a) + { setAddressVal(myScoreAddress[p][a], myScoreAddressVal[p][a]); + string strAddr = myScoreAddress[p][a]->getText(); + scoreAddr[a] = strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16); + } Int32 score = instance().highScores().score(p, numAddr, myTrailingZeroes->getSelected(), - myScoreBCD->getState()); + myScoreBCD->getState(), scoreAddr); if (score >= 0) { ostringstream ss; @@ -1032,21 +1063,27 @@ void GameInfoDialog::handleHighScoresWidgets() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void GameInfoDialog::setAddressVal(const EditTextWidget* addressWidget, EditTextWidget* valWidget, +void GameInfoDialog::setAddressVal(EditTextWidget* addressWidget, EditTextWidget* valWidget, bool isBCD, uInt8 incVal) { + string strAddr; + + // limit address size + strAddr = addressWidget->getText(); + strAddr = strAddr.substr(0, 4); + addressWidget->setText(strAddr); + if (instance().hasConsole() && valWidget->isEnabled()) { System& system = instance().console().system(); - string strAddr; uInt16 addr; uInt8 val; ostringstream ss; - strAddr = addressWidget->getText(); + // convert to number and read from memory addr = strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16); val = system.peek(addr) + incVal; - + // format output and display in value widget if (isBCD) ss << std::hex; ss << std::right << std::setw(2) << std::setfill('0') diff --git a/src/gui/GameInfoDialog.hxx b/src/gui/GameInfoDialog.hxx index b3cd81f27..30f94cce1 100644 --- a/src/gui/GameInfoDialog.hxx +++ b/src/gui/GameInfoDialog.hxx @@ -62,7 +62,7 @@ class GameInfoDialog : public Dialog, public CommandSender void updateControllerStates(); void eraseEEPROM(); void handleHighScoresWidgets(); - void setAddressVal(const EditTextWidget* address, EditTextWidget* val, bool isBCD = true, uInt8 incVal = 0); + void setAddressVal(EditTextWidget* address, EditTextWidget* val, bool isBCD = true, uInt8 incVal = 0); private: TabWidget* myTab{nullptr}; @@ -122,8 +122,8 @@ class GameInfoDialog : public Dialog, public CommandSender StaticTextWidget* myVarAddressLabel{ nullptr }; EditTextWidget* myVarAddress{ nullptr }; EditTextWidget* myVarAddressVal{ nullptr }; - CheckboxWidget* myVarBCD{ nullptr }; - CheckboxWidget* myVarZeroBased{ nullptr }; + CheckboxWidget* myVarsBCD{ nullptr }; + CheckboxWidget* myVarsZeroBased{ nullptr }; StaticTextWidget* myScoresLabel{ nullptr }; StaticTextWidget* myScoreDigitsLabel{ nullptr };