From a84630b14c947dce7e8320d053090db57a6df3fd Mon Sep 17 00:00:00 2001 From: thrust26 Date: Mon, 10 Feb 2020 23:26:15 +0100 Subject: [PATCH] refactor for saving props save props --- src/common/HighScoresManager.cxx | 202 +++++++++++++++++-------------- src/common/HighScoresManager.hxx | 39 +++--- src/gui/GameInfoDialog.cxx | 97 ++++++++++----- src/gui/GameInfoDialog.hxx | 2 + 4 files changed, 206 insertions(+), 134 deletions(-) diff --git a/src/common/HighScoresManager.cxx b/src/common/HighScoresManager.cxx index 32e1fd474..a30888937 100644 --- a/src/common/HighScoresManager.cxx +++ b/src/common/HighScoresManager.cxx @@ -34,7 +34,6 @@ */ #include "OSystem.hxx" -//#include "Props.hxx" #include "PropsSet.hxx" #include "Console.hxx" #include "Launcher.hxx" @@ -42,8 +41,6 @@ #include "HighScoresManager.hxx" - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HighScoresManager::HighScoresManager(OSystem& osystem) : myOSystem(osystem) @@ -51,7 +48,7 @@ HighScoresManager::HighScoresManager(OSystem& osystem) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Int16 HighScoresManager::peek(uInt16 addr) +Int16 HighScoresManager::peek(uInt16 addr) const { if (myOSystem.hasConsole()) { @@ -78,10 +75,10 @@ Properties& HighScoresManager::properties(Properties& props) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string HighScoresManager::getPropIdx(PropType type, uInt32 idx) const +string HighScoresManager::getPropIdx(const Properties& props, PropType type, uInt32 idx) const { - Properties props; - string property = properties(props).get(type); + string property = props.get(type); + std::replace(property.begin(), property.end(), ',', ' '); std::replace(property.begin(), property.end(), '|', ' '); istringstream buf(property); @@ -95,111 +92,132 @@ string HighScoresManager::getPropIdx(PropType type, uInt32 idx) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 HighScoresManager::numPlayers() const +uInt32 HighScoresManager::numPlayers(const Properties& props) const { - string numPlayers = getPropIdx(PropType::Cart_Players); + string numPlayers = getPropIdx(props, PropType::Cart_Players); return numPlayers == EmptyString ? 1 : std::min(uInt32(stoi(numPlayers)), MAX_PLAYERS); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 HighScoresManager::numVariations() const +uInt32 HighScoresManager::numVariations(const Properties& props) const { - string numVariations = getPropIdx(PropType::Cart_Variations); + string numVariations = getPropIdx(props, PropType::Cart_Variations); return numVariations == EmptyString ? 1 : std::min(stoi(numVariations), 256); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool HighScoresManager::getFormats(Formats& formats) const +bool HighScoresManager::get(const Properties& props, Formats& formats, Addresses& addresses) const { - formats.numDigits = numDigits(); - formats.trailingZeroes = trailingZeroes(); - formats.scoreBCD = scoreBCD(); - formats.varBCD = varBCD(); - formats.varZeroBased = varZeroBased(); + formats.numDigits = numDigits(props); + formats.trailingZeroes = trailingZeroes(props); + formats.scoreBCD = scoreBCD(props); + formats.varBCD = varBCD(props); + formats.varZeroBased = varZeroBased(props); - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 HighScoresManager::numDigits() const -{ - string digits = getPropIdx(PropType::Cart_Formats, 0); - - return digits == EmptyString ? 4 : stoi(digits); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 HighScoresManager::trailingZeroes() const -{ - string trailing = getPropIdx(PropType::Cart_Formats, 1); - - return trailing == EmptyString ? 0 : stoi(trailing);} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool HighScoresManager::scoreBCD() const -{ - string bcd = getPropIdx(PropType::Cart_Formats, 2); - - return bcd == EmptyString ? true : bcd == "B"; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool HighScoresManager::varBCD() const -{ - string bcd = getPropIdx(PropType::Cart_Formats, 3); - - return bcd == EmptyString ? true : bcd == "B"; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool HighScoresManager::varZeroBased() const -{ - string zeroBased = getPropIdx(PropType::Cart_Formats, 4); - - return zeroBased == EmptyString ? false : zeroBased != "0"; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool HighScoresManager::getAddresses(Addresses& addresses) const -{ - addresses.playerAddr = playerAddress(); - addresses.varAddr = varAddress(); + addresses.playerAddr = playerAddress(props); + addresses.varAddr = varAddress(props); for (uInt32 p = 0; p < MAX_PLAYERS; ++p) { - if (p < numPlayers()) + if (p < numPlayers(props)) { - for (uInt32 a = 0; a < numAddrBytes(); ++a) + for (uInt32 a = 0; a < numAddrBytes(props); ++a) { - uInt32 idx = p * numAddrBytes() + a; - string addr = getPropIdx(PropType::Cart_Addresses, idx); + 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)); } } else - for (uInt32 a = 0; a < numAddrBytes(); ++a) + for (uInt32 a = 0; a < numAddrBytes(props); ++a) addresses.scoreAddr[p][a] = -1; } - return (EmptyString != getPropIdx(PropType::Cart_Addresses, 0)); + return (EmptyString != getPropIdx(props, PropType::Cart_Addresses, 0)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 HighScoresManager::playerAddress() const +void HighScoresManager::set(Properties& props, uInt32 numPlayers, uInt32 numVariations, + const Formats& formats, const Addresses& addresses) const { - uInt32 idx = numAddrBytes() * numPlayers() + 1; - string addr = getPropIdx(PropType::Cart_Addresses, idx); + ostringstream buf; + + props.set(PropType::Cart_Players, std::to_string(numPlayers)); + props.set(PropType::Cart_Variations, std::to_string(numVariations)); + + buf << formats.numDigits << "," + << formats.trailingZeroes << "," + << (formats.scoreBCD ? "B" : "H") << "," + << (formats.varBCD ? "B" : "D") << "," + << formats.varZeroBased; + 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 << addresses.varAddr << ","; + buf << addresses.playerAddr; + props.set(PropType::Cart_Addresses, buf.str()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 HighScoresManager::numDigits(const Properties& props) const +{ + string digits = getPropIdx(props, PropType::Cart_Formats, 0); + + return digits == EmptyString ? 4 : stoi(digits); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 HighScoresManager::trailingZeroes(const Properties& props) const +{ + string trailing = getPropIdx(props, PropType::Cart_Formats, 1); + + return trailing == EmptyString ? 0 : stoi(trailing);} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool HighScoresManager::scoreBCD(const Properties& props) const +{ + string bcd = getPropIdx(props, PropType::Cart_Formats, 2); + + return bcd == EmptyString ? true : bcd == "B"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool HighScoresManager::varBCD(const Properties& props) const +{ + string bcd = getPropIdx(props, PropType::Cart_Formats, 3); + + return bcd == EmptyString ? true : bcd == "B"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool HighScoresManager::varZeroBased(const Properties& props) const +{ + string zeroBased = getPropIdx(props, PropType::Cart_Formats, 4); + + return zeroBased == EmptyString ? false : zeroBased != "0"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 HighScoresManager::varAddress() const +uInt16 HighScoresManager::varAddress(const Properties& props) const { - uInt32 idx = numAddrBytes() * numPlayers(); - string addr = getPropIdx(PropType::Cart_Addresses, idx); + uInt32 idx = numAddrBytes(props) * numPlayers(props); + string addr = getPropIdx(props, PropType::Cart_Addresses, idx); return addr == EmptyString ? 0 : stoi(addr, nullptr, 16); } @@ -207,22 +225,30 @@ uInt16 HighScoresManager::varAddress() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt32 HighScoresManager::numAddrBytes(Int32 digits, Int32 trailing) const { - return ((digits < 0 ? numDigits() : digits) - (trailing < 0 ? trailingZeroes() : trailing) + 1) / 2; + return (digits - trailing + 1) / 2; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Int32 HighScoresManager::score(uInt32 player, uInt32 numAddrBytes, bool isBCD) const +uInt32 HighScoresManager::numAddrBytes(const Properties& props) const +{ + return numAddrBytes(numDigits(props), trailingZeroes(props)); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Int32 HighScoresManager::score(uInt32 player, uInt32 numAddrBytes, uInt32 trailingZeroes, bool isBCD) 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(PropType::Cart_Addresses, idx); + string strAddr = getPropIdx(properties(props), PropType::Cart_Addresses, idx); uInt16 addr = (strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16)); uInt32 score; @@ -242,18 +268,19 @@ Int32 HighScoresManager::score(uInt32 player, uInt32 numAddrBytes, bool isBCD) c } if (totalScore != -1) - for (uInt32 i = 0; i < trailingZeroes(); ++i) + for (uInt32 i = 0; i < trailingZeroes; ++i) totalScore *= 10; return totalScore; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Int32 HighScoresManager::score(uInt32 player) const +Int32 HighScoresManager::score(const Properties& props, uInt32 player) const { - return score(player, numAddrBytes(), scoreBCD()); + return score(player, numAddrBytes(props), trailingZeroes(props), scoreBCD(props)); } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool HighScoresManager::parseAddresses(uInt32& variation, uInt32& player, uInt32 scores[]) { @@ -264,7 +291,6 @@ bool HighScoresManager::parseAddresses(uInt32& variation, uInt32& player, uInt32 System& system = myOSystem.console().system(); - Properties props; string formats = properties(props).get(PropType::Cart_Formats); string addresses = properties(props).get(PropType::Cart_Addresses); @@ -295,7 +321,7 @@ bool HighScoresManager::parseAddresses(uInt32& variation, uInt32& player, uInt32 varAdd = 0; // 2. retrieve current scores for all players - for (uInt32 i = 0; i < numPlayers(); ++i) + for (uInt32 i = 0; i < numPlayers(props); ++i) { Int32 totalScore = 0; @@ -317,7 +343,7 @@ bool HighScoresManager::parseAddresses(uInt32& variation, uInt32& player, uInt32 } // 3. retrieve current variation (0..255) - if (numVariations() == 1) + if (numVariations(props) == 1) return true; if (!(addrBuf >> std::hex >> addr)) @@ -326,17 +352,17 @@ bool HighScoresManager::parseAddresses(uInt32& variation, uInt32& player, uInt32 if (varFormat == 'B') variation = (variation >> 4) * 10 + variation % 16; variation += varAdd; - variation = std::min(variation, numVariations()); + variation = std::min(variation, numVariations(props)); // 4. retrieve current player (0..3) - if (numPlayers() == 1) + if (numPlayers(props) == 1) return true; if (!(addrBuf >> std::hex >> addr)) return false; player = system.peek(addr); - player = std::min(player, numPlayers() - 1); + player = std::min(player, numPlayers(props) - 1); return true; } diff --git a/src/common/HighScoresManager.hxx b/src/common/HighScoresManager.hxx index b98892642..def2733c3 100644 --- a/src/common/HighScoresManager.hxx +++ b/src/common/HighScoresManager.hxx @@ -26,10 +26,11 @@ class HighScoresManager { public: - static const uInt32 MAX_PLAYERS = 4; static const uInt32 MAX_SCORE_ADDR = 3; + using ScoreAddresses = BSPF::array2D; + struct Formats { uInt32 numDigits; uInt32 trailingZeroes; @@ -40,7 +41,7 @@ public: struct Addresses { - Int16 scoreAddr[HighScoresManager::MAX_PLAYERS][HighScoresManager::MAX_SCORE_ADDR]; + ScoreAddresses scoreAddr; uInt16 varAddr; uInt16 playerAddr; }; @@ -51,35 +52,37 @@ public: /* Methods for returning high scores related variables */ - uInt32 numVariations() const; - uInt32 numPlayers() const; + uInt32 numVariations(const Properties& props) const; + uInt32 numPlayers(const Properties& props) const; - bool getFormats(Formats& formats) const; - bool getAddresses(Addresses& addresses) const; + bool get(const Properties& props, Formats& formats, Addresses& addresses) const; + void set(Properties& props, uInt32 numPlayers, uInt32 numVariations, + const Formats& formats, const Addresses& addresses) const; - uInt32 numDigits() const; - uInt32 trailingZeroes() const; - bool scoreBCD() const; - bool varBCD() const; - bool varZeroBased() 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; - uInt16 varAddress() const; - uInt16 playerAddress() const; + uInt16 varAddress(const Properties& props) const; + uInt16 playerAddress(const Properties& props) const; - uInt32 numAddrBytes(Int32 digits = -1, Int32 trailing = -1) 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) const; - Int32 score(uInt32 player, uInt32 numAddrBytes, bool isBCD) const; + 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(PropType type, uInt32 idx = 0) const; - Int16 peek(uInt16 addr); + 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: diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 3229717bd..033d6c218 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -658,45 +658,44 @@ void GameInfoDialog::loadHighScoresProperties(const Properties& props) { HighScoresManager::Formats formats; HighScoresManager::Addresses addresses; - bool enable = instance().highScores().getAddresses(addresses); - - instance().highScores().getFormats(formats); + bool enable = instance().highScores().get(props, formats, addresses); myHighScores->setState(enable); - myPlayers->setSelected(instance().highScores().numPlayers()); - myVariations->setText(std::to_string(instance().highScores().numVariations())); + myPlayers->setSelected(instance().highScores().numPlayers(props)); + myVariations->setText(std::to_string(instance().highScores().numVariations(props))); - if (true) + ostringstream ss; + + myScoreDigits->setSelected(formats.numDigits); + myTrailingZeroes->setSelected(formats.trailingZeroes); + myScoreBCD->setState(formats.scoreBCD); + myVarBCD->setState(formats.varBCD); + myVarZeroBased->setState(formats.varZeroBased); + + ss.str(""); + ss << std::hex << std::right << std::setw(4) << std::setfill('0') + << std::uppercase << addresses.playerAddr; + myPlayersAddress->setText(ss.str()); + + ss.str(""); + ss << std::hex << std::right << std::setw(4) << std::setfill('0') + << std::uppercase << addresses.varAddr; + myVarAddress->setText(ss.str()); + + for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p) { - ostringstream ss; - - myScoreDigits->setSelected(formats.numDigits); - myTrailingZeroes->setSelected(formats.trailingZeroes); - myScoreBCD->setState(formats.scoreBCD); - myVarBCD->setState(formats.varBCD); - myVarZeroBased->setState(formats.varZeroBased); - - ss.str(""); - ss << std::hex << std::right << std::setw(4) << std::setfill('0') - << std::uppercase << addresses.playerAddr; - myPlayersAddress->setText(ss.str()); - - ss.str(""); - ss << std::hex << std::right << std::setw(4) << std::setfill('0') - << std::uppercase << addresses.varAddr; - myVarAddress->setText(ss.str()); - - - for (uInt32 p = 0; p < instance().highScores().numPlayers(); ++p) + for (uInt32 a = 0; a < instance().highScores().numAddrBytes(props); ++a) { - for (uInt32 a = 0; a < instance().highScores().numAddrBytes(); ++a) + if (p < instance().highScores().numPlayers(props)) { ss.str(""); ss << std::hex << std::right << std::setw(4) << std::setfill('0') << std::uppercase << addresses.scoreAddr[p][a]; myScoreAddress[p][a]->setText(ss.str()); } + else + myScoreAddress[p][a]->setText(""); } } handleHighScoresWidgets(); @@ -745,6 +744,8 @@ void GameInfoDialog::saveConfig() myGameProperties.set(PropType::Cart_Rarity, myRarity->getText()); myGameProperties.set(PropType::Cart_Note, myNote->getText()); + saveHighScoresProperties(); + // Always insert; if the properties are already present, nothing will happen instance().propSet().insert(myGameProperties); instance().saveConfig(); @@ -770,6 +771,45 @@ void GameInfoDialog::saveConfig() } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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) + { + 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); + } + } + + strAddr = myVariations->getText(); + instance().highScores().set(myGameProperties, myPlayers->getSelected() + 1, + strAddr == EmptyString ? 1 : stoi(strAddr), + formats, addresses); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::setDefaults() { @@ -969,7 +1009,8 @@ void GameInfoDialog::handleHighScoresWidgets() for (uInt32 a = 0; a < numAddr; ++a) setAddressVal(myScoreAddress[p][a], myScoreAddressVal[p][a]); - Int32 score = instance().highScores().score(p, numAddr, myScoreBCD->getState()); + Int32 score = instance().highScores().score(p, numAddr, myTrailingZeroes->getSelected(), + myScoreBCD->getState()); if (score >= 0) { ostringstream ss; diff --git a/src/gui/GameInfoDialog.hxx b/src/gui/GameInfoDialog.hxx index 25a25689e..b3cd81f27 100644 --- a/src/gui/GameInfoDialog.hxx +++ b/src/gui/GameInfoDialog.hxx @@ -56,6 +56,8 @@ class GameInfoDialog : public Dialog, public CommandSender void loadCartridgeProperties(const Properties& props); // load the properties for the 'High Scores' tab void loadHighScoresProperties(const Properties& props); + // load the properties of the 'High Scores' tab + void saveHighScoresProperties(); void updateControllerStates(); void eraseEEPROM();