add "invert score order" format parameter

add "Save?" dialog
This commit is contained in:
thrust26 2020-02-16 12:07:41 +01:00
parent 2b86772d6c
commit ebf743b997
6 changed files with 140 additions and 45 deletions

View File

@ -25,6 +25,7 @@
"", ; special label (5 chars)
B, ; special format (BCD, HEX)
0, ; zero-based special
0, ; invert score order
Addresses (in hex):
n*p-times xx, ; score info for each player, high to low
xx, ; variation address (if more than 1 variation)
@ -141,6 +142,7 @@ bool HighScoresManager::get(const Properties& props, uInt32& numPlayersR, uInt32
info.special = specialLabel(props);
info.specialBCD = specialBCD(props);
info.specialZeroBased = specialZeroBased(props);
info.scoreInvert = scoreInvert(props);
info.playersAddr = playerAddress(props);
info.varsAddr = varAddress(props);
@ -177,12 +179,14 @@ void HighScoresManager::set(Properties& props, uInt32 numPlayers, uInt32 numVari
props.set(PropType::Cart_Variations, to_string(min(numVariations, MAX_VARIATIONS)));
// fill from the back to skip default values
if (output.length() || info.scoreInvert != DEFAULT_SCORE_REVERSED)
output.insert(0, info.scoreInvert ? ",1" : ",0");
if (output.length() || info.specialZeroBased != DEFAULT_SPECIAL_ZERO_BASED)
output = info.specialZeroBased ? ",1" : ",0";
output.insert(0, info.specialZeroBased ? ",1" : ",0");
if (output.length() || info.specialBCD != DEFAULT_SPECIAL_BCD)
output.insert(0, info.specialBCD ? ",B" : ",D");
if (output.length() || !info.special.empty())
output.insert(0, "," + info.special);
output.insert(0, "," + (info.special.empty() ? "-" : info.special));
if (output.length() || info.varsZeroBased != DEFAULT_VARS_ZERO_BASED)
output.insert(0, info.varsZeroBased ? ",1" : ",0");
@ -220,7 +224,7 @@ void HighScoresManager::set(Properties& props, uInt32 numPlayers, uInt32 numVari
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 HighScoresManager::numDigits(const Properties& props) const
{
string digits = getPropIdx(props, PropType::Cart_Formats, 0);
string digits = getPropIdx(props, PropType::Cart_Formats, IDX_SCORE_DIGITS);
return min(uInt32(stringToInt(digits, DEFAULT_DIGITS)), MAX_SCORE_DIGITS);
}
@ -228,7 +232,7 @@ uInt32 HighScoresManager::numDigits(const Properties& props) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 HighScoresManager::trailingZeroes(const Properties& props) const
{
string trailing = getPropIdx(props, PropType::Cart_Formats, 1);
string trailing = getPropIdx(props, PropType::Cart_Formats, IDX_TRAILING_ZEROES);
return min(uInt32(stringToInt(trailing, DEFAULT_TRAILING)), MAX_TRAILING);
}
@ -236,7 +240,7 @@ uInt32 HighScoresManager::trailingZeroes(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, IDX_SCORE_BCD);
return bcd == EmptyString ? DEFAULT_SCORE_BCD : bcd == "B";
}
@ -244,7 +248,7 @@ bool HighScoresManager::scoreBCD(const Properties& props) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool HighScoresManager::varBCD(const Properties& props) const
{
string bcd = getPropIdx(props, PropType::Cart_Formats, 3);
string bcd = getPropIdx(props, PropType::Cart_Formats, IDX_VAR_BCD);
return bcd == EmptyString ? DEFAULT_VARS_BCD : bcd == "B";
}
@ -252,7 +256,7 @@ bool HighScoresManager::varBCD(const Properties& props) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool HighScoresManager::varZeroBased(const Properties& props) const
{
string zeroBased = getPropIdx(props, PropType::Cart_Formats, 4);
string zeroBased = getPropIdx(props, PropType::Cart_Formats, IDX_VAR_ZERO_BASED);
return zeroBased == EmptyString ? DEFAULT_VARS_ZERO_BASED : zeroBased != "0";
}
@ -263,7 +267,7 @@ string HighScoresManager::specialLabel(const Properties& props) const
string orgLabel, label;
// some ugly formatting
orgLabel = label = getPropIdx(props, PropType::Cart_Formats, 5);
orgLabel = label = getPropIdx(props, PropType::Cart_Formats, IDX_SPECIAL_LABEL);
label = BSPF::toLowerCase(label);
label[0] = orgLabel[0];
@ -273,7 +277,7 @@ string HighScoresManager::specialLabel(const Properties& props) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool HighScoresManager::specialBCD(const Properties& props) const
{
string bcd = getPropIdx(props, PropType::Cart_Formats, 6);
string bcd = getPropIdx(props, PropType::Cart_Formats, IDX_SPECIAL_BCD);
return bcd == EmptyString ? DEFAULT_SPECIAL_BCD : bcd == "B";
}
@ -281,11 +285,17 @@ bool HighScoresManager::specialBCD(const Properties& props) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool HighScoresManager::specialZeroBased(const Properties& props) const
{
string zeroBased = getPropIdx(props, PropType::Cart_Formats, 7);
string zeroBased = getPropIdx(props, PropType::Cart_Formats, IDX_SPECIAL_ZERO_BASED);
return zeroBased == EmptyString ? DEFAULT_SPECIAL_ZERO_BASED : zeroBased != "0";
}
bool HighScoresManager::scoreInvert(const Properties& props) const
{
string reversed = getPropIdx(props, PropType::Cart_Formats, IDX_SCORE_INVERT);
return reversed == EmptyString ? DEFAULT_SCORE_REVERSED : reversed != "0";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool HighScoresManager::playerZeroBased(const Properties& props) const
@ -293,11 +303,10 @@ bool HighScoresManager::playerZeroBased(const Properties& props) const
return DEFAULT_PLAYERS_ZERO_BASED;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 HighScoresManager::playerAddress(const Properties& props) const
{
uInt32 idx = numAddrBytes(props) * numPlayers(props) + 1;
uInt32 idx = numAddrBytes(props) * numPlayers(props) + IDX_PLAYERS_ADDRESS;
string addr = getPropIdx(props, PropType::Cart_Addresses, idx);
return stringToIntBase16(addr, DEFAULT_ADDRESS);
@ -306,7 +315,7 @@ uInt16 HighScoresManager::playerAddress(const Properties& props) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 HighScoresManager::varAddress(const Properties& props) const
{
uInt32 idx = numAddrBytes(props) * numPlayers(props);
uInt32 idx = numAddrBytes(props) * numPlayers(props) + IDX_VARS_ADDRESS;
string addr = getPropIdx(props, PropType::Cart_Addresses, idx);
return stringToIntBase16(addr, DEFAULT_ADDRESS);
@ -315,7 +324,7 @@ uInt16 HighScoresManager::varAddress(const Properties& props) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 HighScoresManager::specialAddress(const Properties& props) const
{
uInt32 idx = numAddrBytes(props) * numPlayers(props) + 2;
uInt32 idx = numAddrBytes(props) * numPlayers(props) + IDX_SPECIAL_ADDRESS;
string addr = getPropIdx(props, PropType::Cart_Addresses, idx);
return stringToIntBase16(addr, DEFAULT_ADDRESS);
@ -466,6 +475,12 @@ Int32 HighScoresManager::score() const
return score(currentPlayer, numBytes, trailingZeroes(props), scoreBCD(props), scoreAddr);
}
bool HighScoresManager::scoreInvert() const
{
Properties props;
return scoreInvert(properties(props));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int32 HighScoresManager::special() const
{

View File

@ -45,6 +45,7 @@ namespace HSM {
string special;
bool specialBCD;
bool specialZeroBased;
bool scoreInvert;
// Addresses
ScoresAddresses scoresAddr;
uInt16 varsAddr;
@ -115,15 +116,34 @@ class HighScoresManager
string specialLabel() const;
Int32 variation() const;
Int32 score() const;
bool scoreInvert() const;
Int32 special() const;
private:
enum {
IDX_SCORE_DIGITS = 0,
IDX_TRAILING_ZEROES,
IDX_SCORE_BCD,
IDX_VAR_BCD,
IDX_VAR_ZERO_BASED,
IDX_SPECIAL_LABEL,
IDX_SPECIAL_BCD,
IDX_SPECIAL_ZERO_BASED,
IDX_SCORE_INVERT
};
enum {
IDX_VARS_ADDRESS = 0,
IDX_PLAYERS_ADDRESS,
IDX_SPECIAL_ADDRESS
};
static const uInt32 MAX_VARIATIONS = 256;
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_SCORE_REVERSED = false;
static const bool DEFAULT_VARS_BCD = true;
static const bool DEFAULT_VARS_ZERO_BASED = false;
static const bool DEFAULT_PLAYERS_ZERO_BASED = true;
@ -140,6 +160,7 @@ class HighScoresManager
uInt32 numDigits(const Properties& props) const;
uInt32 trailingZeroes(const Properties& props) const;
bool scoreBCD(const Properties& props) const;
bool scoreInvert(const Properties& props) const;
bool varBCD(const Properties& props) const;
bool varZeroBased(const Properties& props) const;
string specialLabel(const Properties& props) const;

View File

@ -361,7 +361,7 @@ GameInfoDialog::GameInfoDialog(
return (c >= '0' && c <= '9');
};
EditableWidget::TextFilter fSpecial = [](char c) {
return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.'|| c == '-,';
return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.'|| c == '-';
};
xpos = HBORDER; ypos = VBORDER;
@ -459,6 +459,9 @@ GameInfoDialog::GameInfoDialog(
myScoreBCD = new CheckboxWidget(myTab, font, myVarsBCD->getLeft(), ypos + 1, "BCD", kHiScoresChanged);
wid.push_back(myScoreBCD);
myScoreInvert = new CheckboxWidget(myTab, font, myScoreBCD->getRight() + 16, ypos + 1, "Invert");
wid.push_back(myScoreInvert);
for (uInt32 p = 0; p < HSM::MAX_PLAYERS; ++p)
{
uInt32 s_xpos = xpos;
@ -478,9 +481,9 @@ GameInfoDialog::GameInfoDialog(
myScoreAddressVal[p][a]->setEditable(false);
s_xpos += myScoreAddressVal[p][a]->getWidth() + 16;
}
myCurrentScore[p] = new StaticTextWidget(myTab, font, s_xpos + 8+6, ypos + 1, "123456");
myCurrentScore[p] = new StaticTextWidget(myTab, font, s_xpos, ypos + 1, "= 123456");
}
myCurrentScoreLabel = new StaticTextWidget(myTab, font, myCurrentScore[0]->getLeft(), myScoreBCD->getTop(), "Current");
//myCurrentScoreLabel = new StaticTextWidget(myTab, font, myCurrentScore[0]->getLeft(), myScoreBCD->getTop(), "Current");
// Add items for tab 4
addToFocusList(wid, myTab, tabID);
@ -689,6 +692,7 @@ void GameInfoDialog::loadHighScoresProperties(const Properties& props)
myScoreDigits->setSelected(info.numDigits);
myTrailingZeroes->setSelected(info.trailingZeroes);
myScoreBCD->setState(info.scoreBCD);
myScoreInvert->setState(info.scoreInvert);
myVarsBCD->setState(info.varsBCD);
myVarsZeroBased->setState(info.varsZeroBased);
mySpecialName->setText(info.special);
@ -828,6 +832,7 @@ void GameInfoDialog::saveHighScoresProperties()
info.numDigits = myScoreDigits->getSelected() + 1;
info.trailingZeroes = myTrailingZeroes->getSelected();
info.scoreBCD = myScoreBCD->getState();
info.scoreInvert = myScoreInvert->getState();
// fill addresses
string strAddr;
@ -1047,7 +1052,8 @@ void GameInfoDialog::updateHighScoresWidgets()
myScoreBCD->setEnabled(enable);
myTrailingZeroesLabel->setEnabled(enable);
myTrailingZeroes->setEnabled(enable);
myCurrentScoreLabel->setEnabled(enable);
myScoreInvert->setEnabled(enable);
//myCurrentScoreLabel->setEnabled(enable);
for (uInt32 p = 0; p < HSM::MAX_PLAYERS; ++p)
{
@ -1092,7 +1098,7 @@ void GameInfoDialog::updateHighScoresWidgets()
ostringstream ss;
ss.str("");
ss << right << setw(myScoreDigits->getSelected() + 1) << setfill(' ') << score;
ss << "= " << right << setw(myScoreDigits->getSelected() + 1) << setfill(' ') << score;
myCurrentScore[p]->setLabel(ss.str());
}
else

View File

@ -143,11 +143,12 @@ class GameInfoDialog : public Dialog, public CommandSender
StaticTextWidget* myTrailingZeroesLabel{nullptr};
PopUpWidget* myTrailingZeroes{nullptr};
CheckboxWidget* myScoreBCD{nullptr};
CheckboxWidget* myScoreInvert{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{nullptr};
//StaticTextWidget* myCurrentScoreLabel{nullptr};
StaticTextWidget* myCurrentScore[HSM::MAX_PLAYERS]{nullptr};
enum {

View File

@ -20,9 +20,9 @@
#include "EventHandler.hxx"
#include "Font.hxx"
#include "FBSurface.hxx"
//#include "StringParser.hxx"
#include "EditTextWidget.hxx"
#include "PopUpWidget.hxx"
#include "MessageBox.hxx"
#include "HighScoresManager.hxx"
@ -32,14 +32,14 @@
HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h)
: Dialog(osystem, parent, font, "High Scores"),
myInitials("")
_max_w(max_w),
_max_h(max_h),
myInitials(""),
myDirty(false)
{
const GUI::Font& ifont = instance().frameBuffer().infoFont();
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth();
//fontHeight = font.getFontHeight(),
//buttonHeight = font.getLineHeight() + 4;
//infoLineHeight = ifont.getLineHeight();
const int VBORDER = 8;
const int HBORDER = 10;
const int VGAP = 4;
@ -48,8 +48,8 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
WidgetArray wid;
VariantList items;
_w = 44 * fontWidth + HBORDER * 2; // max_w - 20;
_h = 400; // max_h - 20;
_w = std::min(max_w, 44 * fontWidth + HBORDER * 2);
_h = std::min(max_h, 400);
ypos = VBORDER + _th; xpos = HBORDER;
@ -135,14 +135,19 @@ void HighScoresDialog::loadConfig()
}
myVariationWidget->addItems(items);
myVariationWidget->setSelected(instance().highScores().variation());
myVariationWidget->setEnabled(instance().highScores().numVariations() > 1);
mySpecialLabelWidget->setLabel(instance().highScores().specialLabel());
string label = " " + instance().highScores().specialLabel();
if (label.length() > 5)
label = label.substr(label.length() - 5);
mySpecialLabelWidget->setLabel(label);
myMD5 = instance().console().properties().get(PropType::Cart_MD5);
myMD5Widget->setLabel("MD5: " + myMD5);
myEditPos = myHighScorePos = -1;
myNow = now();
myDirty = false;
handleVariation(true);
}
@ -156,10 +161,7 @@ void HighScoresDialog::saveConfig()
myNames[myHighScorePos] = myInitials;
}
// save selected variation
Int32 variation = myVariationWidget->getSelectedTag().toInt();
saveHighScores(variation);
saveHighScores(myVariation);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -169,7 +171,7 @@ void HighScoresDialog::handleCommand(CommandSender* sender, int cmd, int data, i
{
case kOKCmd:
saveConfig();
// falls through...
[[fallthrough]];
case kCloseCmd:
instance().eventHandler().leaveMenuMode();
break;
@ -189,6 +191,14 @@ void HighScoresDialog::handleCommand(CommandSender* sender, int cmd, int data, i
updateWidgets();
break;
case kConfirmSave:
saveConfig();
[[fallthrough]];
case kCancelSave:
myDirty = false;
handleVariation();
break;
default:
Dialog::handleCommand(sender, cmd, data, 0);
}
@ -197,17 +207,19 @@ void HighScoresDialog::handleCommand(CommandSender* sender, int cmd, int data, i
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void HighScoresDialog::handleVariation(bool init)
{
// TODO: if anything changed, asked for saving
Int32 variation = myVariationWidget->getSelectedTag().toInt();
if (handleDirty())
{
myVariation = myVariationWidget->getSelectedTag().toInt();
loadHighScores(variation);
loadHighScores(myVariation);
myEditPos = -1;
myEditPos = -1;
if (variation == instance().highScores().variation())
handlePlayedVariation();
if (myVariation == instance().highScores().variation())
handlePlayedVariation();
updateWidgets(init);
updateWidgets(init);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -268,10 +280,14 @@ void HighScoresDialog::handlePlayedVariation()
if (newScore > 0)
{
Int32 newSpecial = instance().highScores().special();
bool scoreInvert = instance().highScores().scoreInvert();
for (myHighScorePos = 0; myHighScorePos < NUM_POSITIONS; ++myHighScorePos)
{
if (newScore > myHighScores[myHighScorePos] ||
(newScore == myHighScores[myHighScorePos] && newSpecial > mySpecials[myHighScorePos]))
if ((!scoreInvert && newScore > myHighScores[myHighScorePos]) ||
((scoreInvert && newScore < myHighScores[myHighScorePos]) || myHighScores[myHighScorePos] == 0))
break;
if (newScore == myHighScores[myHighScorePos] && newSpecial > mySpecials[myHighScorePos])
break;
}
@ -289,6 +305,7 @@ void HighScoresDialog::handlePlayedVariation()
//myNames[myHighScorePos] = "";
mySpecials[myHighScorePos] = newSpecial;
myDates[myHighScorePos] = myNow;
myDirty = true;
}
else
myHighScorePos = -1;
@ -320,6 +337,29 @@ void HighScoresDialog::deletePos(int pos)
myEditPos--;
myEditNamesWidget[myEditPos]->setText(myEditNamesWidget[myEditPos + 1]->getText());
}
myDirty = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool HighScoresDialog::handleDirty()
{
if (myDirty)
{
if (!myConfirmMsg)
{
StringList msg;
msg.push_back("Do you want to save the changed");
msg.push_back("high scores for this variation?");
msg.push_back("");
myConfirmMsg = make_unique<GUI::MessageBox>
(this, _font, msg, _max_w, _max_h, kConfirmSave, kCancelSave,
"Yes", "No", "Save High Scores", false);
}
myConfirmMsg->show();
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -26,8 +26,10 @@ class DialogContainer;
class OSystem;
class EditTextWidget;
class PopUpWidget;
#include "Serializable.hxx"
namespace GUI {
class MessageBox;
}
class Serializer;
#include "Dialog.hxx"
@ -56,6 +58,7 @@ class HighScoresDialog : public Dialog
void handlePlayedVariation();
void deletePos(int pos);
bool handleDirty();
void saveHighScores(Int32 variation) const;
void loadHighScores(Int32 variation);
@ -80,10 +83,19 @@ class HighScoresDialog : public Dialog
enum {
kVariationChanged = 'Vach',
kDeleteSingle = 'DeSi'
kDeleteSingle = 'DeSi',
kConfirmSave = 'CfSv',
kCancelSave = 'CcSv'
};
private:
bool myDirty;
unique_ptr<GUI::MessageBox> myConfirmMsg;
int _max_w;
int _max_h;
Int32 myVariation;
string myInitials;
Int32 myEditPos;
Int32 myHighScorePos;