add namespace for HighScoresManager

omit default property parameters
This commit is contained in:
thrust26 2020-02-11 13:39:27 +01:00
parent 08b04f4695
commit e849da3be1
5 changed files with 257 additions and 206 deletions

View File

@ -23,9 +23,9 @@
B, ; variation format (BCD, HEX) B, ; variation format (BCD, HEX)
0, ; zero-based variation 0, ; zero-based variation
Addresses (in hex): Addresses (in hex):
n*p-times xx, ; score addresses for each player, high to low n*p-times xx, ; score info for each player, high to low
xx, ; variation address (if more than 1 variation) xx, ; variation address (if more than 1 variation)
xx, ; player address (if more than 1 player) xx ; player address (if more than 1 player)
TODO: TODO:
- variation bits (Centipede) - variation bits (Centipede)
@ -41,6 +41,10 @@
#include "HighScoresManager.hxx" #include "HighScoresManager.hxx"
using namespace BSPF;
using namespace std;
using namespace HSM;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HighScoresManager::HighScoresManager(OSystem& osystem) HighScoresManager::HighScoresManager(OSystem& osystem)
: myOSystem(osystem) : myOSystem(osystem)
@ -79,8 +83,8 @@ string HighScoresManager::getPropIdx(const Properties& props, PropType type, uIn
{ {
string property = props.get(type); string property = props.get(type);
std::replace(property.begin(), property.end(), ',', ' '); replace(property.begin(), property.end(), ',', ' ');
std::replace(property.begin(), property.end(), '|', ' '); replace(property.begin(), property.end(), '|', ' ');
istringstream buf(property); istringstream buf(property);
string result; string result;
@ -96,8 +100,7 @@ uInt32 HighScoresManager::numPlayers(const Properties& props) const
{ {
string numPlayers = getPropIdx(props, PropType::Cart_Players); string numPlayers = getPropIdx(props, PropType::Cart_Players);
return numPlayers == EmptyString ? return min(uInt32(stringToInt(numPlayers, DEFAULT_PLAYER)), MAX_PLAYERS);
DEFAULT_PLAYER : std::min(uInt32(stoi(numPlayers)), MAX_PLAYERS);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -105,25 +108,24 @@ uInt32 HighScoresManager::numVariations(const Properties& props) const
{ {
string numVariations = getPropIdx(props, PropType::Cart_Variations); string numVariations = getPropIdx(props, PropType::Cart_Variations);
return numVariations == EmptyString ? return min(uInt32(stringToInt(numVariations, DEFAULT_VARIATION)), MAX_VARIATIONS);
DEFAULT_VARIATION : std::min(uInt32(stoi(numVariations)), MAX_VARIATIONS);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool HighScoresManager::get(const Properties& props, uInt32& numPlayersR, uInt32& numVariationsR, bool HighScoresManager::get(const Properties& props, uInt32& numPlayersR, uInt32& numVariationsR,
Formats& formats, Addresses& addresses) const ScoresInfo& info) const
{ {
numPlayersR = numPlayers(props); numPlayersR = numPlayers(props);
numVariationsR = numVariations(props); numVariationsR = numVariations(props);
formats.numDigits = numDigits(props); info.numDigits = numDigits(props);
formats.trailingZeroes = trailingZeroes(props); info.trailingZeroes = trailingZeroes(props);
formats.scoreBCD = scoreBCD(props); info.scoreBCD = scoreBCD(props);
formats.varsBCD = varBCD(props); info.varsBCD = varBCD(props);
formats.varsZeroBased = varZeroBased(props); info.varsZeroBased = varZeroBased(props);
addresses.playersAddr = playerAddress(props); info.playersAddr = playerAddress(props);
addresses.varsAddr = varAddress(props); info.varsAddr = varAddress(props);
for (uInt32 p = 0; p < MAX_PLAYERS; ++p) for (uInt32 p = 0; p < MAX_PLAYERS; ++p)
{ {
if (p < numPlayersR) if (p < numPlayersR)
@ -133,12 +135,12 @@ bool HighScoresManager::get(const Properties& props, uInt32& numPlayersR, uInt32
uInt32 idx = p * numAddrBytes(props) + a; uInt32 idx = p * numAddrBytes(props) + a;
string addr = getPropIdx(props, PropType::Cart_Addresses, idx); string addr = getPropIdx(props, PropType::Cart_Addresses, idx);
addresses.scoresAddr[p][a] = (addr == EmptyString ? 0 : stoi(addr, nullptr, 16)); info.scoresAddr[p][a] = stringToIntBase16(addr);
} }
} }
else else
for (uInt32 a = 0; a < numAddrBytes(props); ++a) for (uInt32 a = 0; a < numAddrBytes(props); ++a)
addresses.scoresAddr[p][a] = -1; info.scoresAddr[p][a] = -1;
} }
return (EmptyString != getPropIdx(props, PropType::Cart_Addresses, 0)); return (EmptyString != getPropIdx(props, PropType::Cart_Addresses, 0));
@ -146,31 +148,43 @@ bool HighScoresManager::get(const Properties& props, uInt32& numPlayersR, uInt32
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void HighScoresManager::set(Properties& props, uInt32 numPlayers, uInt32 numVariations, void HighScoresManager::set(Properties& props, uInt32 numPlayers, uInt32 numVariations,
const Formats& formats, const Addresses& addresses) const const ScoresInfo& info) const
{ {
ostringstream buf; ostringstream buf;
string output;
props.set(PropType::Cart_Players, std::to_string(numPlayers)); props.set(PropType::Cart_Players, to_string(numPlayers));
props.set(PropType::Cart_Variations, std::to_string(std::min(numVariations, MAX_VARIATIONS))); props.set(PropType::Cart_Variations, to_string(min(numVariations, MAX_VARIATIONS)));
// fill from the back to skip default values
if (info.varsZeroBased != DEFAULT_VARS_ZERO_BASED)
output = info.varsZeroBased ? ",1" : ",0";
if (output.length() || info.varsBCD != DEFAULT_VARS_BCD)
output.insert(0, info.varsBCD ? ",B" : ",D");
if (output.length() || info.scoreBCD != DEFAULT_SCORE_BCD)
output.insert(0, info.scoreBCD ? ",B" : ",H");
if (output.length() || info.trailingZeroes != DEFAULT_TRAILING)
output.insert(0, "," + to_string(info.trailingZeroes));
if (output.length() || info.numDigits != DEFAULT_DIGITS)
output.insert(0, to_string(info.numDigits));
props.set(PropType::Cart_Formats, output);
buf << formats.numDigits << ","
<< formats.trailingZeroes << ","
<< (formats.scoreBCD ? "B" : "H") << ","
<< (formats.varsBCD ? "B" : "D") << ","
<< formats.varsZeroBased;
props.set(PropType::Cart_Formats, buf.str());
buf.str("");
for (uInt32 p = 0; p < numPlayers; ++p) for (uInt32 p = 0; p < numPlayers; ++p)
{ {
for (uInt32 a = 0; a < numAddrBytes(formats.numDigits, formats.trailingZeroes); ++a) for (uInt32 a = 0; a < numAddrBytes(info.numDigits, info.trailingZeroes); ++a)
buf << std::hex << addresses.scoresAddr[p][a] << ","; buf << hex << info.scoresAddr[p][a] << ",";
} }
buf << addresses.varsAddr << ",";
buf << addresses.playersAddr; // add optional addresses
props.set(PropType::Cart_Addresses, buf.str()); if (numVariations > 1 || numPlayers > 1)
buf << info.varsAddr << "," ;
if (numPlayers > 1)
buf << info.playersAddr << "," ;
output = buf.str();
output.pop_back();
props.set(PropType::Cart_Addresses, output);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -178,7 +192,7 @@ uInt32 HighScoresManager::numDigits(const Properties& props) const
{ {
string digits = getPropIdx(props, PropType::Cart_Formats, 0); string digits = getPropIdx(props, PropType::Cart_Formats, 0);
return digits == EmptyString ? DEFAULT_DIGITS : stoi(digits); return min(uInt32(stringToInt(digits, DEFAULT_DIGITS)), MAX_DIGITS);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -186,7 +200,8 @@ uInt32 HighScoresManager::trailingZeroes(const Properties& props) const
{ {
string trailing = getPropIdx(props, PropType::Cart_Formats, 1); string trailing = getPropIdx(props, PropType::Cart_Formats, 1);
return trailing == EmptyString ? DEFAULT_TRAILING : stoi(trailing);} return min(uInt32(stringToInt(trailing, DEFAULT_TRAILING)), MAX_TRAILING);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool HighScoresManager::scoreBCD(const Properties& props) const bool HighScoresManager::scoreBCD(const Properties& props) const
@ -225,7 +240,7 @@ uInt16 HighScoresManager::playerAddress(const Properties& props) const
uInt32 idx = numAddrBytes(props) * numPlayers(props) + 1; uInt32 idx = numAddrBytes(props) * numPlayers(props) + 1;
string addr = getPropIdx(props, PropType::Cart_Addresses, idx); string addr = getPropIdx(props, PropType::Cart_Addresses, idx);
return addr == EmptyString ? DEFAULT_ADDRESS : stoi(addr, nullptr, 16); return stringToIntBase16(addr, DEFAULT_ADDRESS);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -234,7 +249,7 @@ uInt16 HighScoresManager::varAddress(const Properties& props) const
uInt32 idx = numAddrBytes(props) * numPlayers(props); uInt32 idx = numAddrBytes(props) * numPlayers(props);
string addr = getPropIdx(props, PropType::Cart_Addresses, idx); string addr = getPropIdx(props, PropType::Cart_Addresses, idx);
return addr == EmptyString ? DEFAULT_ADDRESS : stoi(addr, nullptr, 16); return stringToIntBase16(addr, DEFAULT_ADDRESS);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -250,8 +265,8 @@ uInt32 HighScoresManager::numAddrBytes(const Properties& props) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int32 HighScoresManager::score(uInt32 player, uInt32 numAddrBytes, uInt32 trailingZeroes, bool isBCD, Int32 HighScoresManager::score(uInt32 player, uInt32 numAddrBytes, uInt32 trailingZeroes,
const ScoreAddresses& scoreAddr) const bool isBCD, const ScoreAddresses& scoreAddr) const
{ {
if (!myOSystem.hasConsole()) if (!myOSystem.hasConsole())
return -1; return -1;
@ -322,7 +337,7 @@ Int32 HighScoresManager::score() const
if (addr == EmptyString) if (addr == EmptyString)
return -1; return -1;
scoreAddr[b] = stoi(addr, nullptr, 16); scoreAddr[b] = stringToIntBase16(addr);
} }
return score(currentPlayer, numBytes, trailingZeroes(props), scoreBCD(props), scoreAddr); return score(currentPlayer, numBytes, trailingZeroes(props), scoreBCD(props), scoreAddr);

View File

@ -20,91 +20,128 @@
class OSystem; class OSystem;
class HighScoresManager namespace HSM {
{
public:
static const uInt32 MAX_PLAYERS = 4; static const uInt32 MAX_PLAYERS = 4;
static const uInt32 MAX_SCORE_ADDR = 3; static const uInt32 MAX_SCORE_ADDR = 3;
static const uInt32 DEFAULT_PLAYER = 1;
static const uInt32 DEFAULT_VARIATION = 1;
static const uInt32 DEFAULT_ADDRESS = 0;
using ScoreAddresses = array<Int16, MAX_SCORE_ADDR>; using ScoreAddresses = array<Int16, MAX_SCORE_ADDR>;
using ScoresAddresses = array<ScoreAddresses, MAX_PLAYERS>; using ScoresAddresses = array<ScoreAddresses, MAX_PLAYERS>;
struct Formats { struct ScoresInfo {
// Formats
uInt32 numDigits; uInt32 numDigits;
uInt32 trailingZeroes; uInt32 trailingZeroes;
bool scoreBCD; bool scoreBCD;
bool varsBCD; bool varsBCD;
bool varsZeroBased; bool varsZeroBased;
}; // Addresses
struct Addresses {
ScoresAddresses scoresAddr; ScoresAddresses scoresAddr;
uInt16 varsAddr; uInt16 varsAddr;
uInt16 playersAddr; uInt16 playersAddr;
}; };
HighScoresManager(OSystem& osystem); } // namespace HSM
virtual ~HighScoresManager() = default;
/* using namespace HSM;
Methods for returning high scores related variables
*/
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; This class provides an interface to define, load and save scores. It is meant
for games which do not support saving highscores.
// retrieve current values TODO: load and saves scores
Int32 player() const;
Int32 variation() const;
Int32 score() const;
private: @author Thomas Jentzsch
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: class HighScoresManager
uInt32 numVariations(const Properties& props) const; {
uInt32 numPlayers(const Properties& props) const; public:
uInt16 varAddress(const Properties& props) const; HighScoresManager(OSystem& osystem);
uInt16 playerAddress(const Properties& props) const; virtual ~HighScoresManager() = default;
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;
uInt32 numAddrBytes(const Properties& props) const; /**
Get the highscore data of game's properties
Properties& properties(Properties& props) const; @return True if highscore data exists, else false
string getPropIdx(const Properties& props, PropType type, uInt32 idx = 0) const; */
Int16 peek(uInt16 addr) const; bool get(const Properties& props, uInt32& numPlayers, uInt32& numVariations,
ScoresInfo& info) const;
/**
Set the highscore data of game's properties
*/
void set(Properties& props, uInt32 numPlayers, uInt32 numVariations,
const ScoresInfo& info) const;
private: /**
// Reference to the osystem object Calculate the number of bytes for one player's score from given parameters
OSystem& myOSystem;
private: @return The number of score address bytes
// Following constructors and assignment operators not supported */
HighScoresManager() = delete; uInt32 numAddrBytes(Int32 digits, Int32 trailing) const;
HighScoresManager(const HighScoresManager&) = delete;
HighScoresManager(HighScoresManager&&) = delete; /**
HighScoresManager& operator=(const HighScoresManager&) = delete; Calculate the score from given parameters
HighScoresManager& operator=(HighScoresManager&&) = delete;
@return The current score or -1 if no valid data exists
*/
Int32 score(uInt32 player, uInt32 numAddrBytes, uInt32 trailingZeroes, bool isBCD,
const ScoreAddresses& scoreAddr) const;
// Retrieve current values (using game's properties)
Int32 player() const;
Int32 variation() const;
Int32 score() const;
private:
static const uInt32 MAX_VARIATIONS = 256;
static const uInt32 MAX_DIGITS = 6;
static const uInt32 MAX_TRAILING = 3;
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;
private:
// Get individual highscore info from properties
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;
// Calculate the number of bytes for one player's score from property parameters
uInt32 numAddrBytes(const Properties& props) const;
// Get properties
Properties& properties(Properties& props) const;
// Get value from highscore propterties at given index
string getPropIdx(const Properties& props, PropType type, uInt32 idx = 0) const;
// Peek into memory
Int16 peek(uInt16 addr) const;
private:
// Reference to the osystem object
OSystem& myOSystem;
private:
// Following constructors and assignment operators not supported
HighScoresManager() = delete;
HighScoresManager(const HighScoresManager&) = delete;
HighScoresManager(HighScoresManager&&) = delete;
HighScoresManager& operator=(const HighScoresManager&) = delete;
HighScoresManager& operator=(HighScoresManager&&) = delete;
}; };
#endif #endif

View File

@ -152,6 +152,13 @@ namespace BSPF
catch(...) { return defaultValue; } catch(...) { return defaultValue; }
} }
// Convert string with base 16 to integer, using default value on any error
inline int stringToIntBase16(const string& s, const int defaultValue = 0)
{
try { return std::stoi(s, nullptr, 16); }
catch(...) { return defaultValue; }
}
// Compare two strings, ignoring case // Compare two strings, ignoring case
inline int compareIgnoreCase(const string& s1, const string& s2) inline int compareIgnoreCase(const string& s1, const string& s2)
{ {

View File

@ -42,6 +42,9 @@
#include "GameInfoDialog.hxx" #include "GameInfoDialog.hxx"
using namespace std;
using namespace BSPF;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GameInfoDialog::GameInfoDialog( GameInfoDialog::GameInfoDialog(
OSystem& osystem, DialogContainer& parent, const GUI::Font& font, OSystem& osystem, DialogContainer& parent, const GUI::Font& font,
@ -373,7 +376,7 @@ GameInfoDialog::GameInfoDialog(
pwidth = font.getStringWidth("4"); pwidth = font.getStringWidth("4");
myPlayersLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, lwidth, fontHeight, "Players"); myPlayersLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, lwidth, fontHeight, "Players");
myPlayers = new PopUpWidget(myTab, font, xpos + lwidth, ypos, pwidth, lineHeight, items, "", 0, kPlayersChanged); myPlayers = new PopUpWidget(myTab, font, xpos + lwidth, ypos, pwidth, lineHeight, items, "", 0, kHiScoresChanged);
wid.push_back(myPlayers); wid.push_back(myPlayers);
int awidth = font.getStringWidth("FFFF") + 4; int awidth = font.getStringWidth("FFFF") + 4;
@ -402,10 +405,10 @@ GameInfoDialog::GameInfoDialog(
myVarAddressVal = new EditTextWidget(myTab, font, myVarAddress->getRight() + 2, ypos - 1, vwidth, lineHeight); myVarAddressVal = new EditTextWidget(myTab, font, myVarAddress->getRight() + 2, ypos - 1, vwidth, lineHeight);
myVarAddressVal->setEditable(false); myVarAddressVal->setEditable(false);
myVarsBCD = new CheckboxWidget(myTab, font, myVarAddressVal->getRight() + 16, ypos + 1, "BCD", kVarBcdChanged); myVarsBCD = new CheckboxWidget(myTab, font, myVarAddressVal->getRight() + 16, ypos + 1, "BCD", kHiScoresChanged);
wid.push_back(myVarsBCD); wid.push_back(myVarsBCD);
myVarsZeroBased = new CheckboxWidget(myTab, font, myVarsBCD->getRight() + 16, ypos + 1, "0-based", kVarZeroBasedChanged); myVarsZeroBased = new CheckboxWidget(myTab, font, myVarsBCD->getRight() + 16, ypos + 1, "0-based", kHiScoresChanged);
wid.push_back(myVarsZeroBased); wid.push_back(myVarsZeroBased);
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
@ -425,7 +428,7 @@ GameInfoDialog::GameInfoDialog(
myScoreDigitsLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, "Digits "); myScoreDigitsLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, "Digits ");
myScoreDigits = new PopUpWidget(myTab, font, myScoreDigitsLabel->getRight(), ypos, pwidth, lineHeight, myScoreDigits = new PopUpWidget(myTab, font, myScoreDigitsLabel->getRight(), ypos, pwidth, lineHeight,
items, "", 0, kScoreDigitsChanged); items, "", 0, kHiScoresChanged);
wid.push_back(myScoreDigits); wid.push_back(myScoreDigits);
items.clear(); items.clear();
@ -437,22 +440,22 @@ GameInfoDialog::GameInfoDialog(
myTrailingZeroesLabel = new StaticTextWidget(myTab, font, myScoreDigits->getRight() + 20, ypos + 1, "0-Digits "); myTrailingZeroesLabel = new StaticTextWidget(myTab, font, myScoreDigits->getRight() + 20, ypos + 1, "0-Digits ");
myTrailingZeroes = new PopUpWidget(myTab, font, myTrailingZeroesLabel->getRight(), ypos, pwidth, lineHeight, myTrailingZeroes = new PopUpWidget(myTab, font, myTrailingZeroesLabel->getRight(), ypos, pwidth, lineHeight,
items, "", 0, kScoreZeroesChanged); items, "", 0, kHiScoresChanged);
wid.push_back(myTrailingZeroes); wid.push_back(myTrailingZeroes);
myScoreBCD = new CheckboxWidget(myTab, font, myVarsBCD->getLeft(), ypos + 1, "BCD", kScoreBcdChanged); myScoreBCD = new CheckboxWidget(myTab, font, myVarsBCD->getLeft(), ypos + 1, "BCD", kHiScoresChanged);
wid.push_back(myScoreBCD); wid.push_back(myScoreBCD);
for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p) for (uInt32 p = 0; p < HSM::MAX_PLAYERS; ++p)
{ {
uInt32 s_xpos = xpos; uInt32 s_xpos = xpos;
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
myScoreAddressesLabel[p] = new StaticTextWidget(myTab, font, s_xpos, ypos + 1, myScoreAddressesLabel[p] = new StaticTextWidget(myTab, font, s_xpos, ypos + 1,
"P" + std::to_string(p + 1) + " Addresses "); "P" + to_string(p + 1) + " Addresses ");
s_xpos += myScoreAddressesLabel[p]->getWidth(); s_xpos += myScoreAddressesLabel[p]->getWidth();
for (uInt32 a = 0; a < HighScoresManager::MAX_SCORE_ADDR; ++a) for (uInt32 a = 0; a < HSM::MAX_SCORE_ADDR; ++a)
{ {
myScoreAddress[p][a] = new EditTextWidget(myTab, font, s_xpos, ypos - 1, awidth, lineHeight); myScoreAddress[p][a] = new EditTextWidget(myTab, font, s_xpos, ypos - 1, awidth, lineHeight);
myScoreAddress[p][a]->setTextFilter(fAddr); myScoreAddress[p][a]->setTextFilter(fAddr);
@ -584,10 +587,10 @@ void GameInfoDialog::loadEmulationProperties(const Properties& props)
myPPBlend->setEnabled(!alwaysPhosphor && usePhosphor); myPPBlend->setEnabled(!alwaysPhosphor && usePhosphor);
const string& blend = props.get(PropType::Display_PPBlend); const string& blend = props.get(PropType::Display_PPBlend);
myPPBlend->setValue(BSPF::stringToInt(blend)); myPPBlend->setValue(stringToInt(blend));
// set vertical center // set vertical center
Int32 vcenter = BSPF::stringToInt(props.get(PropType::Display_VCenter)); Int32 vcenter = stringToInt(props.get(PropType::Display_VCenter));
myVCenter->setValueLabel(vcenter); myVCenter->setValueLabel(vcenter);
myVCenter->setValue(vcenter); myVCenter->setValue(vcenter);
myVCenter->setValueUnit(vcenter ? "px" : ""); myVCenter->setValueUnit(vcenter ? "px" : "");
@ -620,7 +623,7 @@ void GameInfoDialog::loadControllerProperties(const Properties& props)
istringstream m_axis(props.get(PropType::Controller_MouseAxis)); istringstream m_axis(props.get(PropType::Controller_MouseAxis));
string m_control, m_range; string m_control, m_range;
m_axis >> m_control; m_axis >> m_control;
bool autoAxis = BSPF::equalsIgnoreCase(m_control, "AUTO"); bool autoAxis = equalsIgnoreCase(m_control, "AUTO");
myMouseControl->setState(!autoAxis); myMouseControl->setState(!autoAxis);
if(autoAxis) if(autoAxis)
{ {
@ -636,7 +639,7 @@ void GameInfoDialog::loadControllerProperties(const Properties& props)
myMouseY->setEnabled(!autoAxis); myMouseY->setEnabled(!autoAxis);
if(m_axis >> m_range) if(m_axis >> m_range)
{ {
myMouseRange->setValue(BSPF::stringToInt(m_range)); myMouseRange->setValue(stringToInt(m_range));
} }
else else
{ {
@ -660,51 +663,49 @@ void GameInfoDialog::loadCartridgeProperties(const Properties& props)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameInfoDialog::loadHighScoresProperties(const Properties& props) void GameInfoDialog::loadHighScoresProperties(const Properties& props)
{ {
HighScoresManager::Formats formats; HSM::ScoresInfo info;
HighScoresManager::Addresses addresses;
uInt32 numPlayers, numVariations; uInt32 numPlayers, numVariations;
bool enable = instance().highScores().get(props, numPlayers, numVariations, bool enable = instance().highScores().get(props, numPlayers, numVariations, info);
formats, addresses);
myHighScores->setState(enable); myHighScores->setState(enable);
myPlayers->setSelected(numPlayers); myPlayers->setSelected(numPlayers);
myVariations->setText(std::to_string(numVariations)); myVariations->setText(to_string(numVariations));
ostringstream ss; ostringstream ss;
myScoreDigits->setSelected(formats.numDigits); myScoreDigits->setSelected(info.numDigits);
myTrailingZeroes->setSelected(formats.trailingZeroes); myTrailingZeroes->setSelected(info.trailingZeroes);
myScoreBCD->setState(formats.scoreBCD); myScoreBCD->setState(info.scoreBCD);
myVarsBCD->setState(formats.varsBCD); myVarsBCD->setState(info.varsBCD);
myVarsZeroBased->setState(formats.varsZeroBased); myVarsZeroBased->setState(info.varsZeroBased);
ss.str(""); ss.str("");
ss << std::hex << std::right << std::setw(4) << std::setfill('0') ss << hex << right << setw(4) << setfill('0')
<< std::uppercase << addresses.playersAddr; << uppercase << info.playersAddr;
myPlayersAddress->setText(ss.str()); myPlayersAddress->setText(ss.str());
ss.str(""); ss.str("");
ss << std::hex << std::right << std::setw(4) << std::setfill('0') ss << hex << right << setw(4) << setfill('0')
<< std::uppercase << addresses.varsAddr; << uppercase << info.varsAddr;
myVarAddress->setText(ss.str()); myVarAddress->setText(ss.str());
for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p) for (uInt32 p = 0; p < HSM::MAX_PLAYERS; ++p)
{ {
for (uInt32 a = 0; a < instance().highScores().numAddrBytes(formats.numDigits, formats.trailingZeroes); ++a) for (uInt32 a = 0; a < instance().highScores().numAddrBytes(info.numDigits, info.trailingZeroes); ++a)
{ {
if (p < numPlayers) if (p < numPlayers)
{ {
ss.str(""); ss.str("");
ss << std::hex << std::right << std::setw(4) << std::setfill('0') ss << hex << right << setw(4) << setfill('0')
<< std::uppercase << addresses.scoresAddr[p][a]; << uppercase << info.scoresAddr[p][a];
myScoreAddress[p][a]->setText(ss.str()); myScoreAddress[p][a]->setText(ss.str());
} }
else else
myScoreAddress[p][a]->setText(""); myScoreAddress[p][a]->setText("");
} }
} }
handleHighScoresWidgets(); updateHighScoresWidgets();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -719,7 +720,7 @@ void GameInfoDialog::saveConfig()
myPPBlend->getValueLabel()); myPPBlend->getValueLabel());
Int32 vcenter = myVCenter->getValue(); Int32 vcenter = myVCenter->getValue();
myGameProperties.set(PropType::Display_VCenter, std::to_string(vcenter)); myGameProperties.set(PropType::Display_VCenter, to_string(vcenter));
myGameProperties.set(PropType::Cart_Sound, mySound->getState() ? "STEREO" : "MONO"); myGameProperties.set(PropType::Cart_Sound, mySound->getState() ? "STEREO" : "MONO");
// Console properties // Console properties
@ -780,40 +781,38 @@ void GameInfoDialog::saveConfig()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameInfoDialog::saveHighScoresProperties() void GameInfoDialog::saveHighScoresProperties()
{ {
HighScoresManager::Formats formats; HSM::ScoresInfo info;
HighScoresManager::Addresses addresses;
if (myHighScores->getState()) if (myHighScores->getState())
{ {
// fill formats // fill info
formats.varsZeroBased = myVarsZeroBased->getState(); info.varsZeroBased = myVarsZeroBased->getState();
formats.varsBCD = myVarsBCD->getState(); info.varsBCD = myVarsBCD->getState();
formats.numDigits = myScoreDigits->getSelected() + 1; info.numDigits = myScoreDigits->getSelected() + 1;
formats.trailingZeroes = myTrailingZeroes->getSelected(); info.trailingZeroes = myTrailingZeroes->getSelected();
formats.scoreBCD = myScoreBCD->getState(); info.scoreBCD = myScoreBCD->getState();
// fill addresses // fill info
string strAddr; string strAddr;
strAddr = myPlayersAddress->getText(); strAddr = myPlayersAddress->getText();
addresses.playersAddr = strAddr == EmptyString ? 1 : stoi(strAddr, nullptr, 16); info.playersAddr = stringToIntBase16(strAddr, HSM::DEFAULT_ADDRESS);
strAddr = myVarAddress->getText(); strAddr = myVarAddress->getText();
addresses.varsAddr = strAddr == EmptyString ? 1 : stoi(strAddr, nullptr, 16); info.varsAddr = stringToIntBase16(strAddr, HSM::DEFAULT_ADDRESS);
for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p) for (uInt32 p = 0; p < HSM::MAX_PLAYERS; ++p)
{ {
for (uInt32 a = 0; a < HighScoresManager::MAX_SCORE_ADDR; ++a) for (uInt32 a = 0; a < HSM::MAX_SCORE_ADDR; ++a)
{ {
strAddr = myScoreAddress[p][a]->getText(); strAddr = myScoreAddress[p][a]->getText();
addresses.scoresAddr[p][a] = strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16); info.scoresAddr[p][a] = stringToIntBase16(strAddr, HSM::DEFAULT_ADDRESS);
} }
} }
string strVars = myVariations->getText(); string strVars = myVariations->getText();
instance().highScores().set(myGameProperties, myPlayers->getSelected() + 1, instance().highScores().set(myGameProperties, myPlayers->getSelected() + 1,
strVars == EmptyString ? 1 : stoi(strVars), stringToInt(strVars, HSM::DEFAULT_VARIATION), info);
formats, addresses);
} }
else else
{ {
@ -913,10 +912,10 @@ void GameInfoDialog::updateControllerStates()
// Compumate bankswitching scheme doesn't allow to select controllers // Compumate bankswitching scheme doesn't allow to select controllers
bool enableSelectControl = myBSType->getSelectedTag() != "CM"; bool enableSelectControl = myBSType->getSelectedTag() != "CM";
// Enable Swap Paddles checkbox only for paddle games // Enable Swap Paddles checkbox only for paddle games
bool enableSwapPaddles = BSPF::startsWithIgnoreCase(contrLeft, "PADDLES") || bool enableSwapPaddles = startsWithIgnoreCase(contrLeft, "PADDLES") ||
BSPF::startsWithIgnoreCase(contrRight, "PADDLES") || startsWithIgnoreCase(contrRight, "PADDLES") ||
BSPF::startsWithIgnoreCase(myLeftPortDetected->getLabel(), "Paddles") || startsWithIgnoreCase(myLeftPortDetected->getLabel(), "Paddles") ||
BSPF::startsWithIgnoreCase(myRightPortDetected->getLabel(), "Paddles"); startsWithIgnoreCase(myRightPortDetected->getLabel(), "Paddles");
if(instance().hasConsole()) if(instance().hasConsole())
{ {
@ -966,7 +965,7 @@ void GameInfoDialog::eraseEEPROM()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameInfoDialog::handleHighScoresWidgets() void GameInfoDialog::updateHighScoresWidgets()
{ {
bool enable = myHighScores->getState(); bool enable = myHighScores->getState();
uInt32 players = myPlayers->getSelected() + 1; uInt32 players = myPlayers->getSelected() + 1;
@ -990,7 +989,7 @@ void GameInfoDialog::handleHighScoresWidgets()
myVarAddress->setEnabled(enableVars); myVarAddress->setEnabled(enableVars);
myVarAddress->setEditable(enableVars); myVarAddress->setEditable(enableVars);
myVarAddressVal->setEnabled(enableVars); myVarAddressVal->setEnabled(enableVars);
myVarsBCD->setEnabled(enableVars); myVarsBCD->setEnabled(enableVars && stringToInt(myVariations->getText(), 1) >= 10);
myVarsZeroBased->setEnabled(enableVars); myVarsZeroBased->setEnabled(enableVars);
myScoresLabel->setEnabled(enable); myScoresLabel->setEnabled(enable);
@ -1001,12 +1000,12 @@ void GameInfoDialog::handleHighScoresWidgets()
myTrailingZeroes->setEnabled(enable); myTrailingZeroes->setEnabled(enable);
myCurrentScoreLabel->setEnabled(enable); myCurrentScoreLabel->setEnabled(enable);
for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p) for (uInt32 p = 0; p < HSM::MAX_PLAYERS; ++p)
{ {
enable &= players > p; enable &= players > p;
myScoreAddressesLabel[p]->setEnabled(enable); myScoreAddressesLabel[p]->setEnabled(enable);
for (uInt32 a = 0; a < HighScoresManager::MAX_SCORE_ADDR; ++a) for (uInt32 a = 0; a < HSM::MAX_SCORE_ADDR; ++a)
{ {
myScoreAddress[p][a]->setEnabled(enable && numAddr > a); myScoreAddress[p][a]->setEnabled(enable && numAddr > a);
myScoreAddressVal[p][a]->setEnabled(enable && numAddr > a); myScoreAddressVal[p][a]->setEnabled(enable && numAddr > a);
@ -1027,17 +1026,17 @@ void GameInfoDialog::handleHighScoresWidgets()
setAddressVal(myVarAddress, myVarAddressVal, myVarsBCD->getState(), myVarsZeroBased->getState() ? 1 : 0); setAddressVal(myVarAddress, myVarAddressVal, myVarsBCD->getState(), myVarsZeroBased->getState() ? 1 : 0);
// update score RAM values and resulting scores // update score RAM values and resulting scores
for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p) for (uInt32 p = 0; p < HSM::MAX_PLAYERS; ++p)
{ {
if (p < players) if (p < players)
{ {
HighScoresManager::ScoreAddresses scoreAddr; HSM::ScoreAddresses scoreAddr;
for (uInt32 a = 0; a < numAddr; ++a) for (uInt32 a = 0; a < numAddr; ++a)
{ {
setAddressVal(myScoreAddress[p][a], myScoreAddressVal[p][a]); setAddressVal(myScoreAddress[p][a], myScoreAddressVal[p][a]);
string strAddr = myScoreAddress[p][a]->getText(); string strAddr = myScoreAddress[p][a]->getText();
scoreAddr[a] = strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16); scoreAddr[a] = stringToIntBase16(strAddr, HSM::DEFAULT_ADDRESS);
} }
Int32 score = instance().highScores().score(p, numAddr, myTrailingZeroes->getSelected(), Int32 score = instance().highScores().score(p, numAddr, myTrailingZeroes->getSelected(),
@ -1047,7 +1046,7 @@ void GameInfoDialog::handleHighScoresWidgets()
ostringstream ss; ostringstream ss;
ss.str(""); ss.str("");
ss << std::right << std::setw(myScoreDigits->getSelected() + 1) << std::setfill(' ') << score; ss << right << setw(myScoreDigits->getSelected() + 1) << setfill(' ') << score;
myCurrentScore[p]->setLabel(ss.str()); myCurrentScore[p]->setLabel(ss.str());
} }
else else
@ -1081,13 +1080,13 @@ void GameInfoDialog::setAddressVal(EditTextWidget* addressWidget, EditTextWidget
ostringstream ss; ostringstream ss;
// convert to number and read from memory // convert to number and read from memory
addr = strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16); addr = stringToIntBase16(strAddr, HSM::DEFAULT_ADDRESS);
val = system.peek(addr) + incVal; val = system.peek(addr) + incVal;
// format output and display in value widget // format output and display in value widget
if (isBCD) if (isBCD)
ss << std::hex; ss << hex;
ss << std::right << std::setw(2) << std::setfill('0') ss << right << setw(2) << setfill('0')
<< std::uppercase << uInt16(val); << uppercase << uInt16(val);
valWidget->setText(ss.str()); valWidget->setText(ss.str());
} }
else else
@ -1163,13 +1162,7 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd,
case EditTextWidget::kChangedCmd: case EditTextWidget::kChangedCmd:
case kHiScoresChanged: case kHiScoresChanged:
case kPlayersChanged: updateHighScoresWidgets();
case kVarZeroBasedChanged:
case kVarBcdChanged:
case kScoreDigitsChanged:
case kScoreZeroesChanged:
case kScoreBcdChanged:
handleHighScoresWidgets();
break; break;
default: default:

View File

@ -59,10 +59,15 @@ class GameInfoDialog : public Dialog, public CommandSender
// load the properties of the 'High Scores' tab // load the properties of the 'High Scores' tab
void saveHighScoresProperties(); void saveHighScoresProperties();
// update 'Controller' tab widgets
void updateControllerStates(); void updateControllerStates();
// erase SaveKey/AtariVox pages for current game
void eraseEEPROM(); void eraseEEPROM();
void handleHighScoresWidgets(); // update 'High Scores' tab widgets
void setAddressVal(EditTextWidget* address, EditTextWidget* val, bool isBCD = true, uInt8 incVal = 0); void updateHighScoresWidgets();
// set formatted memory value for given address field
void setAddressVal(EditTextWidget* address, EditTextWidget* val,
bool isBCD = true, uInt8 incVal = 0);
private: private:
TabWidget* myTab{nullptr}; TabWidget* myTab{nullptr};
@ -111,48 +116,42 @@ class GameInfoDialog : public Dialog, public CommandSender
// High Scores properties // High Scores properties
CheckboxWidget* myHighScores{nullptr}; CheckboxWidget* myHighScores{nullptr};
StaticTextWidget* myPlayersLabel{ nullptr }; StaticTextWidget* myPlayersLabel{nullptr};
PopUpWidget* myPlayers{nullptr}; PopUpWidget* myPlayers{nullptr};
StaticTextWidget* myPlayersAddressLabel{ nullptr }; StaticTextWidget* myPlayersAddressLabel{nullptr};
EditTextWidget* myPlayersAddress{ nullptr }; EditTextWidget* myPlayersAddress{nullptr};
EditTextWidget* myPlayersAddressVal{ nullptr }; EditTextWidget* myPlayersAddressVal{nullptr};
StaticTextWidget* myVariationsLabel{ nullptr }; StaticTextWidget* myVariationsLabel{nullptr};
EditTextWidget* myVariations{nullptr}; EditTextWidget* myVariations{nullptr};
StaticTextWidget* myVarAddressLabel{ nullptr }; StaticTextWidget* myVarAddressLabel{nullptr};
EditTextWidget* myVarAddress{ nullptr }; EditTextWidget* myVarAddress{nullptr};
EditTextWidget* myVarAddressVal{ nullptr }; EditTextWidget* myVarAddressVal{nullptr};
CheckboxWidget* myVarsBCD{ nullptr }; CheckboxWidget* myVarsBCD{nullptr};
CheckboxWidget* myVarsZeroBased{ nullptr }; CheckboxWidget* myVarsZeroBased{nullptr};
StaticTextWidget* myScoresLabel{ nullptr }; StaticTextWidget* myScoresLabel{nullptr};
StaticTextWidget* myScoreDigitsLabel{ nullptr }; StaticTextWidget* myScoreDigitsLabel{nullptr};
PopUpWidget* myScoreDigits{nullptr}; PopUpWidget* myScoreDigits{nullptr};
StaticTextWidget* myTrailingZeroesLabel{ nullptr }; StaticTextWidget* myTrailingZeroesLabel{nullptr};
PopUpWidget* myTrailingZeroes{nullptr}; PopUpWidget* myTrailingZeroes{nullptr};
CheckboxWidget* myScoreBCD{nullptr}; CheckboxWidget* myScoreBCD{nullptr};
StaticTextWidget* myScoreAddressesLabel[HighScoresManager::MAX_PLAYERS]{ nullptr }; StaticTextWidget* myScoreAddressesLabel[HSM::MAX_PLAYERS]{nullptr};
EditTextWidget* myScoreAddress[HighScoresManager::MAX_PLAYERS][HighScoresManager::MAX_SCORE_ADDR]{nullptr}; EditTextWidget* myScoreAddress[HSM::MAX_PLAYERS][HSM::MAX_SCORE_ADDR]{nullptr};
EditTextWidget* myScoreAddressVal[HighScoresManager::MAX_PLAYERS][HighScoresManager::MAX_SCORE_ADDR]{nullptr}; EditTextWidget* myScoreAddressVal[HSM::MAX_PLAYERS][HSM::MAX_SCORE_ADDR]{nullptr};
StaticTextWidget* myCurrentScoreLabel; StaticTextWidget* myCurrentScoreLabel;
StaticTextWidget* myCurrentScore[HighScoresManager::MAX_PLAYERS]; StaticTextWidget* myCurrentScore[HSM::MAX_PLAYERS];
enum { enum {
kVCenterChanged = 'Vcch', kVCenterChanged = 'Vcch',
kPhosphorChanged = 'PPch', kPhosphorChanged = 'PPch',
kPPBlendChanged = 'PBch', kPPBlendChanged = 'PBch',
kLeftCChanged = 'LCch', kLeftCChanged = 'LCch',
kRightCChanged = 'RCch', kRightCChanged = 'RCch',
kMCtrlChanged = 'MCch', kMCtrlChanged = 'MCch',
kEEButtonPressed = 'EEgb', kEEButtonPressed = 'EEgb',
kHiScoresChanged = 'HSch', kHiScoresChanged = 'HSch',
kPlayersChanged = 'Plch',
kVarZeroBasedChanged = 'VZch',
kVarBcdChanged = 'VBch',
kScoreDigitsChanged = 'SDch',
kScoreZeroesChanged = 'SZch',
kScoreBcdChanged = 'SBch',
}; };
// Game properties for currently loaded ROM // Game properties for currently loaded ROM