diff --git a/src/common/HighScoresManager.cxx b/src/common/HighScoresManager.cxx index 2fd3e92de..a16fe75ec 100644 --- a/src/common/HighScoresManager.cxx +++ b/src/common/HighScoresManager.cxx @@ -22,16 +22,20 @@ B, ; score format (BCD, HEX) B, ; variation format (BCD, HEX) 0, ; zero-based variation + "", ; special label (5 chars) + B, ; special format (BCD, HEX) + 0, ; zero-based special Addresses (in hex): 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 ; special address (if defined) TODO: - variation bits (Centipede) - player bits (Asteroids, Space Invaders) - score swaps (Asteroids) - - one optional and named value extra per game (round, level...) + - special: one optional and named value extra per game (round, level...) */ #include @@ -126,9 +130,12 @@ bool HighScoresManager::get(const Properties& props, uInt32& numPlayersR, uInt32 info.scoreBCD = scoreBCD(props); info.varsBCD = varBCD(props); info.varsZeroBased = varZeroBased(props); + info.specialBCD = false; // TODO + info.specialZeroBased = true; // TODO info.playersAddr = playerAddress(props); info.varsAddr = varAddress(props); + info.specialAddr = 0; // TODO for (uInt32 p = 0; p < MAX_PLAYERS; ++p) { if (p < numPlayersR) @@ -146,7 +153,7 @@ bool HighScoresManager::get(const Properties& props, uInt32& numPlayersR, uInt32 info.scoresAddr[p][a] = -1; } - return (EmptyString != getPropIdx(props, PropType::Cart_Addresses, 0)); + return (!getPropIdx(props, PropType::Cart_Addresses, 0).empty()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/HighScoresManager.hxx b/src/common/HighScoresManager.hxx index e66a358d0..1a9e21e35 100644 --- a/src/common/HighScoresManager.hxx +++ b/src/common/HighScoresManager.hxx @@ -23,6 +23,7 @@ class OSystem; namespace HSM { static const uInt32 MAX_PLAYERS = 4; static const uInt32 MAX_SCORE_ADDR = 3; + static const uInt32 MAX_SPECIAL = 5; static const uInt32 DEFAULT_PLAYER = 1; static const uInt32 DEFAULT_VARIATION = 1; @@ -38,10 +39,14 @@ namespace HSM { bool scoreBCD; bool varsBCD; bool varsZeroBased; + string special; + bool specialBCD; + bool specialZeroBased; // Addresses ScoresAddresses scoresAddr; uInt16 varsAddr; uInt16 playersAddr; + uInt16 specialAddr; }; } // namespace HSM diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 6c75a1596..5e1061c72 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -360,6 +360,10 @@ GameInfoDialog::GameInfoDialog( EditableWidget::TextFilter fVars = [](char c) { return (c >= '0' && c <= '9'); }; + EditableWidget::TextFilter fSpecial = [](char c) { + return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.'|| c == '-,'; + }; + xpos = HBORDER; ypos = VBORDER; lwidth = font.getStringWidth("Variations "); @@ -415,7 +419,7 @@ GameInfoDialog::GameInfoDialog( mySpecialLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, "Special "); mySpecial = new EditTextWidget(myTab, font, mySpecialLabel->getRight(), ypos - 1, swidth, lineHeight); - //mySpecial->setTextFilter(...); + mySpecial->setTextFilter(fSpecial); wid.push_back(mySpecial); mySpecialAddressLabel = new StaticTextWidget(myTab, font, myPlayersAddressLabel->getLeft(), ypos + 1, "Address "); @@ -695,17 +699,26 @@ void GameInfoDialog::loadHighScoresProperties(const Properties& props) myScoreBCD->setState(info.scoreBCD); myVarsBCD->setState(info.varsBCD); myVarsZeroBased->setState(info.varsZeroBased); + mySpecial->setText(info.special); + mySpecialBCD->setState(info.specialBCD); + mySpecialZeroBased->setState(info.specialZeroBased); ss.str(""); - ss << hex << right << setw(4) << setfill('0') + ss << hex << right << setw(4) << setfill(' ') << uppercase << info.playersAddr; myPlayersAddress->setText(ss.str()); ss.str(""); - ss << hex << right << setw(4) << setfill('0') + ss << hex << right << setw(4) << setfill(' ') << uppercase << info.varsAddr; myVarAddress->setText(ss.str()); + ss.str(""); + ss << hex << right << setw(4) << setfill(' ') + << uppercase << info.specialAddr; + mySpecialAddress->setText(ss.str()); + + for (uInt32 p = 0; p < HSM::MAX_PLAYERS; ++p) { for (uInt32 a = 0; a < instance().highScores().numAddrBytes(info.numDigits, info.trailingZeroes); ++a) @@ -801,20 +814,27 @@ void GameInfoDialog::saveHighScoresProperties() if (myHighScores->getState()) { - // fill info + // fill format info.varsZeroBased = myVarsZeroBased->getState(); info.varsBCD = myVarsBCD->getState(); + + info.special = mySpecial->getText(); + info.specialZeroBased = mySpecialZeroBased->getState(); + info.specialBCD = mySpecialBCD->getState(); + info.numDigits = myScoreDigits->getSelected() + 1; info.trailingZeroes = myTrailingZeroes->getSelected(); info.scoreBCD = myScoreBCD->getState(); - // fill info + // fill addresses string strAddr; strAddr = myPlayersAddress->getText(); info.playersAddr = stringToIntBase16(strAddr, HSM::DEFAULT_ADDRESS); strAddr = myVarAddress->getText(); info.varsAddr = stringToIntBase16(strAddr, HSM::DEFAULT_ADDRESS); + strAddr = mySpecialAddress->getText(); + info.specialAddr = stringToIntBase16(strAddr, HSM::DEFAULT_ADDRESS); for (uInt32 p = 0; p < HSM::MAX_PLAYERS; ++p) { @@ -987,8 +1007,19 @@ void GameInfoDialog::updateHighScoresWidgets() uInt32 players = myPlayers->getSelected() + 1; bool enablePlayers = enable && players > 1; bool enableVars = enable && myVariations->getText() > "1"; + bool enableSpecial = enable && !mySpecial->getText().empty(); uInt32 numAddr = instance().highScores().numAddrBytes(myScoreDigits->getSelected() + 1, myTrailingZeroes->getSelected()); + string strText; + + // limit variants and special size + strText = myVariations->getText(); + strText = strText.substr(0, 3); + myVariations->setText(strText); + + strText = mySpecial->getText(); + strText = strText.substr(0, HSM::MAX_SPECIAL); + mySpecial->setText(strText); // enable widgets myPlayersLabel->setEnabled(enable); @@ -1008,6 +1039,16 @@ void GameInfoDialog::updateHighScoresWidgets() myVarsBCD->setEnabled(enableVars && stringToInt(myVariations->getText(), 1) >= 10); myVarsZeroBased->setEnabled(enableVars); + mySpecialLabel->setEnabled(enable); + mySpecial->setEnabled(enable); + mySpecial->setEditable(enable); + mySpecialAddressLabel->setEnabled(enableSpecial); + mySpecialAddress->setEnabled(enableSpecial); + mySpecialAddress->setEditable(enableSpecial); + mySpecialAddressVal->setEnabled(enableSpecial); + mySpecialBCD->setEnabled(enableSpecial); + mySpecialZeroBased->setEnabled(enableSpecial); + mySpecialLabel->setEnabled(enable); myScoreDigitsLabel->setEnabled(enable); myScoreDigits->setEnabled(enable); @@ -1030,16 +1071,13 @@ void GameInfoDialog::updateHighScoresWidgets() } // verify and update widget data - 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); + setAddressVal(myVarAddress, myVarAddressVal, myVarsBCD->getState(), + myVarsZeroBased->getState() ? 1 : 0); + setAddressVal(mySpecialAddress, mySpecialAddressVal, mySpecialBCD->getState(), + mySpecialZeroBased->getState() ? 1 : 0); // update score RAM values and resulting scores for (uInt32 p = 0; p < HSM::MAX_PLAYERS; ++p) @@ -1101,7 +1139,7 @@ void GameInfoDialog::setAddressVal(EditTextWidget* addressWidget, EditTextWidget // format output and display in value widget if (isBCD) ss << hex; - ss << right << setw(2) << setfill('0') + ss << right << setw(2) << setfill(' ') << uppercase << uInt16(val); valWidget->setText(ss.str()); } diff --git a/src/gui/HighScoresDialog.cxx b/src/gui/HighScoresDialog.cxx index 6ff2b4e20..0545988cc 100644 --- a/src/gui/HighScoresDialog.cxx +++ b/src/gui/HighScoresDialog.cxx @@ -33,8 +33,8 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, : Dialog(osystem, parent, font, "High Scores") { const GUI::Font& ifont = instance().frameBuffer().infoFont(); - const int lineHeight = font.getLineHeight(); - //fontWidth = font.getMaxCharWidth(), + const int lineHeight = font.getLineHeight(), + fontWidth = font.getMaxCharWidth(); //fontHeight = font.getFontHeight(), //buttonHeight = font.getLineHeight() + 4; //infoLineHeight = ifont.getLineHeight(); @@ -46,7 +46,7 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, WidgetArray wid; VariantList items; - _w = 400; // max_w - 20; + _w = 40 * fontWidth + HBORDER * 2; // max_w - 20; _h = 400; // max_h - 20; ypos = VBORDER + _th; xpos = HBORDER; @@ -58,19 +58,19 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, myVariation = new PopUpWidget(this, font, s->getRight(), ypos, font.getStringWidth("256") - 4, lineHeight, items, "", 0, 0); - ypos += lineHeight + VGAP * 2; + ypos += lineHeight + VGAP * 4; int xposRank = HBORDER; int xposScore = xposRank + font.getStringWidth("Rank") + 16; - int xposName = xposScore + font.getStringWidth("123456") + 24; - int xposExtra = xposName + font.getStringWidth("Date") + 16; - int xposDate = xposExtra + font.getStringWidth("Round") + 16; + int xposSpecial = xposScore + font.getStringWidth("Score") + 24; + int xposName = xposSpecial + font.getStringWidth("Round") + 16; + int xposDate = xposName + font.getStringWidth("Name") + 16; int nWidth = font.getStringWidth("ABC") + 4; new StaticTextWidget(this, font, xposRank, ypos + 1, "Rank"); new StaticTextWidget(this, font, xposScore, ypos + 1, "Score"); + new StaticTextWidget(this, font, xposSpecial, ypos + 1, "Round"); new StaticTextWidget(this, font, xposName - 2, ypos + 1, "Name"); - new StaticTextWidget(this, font, xposExtra, ypos + 1, "Round"); new StaticTextWidget(this, font, xposDate+16, ypos + 1, "Date Time"); ypos += lineHeight + VGAP; @@ -79,22 +79,27 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, { myPositions[p] = new StaticTextWidget(this, font, xposRank, ypos + 1, (p < 9 ? " " : "") + std::to_string(p + 1) + ". "); - myScores[p] = new StaticTextWidget(this, font, xposScore, ypos + 1, "123456"); - myNames[p] = new EditTextWidget(this, font, xposName, ypos + 1, nWidth, lineHeight, "JTZ"); - myNames[p]->setEditable(false); - wid.push_back(myNames[p]); - - new StaticTextWidget(this, font, xposExtra, ypos + 1, " 123"); + mySpecials[p] = new StaticTextWidget(this, font, xposSpecial + 8, ypos + 1, "123"); + myEditNames[p] = new EditTextWidget(this, font, xposName, ypos - 1, nWidth, lineHeight, "JTZ"); + //myEditNames[p]->setEditable(false); + myEditNames[p]->setFlags(EditTextWidget::FLAG_INVISIBLE); + wid.push_back(myEditNames[p]); + myNames[p] = new StaticTextWidget(this, font, xposName + 2, ypos + 1, "JTZ"); //new StaticTextWidget(this, font, xposDate, ypos + 1, "12.02.20 17:15"); //new StaticTextWidget(this, font, xposDate, ypos + 1, "02/12/20 12:30am"); - new StaticTextWidget(this, font, xposDate, ypos + 1, "12-02-20 17:15"); + myDates[p] = new StaticTextWidget(this, font, xposDate, ypos + 1, "12-02-20 17:15"); ypos += lineHeight + VGAP; } - ypos += VGAP; + ypos += VGAP * 2; + myMD5 = new StaticTextWidget(this, ifont, xpos, ypos + 1, "MD5: 9ad36e699ef6f45d9eb6c4cf90475c9f"); + + wid.clear(); + addOKCancelBGroup(wid, font); + addBGroupToFocusList(wid); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -125,6 +130,33 @@ void HighScoresDialog::loadConfig() } myVariation->addItems(items); myVariation->setSelected(instance().highScores().variation()); + + // mock data + const string SCORES[NUM_POSITIONS] = {"999999", "250000", "100000", " 50000", " 20000", + " 5000", " 2000", " 700", " 200", " -"}; + const string SPECIALS[NUM_POSITIONS] = {"200", "150", " 90", " 70", " 45", + " 30", " 25", " 10", " 7", " -"}; + const string NAMES[NUM_POSITIONS] = {"RAM", "CDW", "AD ", "JTZ", "DOA", + "ROM", "VCS", "N.S", "JWC", " -"}; + const string DATES[NUM_POSITIONS] = {"19-12-24 21:00", "19-07-18 00:00", "20-01-01 12:00", + "20-02-12 21:50", "20-02-11 14:16", "20-02-11 13:11", + "20-02-10 19:45", "10-02-10 20:04", "05-02-09 22:32", + " - -"}; + + for (Int32 p = 0; p < NUM_POSITIONS; ++p) + { + myScores[p]->setLabel(SCORES[p]); + mySpecials[p]->setLabel(SPECIALS[p]); + myNames[p]->setLabel(NAMES[p]); + myEditNames[p]->setText(NAMES[p]); + myDates[p]->setLabel(DATES[p]); + } + + //myEditNames[4]->setEditable(true); + + //myNames[3]->setHeight(1); + //myNames[3]->setWidth(0); + myEditNames[4]->clearFlags(EditTextWidget::FLAG_INVISIBLE); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -134,6 +166,7 @@ void HighScoresDialog::handleCommand(CommandSender* sender, int cmd, int data, i { case kOKCmd: case kCloseCmd: + instance().eventHandler().leaveMenuMode(); instance().eventHandler().handleEvent(Event::ExitMode); break; diff --git a/src/gui/HighScoresDialog.hxx b/src/gui/HighScoresDialog.hxx index 142f7c6ba..ef701c646 100644 --- a/src/gui/HighScoresDialog.hxx +++ b/src/gui/HighScoresDialog.hxx @@ -50,7 +50,10 @@ class HighScoresDialog : public Dialog PopUpWidget* myVariation; StaticTextWidget* myPositions[NUM_POSITIONS]; StaticTextWidget* myScores[NUM_POSITIONS]; - EditTextWidget* myNames[NUM_POSITIONS]; + StaticTextWidget* mySpecials[NUM_POSITIONS]; + StaticTextWidget* myNames[NUM_POSITIONS]; + EditTextWidget* myEditNames[NUM_POSITIONS]; + StaticTextWidget* myDates[NUM_POSITIONS]; StaticTextWidget* myMD5; private: