finalize High Scores tab in GameInfoDialog

This commit is contained in:
thrust26 2020-02-11 11:01:13 +01:00
parent a84630b14c
commit 08b04f4695
6 changed files with 222 additions and 232 deletions

View File

@ -96,7 +96,8 @@ uInt32 HighScoresManager::numPlayers(const Properties& props) const
{ {
string numPlayers = getPropIdx(props, PropType::Cart_Players); 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); 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.numDigits = numDigits(props);
formats.trailingZeroes = trailingZeroes(props); formats.trailingZeroes = trailingZeroes(props);
formats.scoreBCD = scoreBCD(props); formats.scoreBCD = scoreBCD(props);
formats.varBCD = varBCD(props); formats.varsBCD = varBCD(props);
formats.varZeroBased = varZeroBased(props); formats.varsZeroBased = varZeroBased(props);
addresses.playerAddr = playerAddress(props); addresses.playersAddr = playerAddress(props);
addresses.varAddr = varAddress(props); addresses.varsAddr = varAddress(props);
for (uInt32 p = 0; p < MAX_PLAYERS; ++p) for (uInt32 p = 0; p < MAX_PLAYERS; ++p)
{ {
if (p < numPlayers(props)) if (p < numPlayersR)
{ {
for (uInt32 a = 0; a < numAddrBytes(props); ++a) for (uInt32 a = 0; a < numAddrBytes(props); ++a)
{ {
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.scoreAddr[p][a] = (addr == EmptyString ? 0 : stoi(addr, nullptr, 16)); addresses.scoresAddr[p][a] = (addr == EmptyString ? 0 : stoi(addr, nullptr, 16));
} }
} }
else else
for (uInt32 a = 0; a < numAddrBytes(props); ++a) 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)); return (EmptyString != getPropIdx(props, PropType::Cart_Addresses, 0));
@ -145,23 +151,25 @@ void HighScoresManager::set(Properties& props, uInt32 numPlayers, uInt32 numVari
ostringstream buf; ostringstream buf;
props.set(PropType::Cart_Players, std::to_string(numPlayers)); 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 << "," buf << formats.numDigits << ","
<< formats.trailingZeroes << "," << formats.trailingZeroes << ","
<< (formats.scoreBCD ? "B" : "H") << "," << (formats.scoreBCD ? "B" : "H") << ","
<< (formats.varBCD ? "B" : "D") << "," << (formats.varsBCD ? "B" : "D") << ","
<< formats.varZeroBased; << formats.varsZeroBased;
props.set(PropType::Cart_Formats, buf.str()); props.set(PropType::Cart_Formats, buf.str());
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(formats.numDigits, formats.trailingZeroes); ++a)
buf << std::hex << addresses.scoreAddr[p][a] << ","; buf << std::hex << addresses.scoresAddr[p][a] << ",";
} }
buf << addresses.varAddr << ","; buf << addresses.varsAddr << ",";
buf << addresses.playerAddr; buf << addresses.playersAddr;
props.set(PropType::Cart_Addresses, buf.str()); 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); 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); 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 bool HighScoresManager::scoreBCD(const Properties& props) const
{ {
string bcd = getPropIdx(props, PropType::Cart_Formats, 2); 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); 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); 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 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 ? 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); 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 ? 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()) if (!myOSystem.hasConsole())
return -1; return -1;
Properties props; // TODO: remove and replace adddress with real data
System& system = myOSystem.console().system();
Int32 totalScore = 0; Int32 totalScore = 0;
for (uInt32 b = 0; b < numAddrBytes; ++b) for (uInt32 b = 0; b < numAddrBytes; ++b)
{ {
uInt32 idx = player * numAddrBytes + b; uInt16 addr = scoreAddr[b];
string strAddr = getPropIdx(properties(props), PropType::Cart_Addresses, idx);
uInt16 addr = (strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16));
uInt32 score; uInt32 score;
totalScore *= isBCD ? 100 : 256; totalScore *= isBCD ? 100 : 256;
score = system.peek(addr); score = peek(addr);
if (isBCD) if (isBCD)
{ {
// verify if score is legit // verify if score is legit
if (score >= 160) if (score >= 160)
{ return -1;
totalScore = -1;
break;
}
score = (score >> 4) * 10 + score % 16; score = (score >> 4) * 10 + score % 16;
} }
totalScore += score; 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; Properties props;
string formats = properties(props).get(PropType::Cart_Formats); uInt32 numBytes = numAddrBytes(properties(props));
string addresses = properties(props).get(PropType::Cart_Addresses); uInt32 currentPlayer = player() - playerZeroBased(props) ? 1 : 0;
char scoreFormat; uInt32 idx = numBytes * currentPlayer;
char varFormat; ScoreAddresses scoreAddr;
Int16 addr;
Int32 varAdd, numScoreAddr, scoreMult;
// Since istringstream swallows whitespace, we have to make the for (uInt32 b = 0; b < numBytes; ++b)
// 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)
{ {
Int32 totalScore = 0; string addr = getPropIdx(props, PropType::Cart_Addresses, idx + b);
for (int j = 0; j < numScoreAddr; ++j) if (addr == EmptyString)
{ return -1;
Int32 score; scoreAddr[b] = stoi(addr, nullptr, 16);
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;
} }
// 3. retrieve current variation (0..255) return score(currentPlayer, numBytes, trailingZeroes(props), scoreBCD(props), scoreAddr);
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;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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;
}

View File

@ -18,8 +18,6 @@
#ifndef HIGHSCORES_MANAGER_HXX #ifndef HIGHSCORES_MANAGER_HXX
#define HIGHSCORES_MANAGER_HXX #define HIGHSCORES_MANAGER_HXX
//#include "bspf.hxx"
class OSystem; class OSystem;
class HighScoresManager class HighScoresManager
@ -29,21 +27,21 @@ 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;
using ScoreAddresses = BSPF::array2D<Int16, MAX_PLAYERS, MAX_SCORE_ADDR>; using ScoreAddresses = array<Int16, MAX_SCORE_ADDR>;
using ScoresAddresses = array<ScoreAddresses, MAX_PLAYERS>;
struct Formats { struct Formats {
uInt32 numDigits; uInt32 numDigits;
uInt32 trailingZeroes; uInt32 trailingZeroes;
bool scoreBCD; bool scoreBCD;
bool varBCD; bool varsBCD;
bool varZeroBased; bool varsZeroBased;
}; };
struct Addresses { struct Addresses {
ScoreAddresses scoreAddr; ScoresAddresses scoresAddr;
uInt16 varAddr; uInt16 varsAddr;
uInt16 playerAddr; uInt16 playersAddr;
}; };
HighScoresManager(OSystem& osystem); HighScoresManager(OSystem& osystem);
@ -52,38 +50,50 @@ public:
/* /*
Methods for returning high scores related variables Methods for returning high scores related variables
*/ */
uInt32 numVariations(const Properties& props) const; bool get(const Properties& props, uInt32& numPlayers, uInt32& numVariations,
uInt32 numPlayers(const Properties& props) const; Formats& formats, Addresses& addresses) const;
bool get(const Properties& props, Formats& formats, Addresses& addresses) const;
void set(Properties& props, uInt32 numPlayers, uInt32 numVariations, void set(Properties& props, uInt32 numPlayers, uInt32 numVariations,
const Formats& formats, const Addresses& addresses) const; 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 numDigits(const Properties& props) const;
uInt32 trailingZeroes(const Properties& props) const; uInt32 trailingZeroes(const Properties& props) const;
bool scoreBCD(const Properties& props) const; bool scoreBCD(const Properties& props) const;
bool varBCD(const Properties& props) const; bool varBCD(const Properties& props) const;
bool varZeroBased(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; 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; Properties& properties(Properties& props) const;
string getPropIdx(const Properties& props, PropType type, uInt32 idx = 0) const; string getPropIdx(const Properties& props, PropType type, uInt32 idx = 0) const;
Int16 peek(uInt16 addr) const; Int16 peek(uInt16 addr) const;
bool parseAddresses(uInt32& variation, uInt32& player, uInt32 scores[]);
private: private:
// Reference to the osystem object // Reference to the osystem object

View File

@ -265,6 +265,14 @@ void Properties::print() const
<< endl; << endl;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Properties::reset(PropType key)
{
size_t pos = static_cast<size_t>(key);
myProperties[pos] = ourDefaultProperties[pos];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Properties::setDefaults() void Properties::setDefaults()
{ {

View File

@ -124,6 +124,13 @@ class Properties
*/ */
void setDefaults(); 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) Overloaded equality operator(s)

View File

@ -352,6 +352,12 @@ GameInfoDialog::GameInfoDialog(
wid.clear(); wid.clear();
tabID = myTab->addTab("High Scores", TabWidget::AUTO_WIDTH); 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; xpos = HBORDER; ypos = VBORDER;
lwidth = font.getStringWidth("Variations "); lwidth = font.getStringWidth("Variations ");
@ -371,9 +377,6 @@ GameInfoDialog::GameInfoDialog(
wid.push_back(myPlayers); wid.push_back(myPlayers);
int awidth = font.getStringWidth("FFFF") + 4; 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; int vwidth = font.getStringWidth("123") + 4;
myPlayersAddressLabel = new StaticTextWidget(myTab, font, myPlayers->getRight() + 16, ypos + 1, "Address "); myPlayersAddressLabel = new StaticTextWidget(myTab, font, myPlayers->getRight() + 16, ypos + 1, "Address ");
@ -389,6 +392,7 @@ GameInfoDialog::GameInfoDialog(
vwidth = font.getStringWidth("123") + 4; vwidth = font.getStringWidth("123") + 4;
myVariationsLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, lwidth, fontHeight, "Variations"); myVariationsLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, lwidth, fontHeight, "Variations");
myVariations = new EditTextWidget(myTab, font, xpos + lwidth, ypos - 1, fwidth, lineHeight); myVariations = new EditTextWidget(myTab, font, xpos + lwidth, ypos - 1, fwidth, lineHeight);
myVariations->setTextFilter(fVars);
wid.push_back(myVariations); wid.push_back(myVariations);
myVarAddressLabel = new StaticTextWidget(myTab, font, myPlayersAddressLabel->getLeft(), ypos + 1, "Address "); 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 = new EditTextWidget(myTab, font, myVarAddress->getRight() + 2, ypos - 1, vwidth, lineHeight);
myVarAddressVal->setEditable(false); myVarAddressVal->setEditable(false);
myVarBCD = new CheckboxWidget(myTab, font, myVarAddressVal->getRight() + 16, ypos + 1, "BCD", kVarBcdChanged); myVarsBCD = new CheckboxWidget(myTab, font, myVarAddressVal->getRight() + 16, ypos + 1, "BCD", kVarBcdChanged);
wid.push_back(myVarBCD); wid.push_back(myVarsBCD);
myVarZeroBased = new CheckboxWidget(myTab, font, myVarBCD->getRight() + 16, ypos + 1, "0-based", kVarZeroBasedChanged); myVarsZeroBased = new CheckboxWidget(myTab, font, myVarsBCD->getRight() + 16, ypos + 1, "0-based", kVarZeroBasedChanged);
wid.push_back(myVarZeroBased); wid.push_back(myVarsZeroBased);
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
@ -436,7 +440,7 @@ GameInfoDialog::GameInfoDialog(
items, "", 0, kScoreZeroesChanged); items, "", 0, kScoreZeroesChanged);
wid.push_back(myTrailingZeroes); 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); wid.push_back(myScoreBCD);
@ -658,40 +662,42 @@ void GameInfoDialog::loadHighScoresProperties(const Properties& props)
{ {
HighScoresManager::Formats formats; HighScoresManager::Formats formats;
HighScoresManager::Addresses addresses; 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); myHighScores->setState(enable);
myPlayers->setSelected(instance().highScores().numPlayers(props)); myPlayers->setSelected(numPlayers);
myVariations->setText(std::to_string(instance().highScores().numVariations(props))); myVariations->setText(std::to_string(numVariations));
ostringstream ss; ostringstream ss;
myScoreDigits->setSelected(formats.numDigits); myScoreDigits->setSelected(formats.numDigits);
myTrailingZeroes->setSelected(formats.trailingZeroes); myTrailingZeroes->setSelected(formats.trailingZeroes);
myScoreBCD->setState(formats.scoreBCD); myScoreBCD->setState(formats.scoreBCD);
myVarBCD->setState(formats.varBCD); myVarsBCD->setState(formats.varsBCD);
myVarZeroBased->setState(formats.varZeroBased); myVarsZeroBased->setState(formats.varsZeroBased);
ss.str(""); ss.str("");
ss << std::hex << std::right << std::setw(4) << std::setfill('0') ss << std::hex << std::right << std::setw(4) << std::setfill('0')
<< std::uppercase << addresses.playerAddr; << std::uppercase << addresses.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 << std::hex << std::right << std::setw(4) << std::setfill('0')
<< std::uppercase << addresses.varAddr; << std::uppercase << addresses.varsAddr;
myVarAddress->setText(ss.str()); myVarAddress->setText(ss.str());
for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p) 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.str("");
ss << std::hex << std::right << std::setw(4) << std::setfill('0') 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()); myScoreAddress[p][a]->setText(ss.str());
} }
else else
@ -777,37 +783,45 @@ void GameInfoDialog::saveHighScoresProperties()
HighScoresManager::Formats formats; HighScoresManager::Formats formats;
HighScoresManager::Addresses addresses; HighScoresManager::Addresses addresses;
//myGameProperties.set(PropType::Cart_Players, myPlayers->getSelectedTag().toString()); if (myHighScores->getState())
//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) // fill formats
{ formats.varsZeroBased = myVarsZeroBased->getState();
strAddr = myScoreAddress[p][a]->getText(); formats.varsBCD = myVarsBCD->getState();
addresses.scoreAddr[p][a] = strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16); formats.numDigits = myScoreDigits->getSelected() + 1;
} formats.trailingZeroes = myTrailingZeroes->getSelected();
} formats.scoreBCD = myScoreBCD->getState();
strAddr = myVariations->getText(); // fill addresses
instance().highScores().set(myGameProperties, myPlayers->getSelected() + 1, string strAddr;
strAddr == EmptyString ? 1 : stoi(strAddr),
formats, addresses); 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, uInt32 numAddr = instance().highScores().numAddrBytes(myScoreDigits->getSelected() + 1,
myTrailingZeroes->getSelected()); myTrailingZeroes->getSelected());
// enable widgets
myPlayersLabel->setEnabled(enable); myPlayersLabel->setEnabled(enable);
myPlayers->setEnabled(enable); myPlayers->setEnabled(enable);
myPlayersAddressLabel->setEnabled(enablePlayers); myPlayersAddressLabel->setEnabled(enablePlayers);
@ -975,8 +990,8 @@ void GameInfoDialog::handleHighScoresWidgets()
myVarAddress->setEnabled(enableVars); myVarAddress->setEnabled(enableVars);
myVarAddress->setEditable(enableVars); myVarAddress->setEditable(enableVars);
myVarAddressVal->setEnabled(enableVars); myVarAddressVal->setEnabled(enableVars);
myVarBCD->setEnabled(enableVars); myVarsBCD->setEnabled(enableVars);
myVarZeroBased->setEnabled(enableVars); myVarsZeroBased->setEnabled(enableVars);
myScoresLabel->setEnabled(enable); myScoresLabel->setEnabled(enable);
myScoreDigitsLabel->setEnabled(enable); myScoreDigitsLabel->setEnabled(enable);
@ -999,18 +1014,34 @@ void GameInfoDialog::handleHighScoresWidgets()
myCurrentScore[p]->setEnabled(enable); myCurrentScore[p]->setEnabled(enable);
} }
setAddressVal(myPlayersAddress, myPlayersAddressVal); // verify and update widget data
setAddressVal(myVarAddress, myVarAddressVal, myVarBCD->getState(), myVarZeroBased->getState() ? 1 : 0); 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) for (uInt32 p = 0; p < HighScoresManager::MAX_PLAYERS; ++p)
{ {
if (p < players) if (p < players)
{ {
HighScoresManager::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();
scoreAddr[a] = strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16);
}
Int32 score = instance().highScores().score(p, numAddr, myTrailingZeroes->getSelected(), Int32 score = instance().highScores().score(p, numAddr, myTrailingZeroes->getSelected(),
myScoreBCD->getState()); myScoreBCD->getState(), scoreAddr);
if (score >= 0) if (score >= 0)
{ {
ostringstream ss; 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) 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()) if (instance().hasConsole() && valWidget->isEnabled())
{ {
System& system = instance().console().system(); System& system = instance().console().system();
string strAddr;
uInt16 addr; uInt16 addr;
uInt8 val; uInt8 val;
ostringstream ss; ostringstream ss;
strAddr = addressWidget->getText(); // convert to number and read from memory
addr = strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16); addr = strAddr == EmptyString ? 0 : stoi(strAddr, nullptr, 16);
val = system.peek(addr) + incVal; val = system.peek(addr) + incVal;
// format output and display in value widget
if (isBCD) if (isBCD)
ss << std::hex; ss << std::hex;
ss << std::right << std::setw(2) << std::setfill('0') ss << std::right << std::setw(2) << std::setfill('0')

View File

@ -62,7 +62,7 @@ class GameInfoDialog : public Dialog, public CommandSender
void updateControllerStates(); void updateControllerStates();
void eraseEEPROM(); void eraseEEPROM();
void handleHighScoresWidgets(); 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: private:
TabWidget* myTab{nullptr}; TabWidget* myTab{nullptr};
@ -122,8 +122,8 @@ class GameInfoDialog : public Dialog, public CommandSender
StaticTextWidget* myVarAddressLabel{ nullptr }; StaticTextWidget* myVarAddressLabel{ nullptr };
EditTextWidget* myVarAddress{ nullptr }; EditTextWidget* myVarAddress{ nullptr };
EditTextWidget* myVarAddressVal{ nullptr }; EditTextWidget* myVarAddressVal{ nullptr };
CheckboxWidget* myVarBCD{ nullptr }; CheckboxWidget* myVarsBCD{ nullptr };
CheckboxWidget* myVarZeroBased{ nullptr }; CheckboxWidget* myVarsZeroBased{ nullptr };
StaticTextWidget* myScoresLabel{ nullptr }; StaticTextWidget* myScoresLabel{ nullptr };
StaticTextWidget* myScoreDigitsLabel{ nullptr }; StaticTextWidget* myScoreDigitsLabel{ nullptr };