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)
0, ; zero-based variation
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, ; player address (if more than 1 player)
xx ; player address (if more than 1 player)
TODO:
- variation bits (Centipede)
@ -41,6 +41,10 @@
#include "HighScoresManager.hxx"
using namespace BSPF;
using namespace std;
using namespace HSM;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HighScoresManager::HighScoresManager(OSystem& osystem)
: myOSystem(osystem)
@ -79,8 +83,8 @@ string HighScoresManager::getPropIdx(const Properties& props, PropType type, uIn
{
string property = props.get(type);
std::replace(property.begin(), property.end(), ',', ' ');
std::replace(property.begin(), property.end(), '|', ' ');
replace(property.begin(), property.end(), ',', ' ');
replace(property.begin(), property.end(), '|', ' ');
istringstream buf(property);
string result;
@ -96,8 +100,7 @@ uInt32 HighScoresManager::numPlayers(const Properties& props) const
{
string numPlayers = getPropIdx(props, PropType::Cart_Players);
return numPlayers == EmptyString ?
DEFAULT_PLAYER : std::min(uInt32(stoi(numPlayers)), MAX_PLAYERS);
return min(uInt32(stringToInt(numPlayers, DEFAULT_PLAYER)), MAX_PLAYERS);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -105,25 +108,24 @@ uInt32 HighScoresManager::numVariations(const Properties& props) const
{
string numVariations = getPropIdx(props, PropType::Cart_Variations);
return numVariations == EmptyString ?
DEFAULT_VARIATION : std::min(uInt32(stoi(numVariations)), MAX_VARIATIONS);
return min(uInt32(stringToInt(numVariations, DEFAULT_VARIATION)), MAX_VARIATIONS);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool HighScoresManager::get(const Properties& props, uInt32& numPlayersR, uInt32& numVariationsR,
Formats& formats, Addresses& addresses) const
ScoresInfo& info) const
{
numPlayersR = numPlayers(props);
numVariationsR = numVariations(props);
formats.numDigits = numDigits(props);
formats.trailingZeroes = trailingZeroes(props);
formats.scoreBCD = scoreBCD(props);
formats.varsBCD = varBCD(props);
formats.varsZeroBased = varZeroBased(props);
info.numDigits = numDigits(props);
info.trailingZeroes = trailingZeroes(props);
info.scoreBCD = scoreBCD(props);
info.varsBCD = varBCD(props);
info.varsZeroBased = varZeroBased(props);
addresses.playersAddr = playerAddress(props);
addresses.varsAddr = varAddress(props);
info.playersAddr = playerAddress(props);
info.varsAddr = varAddress(props);
for (uInt32 p = 0; p < MAX_PLAYERS; ++p)
{
if (p < numPlayersR)
@ -133,12 +135,12 @@ bool HighScoresManager::get(const Properties& props, uInt32& numPlayersR, uInt32
uInt32 idx = p * numAddrBytes(props) + a;
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
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));
@ -146,31 +148,43 @@ bool HighScoresManager::get(const Properties& props, uInt32& numPlayersR, uInt32
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void HighScoresManager::set(Properties& props, uInt32 numPlayers, uInt32 numVariations,
const Formats& formats, const Addresses& addresses) const
const ScoresInfo& info) const
{
ostringstream buf;
string output;
props.set(PropType::Cart_Players, std::to_string(numPlayers));
props.set(PropType::Cart_Variations, std::to_string(std::min(numVariations, MAX_VARIATIONS)));
props.set(PropType::Cart_Players, to_string(numPlayers));
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 a = 0; a < numAddrBytes(formats.numDigits, formats.trailingZeroes); ++a)
buf << std::hex << addresses.scoresAddr[p][a] << ",";
for (uInt32 a = 0; a < numAddrBytes(info.numDigits, info.trailingZeroes); ++a)
buf << hex << info.scoresAddr[p][a] << ",";
}
buf << addresses.varsAddr << ",";
buf << addresses.playersAddr;
props.set(PropType::Cart_Addresses, buf.str());
// add optional addresses
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);
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);
return trailing == EmptyString ? DEFAULT_TRAILING : stoi(trailing);}
return min(uInt32(stringToInt(trailing, DEFAULT_TRAILING)), MAX_TRAILING);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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;
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);
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,
const ScoreAddresses& scoreAddr) const
Int32 HighScoresManager::score(uInt32 player, uInt32 numAddrBytes, uInt32 trailingZeroes,
bool isBCD, const ScoreAddresses& scoreAddr) const
{
if (!myOSystem.hasConsole())
return -1;
@ -322,7 +337,7 @@ Int32 HighScoresManager::score() const
if (addr == EmptyString)
return -1;
scoreAddr[b] = stoi(addr, nullptr, 16);
scoreAddr[b] = stringToIntBase16(addr);
}
return score(currentPlayer, numBytes, trailingZeroes(props), scoreBCD(props), scoreAddr);

View File

@ -20,91 +20,128 @@
class OSystem;
class HighScoresManager
{
public:
namespace HSM {
static const uInt32 MAX_PLAYERS = 4;
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 ScoresAddresses = array<ScoreAddresses, MAX_PLAYERS>;
struct Formats {
struct ScoresInfo {
// Formats
uInt32 numDigits;
uInt32 trailingZeroes;
bool scoreBCD;
bool varsBCD;
bool varsZeroBased;
};
struct Addresses {
// Addresses
ScoresAddresses scoresAddr;
uInt16 varsAddr;
uInt16 playersAddr;
};
HighScoresManager(OSystem& osystem);
virtual ~HighScoresManager() = default;
} // 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;
using namespace HSM;
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
Int32 player() const;
Int32 variation() const;
Int32 score() const;
TODO: load and saves scores
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;
@author Thomas Jentzsch
*/
private:
uInt32 numVariations(const Properties& props) const;
uInt32 numPlayers(const Properties& props) const;
uInt16 varAddress(const Properties& props) const;
uInt16 playerAddress(const Properties& props) const;
uInt32 numDigits(const Properties& props) const;
uInt32 trailingZeroes(const Properties& props) const;
bool scoreBCD(const Properties& props) const;
bool varBCD(const Properties& props) const;
bool varZeroBased(const Properties& props) const;
bool playerZeroBased(const Properties& props) const;
class HighScoresManager
{
public:
HighScoresManager(OSystem& osystem);
virtual ~HighScoresManager() = default;
uInt32 numAddrBytes(const Properties& props) const;
/**
Get the highscore data of game's properties
Properties& properties(Properties& props) const;
string getPropIdx(const Properties& props, PropType type, uInt32 idx = 0) const;
Int16 peek(uInt16 addr) const;
@return True if highscore data exists, else false
*/
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
OSystem& myOSystem;
/**
Calculate the number of bytes for one player's score from given parameters
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;
@return The number of score address bytes
*/
uInt32 numAddrBytes(Int32 digits, Int32 trailing) const;
/**
Calculate the score from given parameters
@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

View File

@ -152,6 +152,13 @@ namespace BSPF
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
inline int compareIgnoreCase(const string& s1, const string& s2)
{

View File

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

View File

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