mirror of https://github.com/stella-emu/stella.git
add load/save for high scores (via Serializer)
change high scores hotkey to INSERT block high score dialog when no data is defined
This commit is contained in:
parent
aa0dc0b9ff
commit
ec2fe206c0
|
@ -102,6 +102,14 @@ string HighScoresManager::getPropIdx(const Properties& props, PropType type, uIn
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool HighScoresManager::enabled() const
|
||||||
|
{
|
||||||
|
Properties props;
|
||||||
|
|
||||||
|
return (!getPropIdx(properties(props), PropType::Cart_Addresses, 0).empty());
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 HighScoresManager::numPlayers(const Properties& props) const
|
uInt32 HighScoresManager::numPlayers(const Properties& props) const
|
||||||
{
|
{
|
||||||
|
@ -490,7 +498,7 @@ Int32 HighScoresManager::special(uInt16 addr, bool varBCD, bool zeroBased) const
|
||||||
Int32 HighScoresManager::fromBCD(uInt8 bcd) const
|
Int32 HighScoresManager::fromBCD(uInt8 bcd) const
|
||||||
{
|
{
|
||||||
// verify if score is legit
|
// verify if score is legit
|
||||||
if (bcd >= 160)
|
if ((bcd & 0xF0) >= 0xA0 || (bcd & 0xF) >= 0xA)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return (bcd >> 4) * 10 + bcd % 16;
|
return (bcd >> 4) * 10 + bcd % 16;
|
||||||
|
|
|
@ -72,6 +72,10 @@ class HighScoresManager
|
||||||
HighScoresManager(OSystem& osystem);
|
HighScoresManager(OSystem& osystem);
|
||||||
virtual ~HighScoresManager() = default;
|
virtual ~HighScoresManager() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// check if high score data has been defined
|
||||||
|
bool enabled() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the highscore data of game's properties
|
Get the highscore data of game's properties
|
||||||
|
|
||||||
|
|
|
@ -507,7 +507,7 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
|
||||||
{Event::UnwindAllMenu, KBDK_UP, MOD3},
|
{Event::UnwindAllMenu, KBDK_UP, MOD3},
|
||||||
{Event::ShowScore, KBDK_S, KBDM_SHIFT | KBDM_CTRL},
|
{Event::ShowScore, KBDK_S, KBDM_SHIFT | KBDM_CTRL},
|
||||||
{Event::ShowVariation, KBDK_V, KBDM_SHIFT | KBDM_CTRL},
|
{Event::ShowVariation, KBDK_V, KBDM_SHIFT | KBDM_CTRL},
|
||||||
{Event::HighScoresMenuMode, KBDK_HOME},
|
{Event::HighScoresMenuMode, KBDK_INSERT},
|
||||||
|
|
||||||
#if defined(RETRON77)
|
#if defined(RETRON77)
|
||||||
{Event::ConsoleColorToggle, KBDK_F4}, // back ("COLOR","B/W")
|
{Event::ConsoleColorToggle, KBDK_F4}, // back ("COLOR","B/W")
|
||||||
|
|
|
@ -1041,14 +1041,16 @@ bool EventHandler::changeStateByEvent(Event::Type type)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::OptionsMenuMode:
|
case Event::OptionsMenuMode:
|
||||||
if (myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE)
|
if (myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE
|
||||||
|
|| myState == EventHandlerState::TIMEMACHINE)
|
||||||
enterMenuMode(EventHandlerState::OPTIONSMENU);
|
enterMenuMode(EventHandlerState::OPTIONSMENU);
|
||||||
else
|
else
|
||||||
handled = false;
|
handled = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::CmdMenuMode:
|
case Event::CmdMenuMode:
|
||||||
if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE)
|
if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE
|
||||||
|
|| myState == EventHandlerState::TIMEMACHINE)
|
||||||
enterMenuMode(EventHandlerState::CMDMENU);
|
enterMenuMode(EventHandlerState::CMDMENU);
|
||||||
else if(myState == EventHandlerState::CMDMENU && !myOSystem.settings().getBool("minimal_ui"))
|
else if(myState == EventHandlerState::CMDMENU && !myOSystem.settings().getBool("minimal_ui"))
|
||||||
// The extra check for "minimal_ui" allows mapping e.g. right joystick fire
|
// The extra check for "minimal_ui" allows mapping e.g. right joystick fire
|
||||||
|
@ -1059,8 +1061,14 @@ bool EventHandler::changeStateByEvent(Event::Type type)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::HighScoresMenuMode:
|
case Event::HighScoresMenuMode:
|
||||||
if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE)
|
if (myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE
|
||||||
enterMenuMode(EventHandlerState::HIGHSCORESMENU);
|
|| myState == EventHandlerState::TIMEMACHINE)
|
||||||
|
{
|
||||||
|
if (myOSystem.highScores().enabled())
|
||||||
|
enterMenuMode(EventHandlerState::HIGHSCORESMENU);
|
||||||
|
else
|
||||||
|
myOSystem.frameBuffer().showMessage("No high scores data defined");
|
||||||
|
}
|
||||||
else if(myState == EventHandlerState::HIGHSCORESMENU)
|
else if(myState == EventHandlerState::HIGHSCORESMENU)
|
||||||
leaveMenuMode();
|
leaveMenuMode();
|
||||||
else
|
else
|
||||||
|
@ -2029,6 +2037,7 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { {
|
||||||
{ Event::Combo16, "Combo 16", "" },
|
{ Event::Combo16, "Combo 16", "" },
|
||||||
{ Event::ShowScore, "Display current score", "" },
|
{ Event::ShowScore, "Display current score", "" },
|
||||||
{ Event::ShowVariation, "Display current variation", "" },
|
{ Event::ShowVariation, "Display current variation", "" },
|
||||||
|
{ Event::HighScoresMenuMode, "Toggle High Scores UI", "" },
|
||||||
} };
|
} };
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -468,7 +468,7 @@ class EventHandler
|
||||||
#else
|
#else
|
||||||
PNG_SIZE = 0,
|
PNG_SIZE = 0,
|
||||||
#endif
|
#endif
|
||||||
EMUL_ACTIONLIST_SIZE = 144 + 2 + PNG_SIZE + COMBO_SIZE,
|
EMUL_ACTIONLIST_SIZE = 144 + 3 + PNG_SIZE + COMBO_SIZE,
|
||||||
MENU_ACTIONLIST_SIZE = 18
|
MENU_ACTIONLIST_SIZE = 18
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
#include "OSystem.hxx"
|
||||||
#include "Console.hxx"
|
#include "Console.hxx"
|
||||||
#include "EventHandler.hxx"
|
#include "EventHandler.hxx"
|
||||||
#include "Font.hxx"
|
#include "Font.hxx"
|
||||||
|
@ -29,8 +30,9 @@
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
|
HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
const GUI::Font& font, int max_w, int max_h)
|
const GUI::Font& font, int max_w, int max_h)
|
||||||
: Dialog(osystem, parent, font, "High Scores")
|
: Dialog(osystem, parent, font, "High Scores"),
|
||||||
|
myInitials("")
|
||||||
{
|
{
|
||||||
const GUI::Font& ifont = instance().frameBuffer().infoFont();
|
const GUI::Font& ifont = instance().frameBuffer().infoFont();
|
||||||
const int lineHeight = font.getLineHeight(),
|
const int lineHeight = font.getLineHeight(),
|
||||||
|
@ -56,7 +58,9 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
|
|
||||||
StaticTextWidget* s = new StaticTextWidget(this, font, xpos, ypos + 1, "Variation ");
|
StaticTextWidget* s = new StaticTextWidget(this, font, xpos, ypos + 1, "Variation ");
|
||||||
myVariationWidget = new PopUpWidget(this, font, s->getRight(), ypos,
|
myVariationWidget = new PopUpWidget(this, font, s->getRight(), ypos,
|
||||||
font.getStringWidth("256") - 4, lineHeight, items, "", 0, 0);
|
font.getStringWidth("256") - 4, lineHeight, items, "", 0,
|
||||||
|
kVariationChanged);
|
||||||
|
wid.push_back(myVariationWidget);
|
||||||
|
|
||||||
ypos += lineHeight + VGAP * 4;
|
ypos += lineHeight + VGAP * 4;
|
||||||
|
|
||||||
|
@ -68,7 +72,7 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
int nWidth = font.getStringWidth("ABC") + 4;
|
int nWidth = font.getStringWidth("ABC") + 4;
|
||||||
|
|
||||||
new StaticTextWidget(this, font, xposRank, ypos + 1, "Rank");
|
new StaticTextWidget(this, font, xposRank, ypos + 1, "Rank");
|
||||||
new StaticTextWidget(this, font, xposScore, ypos + 1, "Score");
|
new StaticTextWidget(this, font, xposScore, ypos + 1, " Score");
|
||||||
mySpecialLabelWidget = new StaticTextWidget(this, font, xposSpecial, ypos + 1, "Round");
|
mySpecialLabelWidget = new StaticTextWidget(this, font, xposSpecial, ypos + 1, "Round");
|
||||||
new StaticTextWidget(this, font, xposName - 2, ypos + 1, "Name");
|
new StaticTextWidget(this, font, xposName - 2, ypos + 1, "Name");
|
||||||
new StaticTextWidget(this, font, xposDate+16, ypos + 1, "Date Time");
|
new StaticTextWidget(this, font, xposDate+16, ypos + 1, "Date Time");
|
||||||
|
@ -81,13 +85,11 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
(p < 9 ? " " : "") + std::to_string(p + 1));
|
(p < 9 ? " " : "") + std::to_string(p + 1));
|
||||||
myScoresWidget[p] = new StaticTextWidget(this, font, xposScore, ypos + 1, "123456");
|
myScoresWidget[p] = new StaticTextWidget(this, font, xposScore, ypos + 1, "123456");
|
||||||
mySpecialsWidget[p] = new StaticTextWidget(this, font, xposSpecial + 8, ypos + 1, "123");
|
mySpecialsWidget[p] = new StaticTextWidget(this, font, xposSpecial + 8, ypos + 1, "123");
|
||||||
myEditNamesWidget[p] = new EditTextWidget(this, font, xposName, ypos - 1, nWidth, lineHeight, "JTZ");
|
myNamesWidget[p] = new StaticTextWidget(this, font, xposName + 2, ypos + 1, " ");
|
||||||
|
myEditNamesWidget[p] = new EditTextWidget(this, font, xposName, ypos - 1, nWidth, lineHeight);
|
||||||
myEditNamesWidget[p]->setFlags(EditTextWidget::FLAG_INVISIBLE);
|
myEditNamesWidget[p]->setFlags(EditTextWidget::FLAG_INVISIBLE);
|
||||||
|
myEditNamesWidget[p]->setEnabled(false);
|
||||||
wid.push_back(myEditNamesWidget[p]);
|
wid.push_back(myEditNamesWidget[p]);
|
||||||
myNamesWidget[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");
|
|
||||||
myDatesWidget[p] = new StaticTextWidget(this, font, xposDate, ypos + 1, "12-02-20 17:15");
|
myDatesWidget[p] = new StaticTextWidget(this, font, xposDate, ypos + 1, "12-02-20 17:15");
|
||||||
|
|
||||||
ypos += lineHeight + VGAP;
|
ypos += lineHeight + VGAP;
|
||||||
|
@ -96,9 +98,8 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
|
|
||||||
myMD5Widget = new StaticTextWidget(this, ifont, xpos, ypos + 1, "MD5: 12345678901234567890123456789012");
|
myMD5Widget = new StaticTextWidget(this, ifont, xpos, ypos + 1, "MD5: 12345678901234567890123456789012");
|
||||||
|
|
||||||
wid.clear();
|
|
||||||
addOKCancelBGroup(wid, font);
|
addOKCancelBGroup(wid, font);
|
||||||
addBGroupToFocusList(wid);
|
addToFocusList(wid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -110,7 +111,7 @@ HighScoresDialog::~HighScoresDialog()
|
||||||
void HighScoresDialog::loadConfig()
|
void HighScoresDialog::loadConfig()
|
||||||
{
|
{
|
||||||
// Enable blending (only once is necessary)
|
// Enable blending (only once is necessary)
|
||||||
if(!surface().attributes().blending)
|
if (!surface().attributes().blending)
|
||||||
{
|
{
|
||||||
surface().attributes().blending = true;
|
surface().attributes().blending = true;
|
||||||
surface().attributes().blendalpha = 90;
|
surface().attributes().blendalpha = 90;
|
||||||
|
@ -120,9 +121,6 @@ void HighScoresDialog::loadConfig()
|
||||||
VariantList items;
|
VariantList items;
|
||||||
|
|
||||||
items.clear();
|
items.clear();
|
||||||
|
|
||||||
myVariation = instance().highScores().variation();
|
|
||||||
|
|
||||||
for (Int32 i = 1; i <= instance().highScores().numVariations(); ++i)
|
for (Int32 i = 1; i <= instance().highScores().numVariations(); ++i)
|
||||||
{
|
{
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
|
@ -130,87 +128,44 @@ void HighScoresDialog::loadConfig()
|
||||||
VarList::push_back(items, buf.str(), i);
|
VarList::push_back(items, buf.str(), i);
|
||||||
}
|
}
|
||||||
myVariationWidget->addItems(items);
|
myVariationWidget->addItems(items);
|
||||||
|
myDisplayedVariation = instance().highScores().variation();
|
||||||
myScore = instance().highScores().score();
|
myVariationWidget->setSelected(myDisplayedVariation);
|
||||||
mySpecial = instance().highScores().special();
|
|
||||||
myVariationWidget->setSelected(myVariation);
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// mock data
|
|
||||||
const Int32 SCORES[NUM_POSITIONS] = {999999, 250000, 100000, 50000, 20000,
|
|
||||||
5000, 2000, 200, 20, 0};
|
|
||||||
const Int32 SPECIALS[NUM_POSITIONS] = {200, 150, 90, 70, 45,
|
|
||||||
30, 25, 10, 7, 0};
|
|
||||||
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] = SCORES[p];
|
|
||||||
mySpecials[p] = SPECIALS[p];
|
|
||||||
myNames[p] = NAMES[p];
|
|
||||||
myDates[p] = DATES[p];
|
|
||||||
}
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
Int32 pos;
|
|
||||||
|
|
||||||
mySpecialLabelWidget->setLabel(instance().highScores().specialLabel());
|
mySpecialLabelWidget->setLabel(instance().highScores().specialLabel());
|
||||||
|
|
||||||
|
// TDOO: required when leaving with hot key
|
||||||
for (Int32 p = 0; p < NUM_POSITIONS; ++p)
|
for (Int32 p = 0; p < NUM_POSITIONS; ++p)
|
||||||
|
{
|
||||||
|
myNamesWidget[p]->clearFlags(EditTextWidget::FLAG_INVISIBLE);
|
||||||
myEditNamesWidget[p]->setFlags(EditTextWidget::FLAG_INVISIBLE);
|
myEditNamesWidget[p]->setFlags(EditTextWidget::FLAG_INVISIBLE);
|
||||||
|
myEditNamesWidget[p]->setEnabled(false);
|
||||||
if (myScore > 0)
|
|
||||||
{
|
|
||||||
for (pos = 0; pos < NUM_POSITIONS; ++pos)
|
|
||||||
{
|
|
||||||
if (myScore > myScores[pos] ||
|
|
||||||
(myScore == myScores[pos] && mySpecial > mySpecials[pos]))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos < NUM_POSITIONS)
|
|
||||||
{
|
|
||||||
for (Int32 p = NUM_POSITIONS - 1; p > pos; --p)
|
|
||||||
{
|
|
||||||
myScores[p] = myScores[p - 1];
|
|
||||||
mySpecials[p] = mySpecials[p - 1];
|
|
||||||
myNames[p] = myNames[p - 1];
|
|
||||||
myDates[p] = myDates[p - 1];
|
|
||||||
}
|
|
||||||
myScores[pos] = myScore;
|
|
||||||
myNames[pos] = "";
|
|
||||||
mySpecials[pos] = mySpecial;
|
|
||||||
myDates[pos] = now();
|
|
||||||
|
|
||||||
myEditNamesWidget[pos]->clearFlags(EditTextWidget::FLAG_INVISIBLE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Int32 p = 0; p < NUM_POSITIONS; ++p)
|
myMD5 = instance().console().properties().get(PropType::Cart_MD5);
|
||||||
{
|
myMD5Widget->setLabel("MD5: " + myMD5);
|
||||||
ostringstream buf;
|
|
||||||
|
|
||||||
buf << std::setw(HSM::MAX_SCORE_DIGITS) << std::setfill(' ') << myScores[p];
|
|
||||||
myScoresWidget[p]->setLabel(buf.str());
|
myPlayedVariation = instance().highScores().variation();
|
||||||
buf.str("");
|
|
||||||
buf << std::setw(HSM::MAX_SPECIAL_DIGITS) << std::setfill(' ') << mySpecials[p];
|
myEditPos = myHighScorePos = -1;
|
||||||
mySpecialsWidget[p]->setLabel(buf.str());
|
myNow = now();
|
||||||
myNamesWidget[p]->setLabel(myNames[p]);
|
handleVariation(true);
|
||||||
myEditNamesWidget[p]->setText(myNames[p]);
|
|
||||||
myDatesWidget[p]->setLabel(myDates[p]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void HighScoresDialog::saveConfig()
|
void HighScoresDialog::saveConfig()
|
||||||
{
|
{
|
||||||
|
if (myHighScorePos != -1)
|
||||||
|
{
|
||||||
|
if (myDisplayedVariation != myPlayedVariation)
|
||||||
|
{
|
||||||
|
loadHighScores(myPlayedVariation);
|
||||||
|
handlePlayedVariation();
|
||||||
|
}
|
||||||
|
myInitials = myEditNamesWidget[myHighScorePos]->getText();
|
||||||
|
myNames[myHighScorePos] = myInitials;
|
||||||
|
saveHighScores();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -220,12 +175,14 @@ void HighScoresDialog::handleCommand(CommandSender* sender, int cmd, int data, i
|
||||||
{
|
{
|
||||||
case kOKCmd:
|
case kOKCmd:
|
||||||
saveConfig();
|
saveConfig();
|
||||||
|
// falls through...
|
||||||
case kCloseCmd:
|
case kCloseCmd:
|
||||||
|
resetVisibility();
|
||||||
instance().eventHandler().leaveMenuMode();
|
instance().eventHandler().leaveMenuMode();
|
||||||
// instance().eventHandler().handleEvent(Event::ExitMode);
|
break;
|
||||||
|
|
||||||
// case GuiObject::kOKCmd:
|
case kVariationChanged:
|
||||||
// close();
|
handleVariation();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -248,3 +205,258 @@ string HighScoresDialog::now() const
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HighScoresDialog::resetVisibility()
|
||||||
|
{
|
||||||
|
if (myEditPos != -1)
|
||||||
|
{
|
||||||
|
// hide again
|
||||||
|
myEditNamesWidget[myEditPos]->setFlags(EditTextWidget::FLAG_INVISIBLE);
|
||||||
|
myEditNamesWidget[myEditPos]->setEnabled(false);
|
||||||
|
myNamesWidget[myEditPos]->clearFlags(EditTextWidget::FLAG_INVISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HighScoresDialog::handlePlayedVariation()
|
||||||
|
{
|
||||||
|
Int32 newScore = instance().highScores().score();
|
||||||
|
|
||||||
|
if (newScore > 0)
|
||||||
|
{
|
||||||
|
Int32 newSpecial = instance().highScores().special();
|
||||||
|
for (myHighScorePos = 0; myHighScorePos < NUM_POSITIONS; ++myHighScorePos)
|
||||||
|
{
|
||||||
|
if (newScore > myHighScores[myHighScorePos] ||
|
||||||
|
(newScore == myHighScores[myHighScorePos] && newSpecial > mySpecials[myHighScorePos]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myHighScorePos < NUM_POSITIONS)
|
||||||
|
{
|
||||||
|
myEditPos = myHighScorePos;
|
||||||
|
for (Int32 p = NUM_POSITIONS - 1; p > myHighScorePos; --p)
|
||||||
|
{
|
||||||
|
myHighScores[p] = myHighScores[p - 1];
|
||||||
|
mySpecials[p] = mySpecials[p - 1];
|
||||||
|
myNames[p] = myNames[p - 1];
|
||||||
|
myDates[p] = myDates[p - 1];
|
||||||
|
}
|
||||||
|
myHighScores[myHighScorePos] = newScore;
|
||||||
|
//myNames[myHighScorePos] = "";
|
||||||
|
mySpecials[myHighScorePos] = newSpecial;
|
||||||
|
myDates[myHighScorePos] = myNow;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
myHighScorePos = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HighScoresDialog::handleVariation(bool init)
|
||||||
|
{
|
||||||
|
resetVisibility();
|
||||||
|
|
||||||
|
myDisplayedVariation = myVariationWidget->getSelectedTag().toInt();
|
||||||
|
|
||||||
|
loadHighScores(myDisplayedVariation);
|
||||||
|
|
||||||
|
myEditPos = -1;
|
||||||
|
|
||||||
|
if (myDisplayedVariation == myPlayedVariation)
|
||||||
|
{
|
||||||
|
handlePlayedVariation();
|
||||||
|
|
||||||
|
if (myHighScorePos != -1)
|
||||||
|
{
|
||||||
|
myNamesWidget[myHighScorePos]->setFlags(EditTextWidget::FLAG_INVISIBLE);
|
||||||
|
myEditNamesWidget[myHighScorePos]->clearFlags(EditTextWidget::FLAG_INVISIBLE);
|
||||||
|
myEditNamesWidget[myHighScorePos]->setEnabled(true);
|
||||||
|
myEditNamesWidget[myHighScorePos]->setEditable(true);
|
||||||
|
if (init)
|
||||||
|
myEditNamesWidget[myHighScorePos]->setText(myInitials);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Int32 p = 0; p < NUM_POSITIONS; ++p)
|
||||||
|
{
|
||||||
|
ostringstream buf;
|
||||||
|
|
||||||
|
if (myHighScores[p] > 0)
|
||||||
|
buf << std::setw(HSM::MAX_SCORE_DIGITS) << std::setfill(' ') << myHighScores[p];
|
||||||
|
myScoresWidget[p]->setLabel(buf.str());
|
||||||
|
|
||||||
|
buf.str("");
|
||||||
|
if (mySpecials[p] > 0)
|
||||||
|
buf << std::setw(HSM::MAX_SPECIAL_DIGITS) << std::setfill(' ') << mySpecials[p];
|
||||||
|
mySpecialsWidget[p]->setLabel(buf.str());
|
||||||
|
|
||||||
|
myNamesWidget[p]->setLabel(myNames[p]);
|
||||||
|
myDatesWidget[p]->setLabel(myDates[p]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HighScoresDialog::saveHighScores() const
|
||||||
|
{
|
||||||
|
if(instance().hasConsole())
|
||||||
|
{
|
||||||
|
ostringstream buf;
|
||||||
|
buf << instance().stateDir()
|
||||||
|
<< instance().console().properties().get(PropType::Cart_Name)
|
||||||
|
<< ".hs" << myPlayedVariation;
|
||||||
|
|
||||||
|
// Make sure the file can be opened for writing
|
||||||
|
Serializer out(buf.str());
|
||||||
|
|
||||||
|
if(!out)
|
||||||
|
{
|
||||||
|
buf.str("");
|
||||||
|
buf << "Can't open/save to high scores file for variation " << myPlayedVariation;
|
||||||
|
instance().frameBuffer().showMessage(buf.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do a complete high scores save
|
||||||
|
if (!save(out))
|
||||||
|
{
|
||||||
|
buf.str("");
|
||||||
|
buf << "Error saving high scores for variation" << myPlayedVariation;
|
||||||
|
instance().frameBuffer().showMessage(buf.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HighScoresDialog::loadHighScores(Int32 variation)
|
||||||
|
{
|
||||||
|
for (Int32 p = 0; p < NUM_POSITIONS; ++p)
|
||||||
|
{
|
||||||
|
myHighScores[p] = 0;
|
||||||
|
mySpecials[p] = 0;
|
||||||
|
myNames[p] = "";
|
||||||
|
myDates[p] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
// mock data
|
||||||
|
const Int32 SCORES[NUM_POSITIONS] = {999999, 250000, 100000, 50000, 20000,
|
||||||
|
5000, 2000, 200, 20, 0};
|
||||||
|
const Int32 SPECIALS[NUM_POSITIONS] = {200, 150, 90, 70, 45,
|
||||||
|
30, 25, 10, 7, 0};
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
myHighScores[p] = SCORES[p];
|
||||||
|
mySpecials[p] = SPECIALS[p];
|
||||||
|
myNames[p] = NAMES[p];
|
||||||
|
myDates[p] = DATES[p];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
if(instance().hasConsole())
|
||||||
|
{
|
||||||
|
ostringstream buf;
|
||||||
|
buf << instance().stateDir()
|
||||||
|
<< instance().console().properties().get(PropType::Cart_Name)
|
||||||
|
<< ".hs" << variation;
|
||||||
|
|
||||||
|
// Make sure the file can be opened in read-only mode
|
||||||
|
Serializer in(buf.str(), Serializer::Mode::ReadOnly);
|
||||||
|
if(!in)
|
||||||
|
{
|
||||||
|
//buf.str("");
|
||||||
|
//buf << "No high scores file for variation " << variation << " found.";
|
||||||
|
//instance().frameBuffer().showMessage(buf.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First test if we have a valid header
|
||||||
|
// If so, do a complete high scores load
|
||||||
|
buf.str("");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (in.getString() != HIGHSCORE_HEADER)
|
||||||
|
buf << "Incompatible high scores for variation " << variation << " file";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (load(in, variation))
|
||||||
|
//buf << "High scores for variation " << variation << " loaded";
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
buf << "Invalid data in high scores for variation " << variation << " file";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
buf << "Invalid data in high scores for variation " << variation << " file";
|
||||||
|
}
|
||||||
|
|
||||||
|
instance().frameBuffer().showMessage(buf.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool HighScoresDialog::save(Serializer& out) const
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Add header so that if the high score format changes in the future,
|
||||||
|
// we'll know right away, without having to parse the rest of the file
|
||||||
|
out.putString(HIGHSCORE_HEADER);
|
||||||
|
|
||||||
|
out.putString(myMD5);
|
||||||
|
out.putInt(myPlayedVariation);
|
||||||
|
for (Int32 p = 0; p < NUM_POSITIONS; ++p)
|
||||||
|
{
|
||||||
|
out.putInt(myHighScores[p]);
|
||||||
|
out.putInt(mySpecials[p]);
|
||||||
|
out.putString(myNames[p]);
|
||||||
|
out.putString(myDates[p]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: HighScoresDialog::save() exception\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool HighScoresDialog::load(Serializer& in, Int32 variation)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (in.getString() != myMD5)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Int32(in.getInt()) != variation)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (Int32 p = 0; p < NUM_POSITIONS; ++p)
|
||||||
|
{
|
||||||
|
myHighScores[p] = in.getInt();
|
||||||
|
mySpecials[p] = in.getInt();
|
||||||
|
myNames[p] = in.getString();
|
||||||
|
myDates[p] = in.getString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: HighScoresDialog::load() exception\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -15,8 +15,10 @@
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#ifndef MESSAGE_DIALOG_HXX
|
#ifndef HIGHSCORE_DIALOG_HXX
|
||||||
#define MESSAGE_DIALOG_HXX
|
#define HIGHSCORE_DIALOG_HXX
|
||||||
|
|
||||||
|
#define HIGHSCORE_HEADER "06000000highscores"
|
||||||
|
|
||||||
//class Properties;
|
//class Properties;
|
||||||
class CommandSender;
|
class CommandSender;
|
||||||
|
@ -25,6 +27,8 @@ class OSystem;
|
||||||
class EditTextWidget;
|
class EditTextWidget;
|
||||||
class PopUpWidget;
|
class PopUpWidget;
|
||||||
|
|
||||||
|
#include "Serializable.hxx"
|
||||||
|
|
||||||
#include "Dialog.hxx"
|
#include "Dialog.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,12 +51,43 @@ class HighScoresDialog : public Dialog
|
||||||
void saveConfig() override;
|
void saveConfig() override;
|
||||||
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
||||||
|
|
||||||
private:
|
void handlePlayedVariation();
|
||||||
Int32 myVariation;
|
void handleVariation(bool init = false);
|
||||||
Int32 myScore;
|
void resetVisibility();
|
||||||
Int32 mySpecial;
|
|
||||||
|
|
||||||
Int32 myScores[NUM_POSITIONS];
|
void saveHighScores() const;
|
||||||
|
void loadHighScores(Int32 variation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Saves the current high scores for this game and variation to the given Serializer.
|
||||||
|
|
||||||
|
@param out The serializer device to save to.
|
||||||
|
@return The result of the save. True on success, false on failure.
|
||||||
|
*/
|
||||||
|
bool save(Serializer& out) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads the current high scores for this game and variation from the given Serializer.
|
||||||
|
|
||||||
|
@param in The Serializer device to load from.
|
||||||
|
@return The result of the load. True on success, false on failure.
|
||||||
|
*/
|
||||||
|
bool load(Serializer& in, Int32 variation);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kVariationChanged = 'Vach'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
string myInitials;
|
||||||
|
Int32 myDisplayedVariation;
|
||||||
|
Int32 myPlayedVariation;
|
||||||
|
Int32 myEditPos;
|
||||||
|
Int32 myHighScorePos;
|
||||||
|
string myNow;
|
||||||
|
|
||||||
|
Int32 myHighScores[NUM_POSITIONS];
|
||||||
Int32 mySpecials[NUM_POSITIONS];
|
Int32 mySpecials[NUM_POSITIONS];
|
||||||
string myNames[NUM_POSITIONS];
|
string myNames[NUM_POSITIONS];
|
||||||
string myDates[NUM_POSITIONS];
|
string myDates[NUM_POSITIONS];
|
||||||
|
|
Loading…
Reference in New Issue