From bac7b0552e10f8def1d71ecf4664dfec1f1e9dd7 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 16 Feb 2020 21:37:22 +0100 Subject: [PATCH] add HighScoresDialog to LauncherDialog remove high scores debug events add Dragster data to stella.pro --- src/common/HighScoresManager.cxx | 4 +- src/common/HighScoresManager.hxx | 4 +- src/common/PKeyboardHandler.cxx | 2 - src/common/stella.pro | 10 ++ src/emucore/Event.hxx | 2 +- src/emucore/EventHandler.cxx | 27 +---- src/gui/HighScoresDialog.cxx | 186 ++++++++++++++++--------------- src/gui/HighScoresDialog.hxx | 6 +- src/gui/HighScoresMenu.cxx | 5 +- src/gui/LauncherDialog.cxx | 31 +++++- src/gui/LauncherDialog.hxx | 3 + 11 files changed, 152 insertions(+), 128 deletions(-) diff --git a/src/common/HighScoresManager.cxx b/src/common/HighScoresManager.cxx index bcf840d76..e903849f5 100644 --- a/src/common/HighScoresManager.cxx +++ b/src/common/HighScoresManager.cxx @@ -347,7 +347,7 @@ uInt32 HighScoresManager::numAddrBytes(const Properties& props) const Int32 HighScoresManager::player(uInt16 addr, uInt32 numPlayers, bool zeroBased) const { if (!myOSystem.hasConsole()) - return -1; + return DEFAULT_PLAYER; Int32 player = peek(addr); Int32 bits = ceil(log(numPlayers + (!zeroBased ? 1 : 0))/log(2)); @@ -393,7 +393,7 @@ Int32 HighScoresManager::variation(uInt16 addr, bool varBCD, bool zeroBased, uInt32 numVariations) const { if (!myOSystem.hasConsole()) - return -1; + return DEFAULT_VARIATION; Int32 var = peek(addr); Int32 bits = ceil(log(numVariations + (!zeroBased ? 1 : 0))/log(2)); diff --git a/src/common/HighScoresManager.hxx b/src/common/HighScoresManager.hxx index b5466fd3c..fefe018fe 100644 --- a/src/common/HighScoresManager.hxx +++ b/src/common/HighScoresManager.hxx @@ -20,6 +20,8 @@ class OSystem; +#include "Props.hxx" + namespace HSM { static const uInt32 MAX_PLAYERS = 4; static const uInt32 MAX_ADDR_CHARS = 4; @@ -62,8 +64,6 @@ using namespace HSM; This class provides an interface to define, load and save scores. It is meant for games which do not support saving highscores. - TODO: load and saves scores - @author Thomas Jentzsch */ diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx index 71dadc1d1..7197d2426 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -505,8 +505,6 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo {Event::Unwind1Menu, KBDK_RIGHT, MOD3}, {Event::Unwind10Menu, KBDK_RIGHT, KBDM_SHIFT | MOD3}, {Event::UnwindAllMenu, KBDK_UP, MOD3}, - {Event::ShowScore, KBDK_S, KBDM_SHIFT | KBDM_CTRL}, - {Event::ShowVariation, KBDK_V, KBDM_SHIFT | KBDM_CTRL}, {Event::HighScoresMenuMode, KBDK_INSERT}, #if defined(RETRON77) diff --git a/src/common/stella.pro b/src/common/stella.pro index 05a3f0f93..03d468d80 100644 --- a/src/common/stella.pro +++ b/src/common/stella.pro @@ -27,6 +27,16 @@ "Cart.Addresses" "E6,E8,DC" "" +"Cart.MD5" "77057d9d14b99e465ea9e29783af0ae3" +"Cart.Manufacturer" "Activision, David Crane" +"Cart.ModelNo" "AG-001" +"Cart.Name" "Dragster (1980) (Activision)" +"Cart.Note" "AKA Drag Strip" +"Cart.Players" "2" +"Cart.Formats" "4,0,B,B,1,-,D,0,1" +"Cart.Addresses" "B3,B5,B4,B6,80,80,0" +"" + "Cart.MD5" "91c2098e88a6b13f977af8c003e0bca5" "Cart.Manufacturer" "Atari - GCC" "Cart.ModelNo" "CX2676" diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx index df16ae5cd..045a0bc8b 100644 --- a/src/emucore/Event.hxx +++ b/src/emucore/Event.hxx @@ -120,7 +120,7 @@ class Event ToggleFrameStats, ToggleSAPortOrder, ExitGame, // add new events from here to avoid that user remapped events get overwritten - ShowScore, ShowVariation, HighScoresMenuMode, + HighScoresMenuMode, LastType }; diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index e8a17699f..b2779c41f 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -721,27 +721,6 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) if(pressed && !repeated) myOSystem.frameBuffer().tiaSurface().saveSnapShot(); return; - #ifdef GUI_SUPPORT - // Debug only, TODO: remove! - case Event::ShowScore: - if (pressed) - { - ostringstream msg; - msg << "Score: " << myOSystem.highScores().score(); - myOSystem.frameBuffer().showMessage(msg.str()); - } - return; - - case Event::ShowVariation: - if (pressed) - { - ostringstream msg; - msg << "Variation: " << myOSystem.highScores().variation(); - myOSystem.frameBuffer().showMessage(msg.str()); - } - return; - #endif - case Event::ExitMode: // Special handling for Escape key // Basically, exit whichever mode we're currently in @@ -1857,6 +1836,7 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { { { Event::ExitMode, "Exit current Stella menu/mode", "" }, { Event::OptionsMenuMode, "Enter Options menu UI", "" }, { Event::CmdMenuMode, "Toggle Commands menu UI", "" }, + { Event::HighScoresMenuMode, "Toggle High Scores UI", "" }, { Event::TogglePauseMode, "Toggle Pause mode", "" }, { Event::StartPauseMode, "Start Pause mode", "" }, { Event::Fry, "Fry cartridge", "" }, @@ -2035,9 +2015,6 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { { { Event::Combo14, "Combo 14", "" }, { Event::Combo15, "Combo 15", "" }, { Event::Combo16, "Combo 16", "" }, - { Event::ShowScore, "Display current score", "" }, - { Event::ShowVariation, "Display current variation", "" }, - { Event::HighScoresMenuMode, "Toggle High Scores UI", "" }, } }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2076,7 +2053,7 @@ const Event::EventSet EventHandler::MiscEvents = { // Event::MouseButtonLeftValue, Event::MouseButtonRightValue, Event::HandleMouseControl, Event::ToggleGrabMouse, Event::ToggleSAPortOrder, - Event::ShowScore, Event::ShowVariation, + Event::HighScoresMenuMode }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/HighScoresDialog.cxx b/src/gui/HighScoresDialog.cxx index c5d38e7ad..3f5df155b 100644 --- a/src/gui/HighScoresDialog.cxx +++ b/src/gui/HighScoresDialog.cxx @@ -17,6 +17,7 @@ #include "OSystem.hxx" #include "Console.hxx" +#include "Launcher.hxx" #include "EventHandler.hxx" #include "Font.hxx" #include "FBSurface.hxx" @@ -30,16 +31,18 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font, int max_w, int max_h) - : Dialog(osystem, parent, font, "High Scores"), - _max_w(max_w), - _max_h(max_h), - myInitials(""), - myDirty(false) + int max_w, int max_h, + Menu::AppMode mode) + : Dialog(osystem, parent, osystem.frameBuffer().font(), "High Scores"), + myMode(mode), + _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(); + const int lineHeight = _font.getLineHeight(), + fontWidth = _font.getMaxCharWidth(); const int VBORDER = 8; const int HBORDER = 10; const int VGAP = 4; @@ -56,43 +59,43 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, //items.clear(); - StaticTextWidget* s = new StaticTextWidget(this, font, xpos, ypos + 1, "Variation "); - myVariationWidget = new PopUpWidget(this, font, s->getRight(), ypos, - font.getStringWidth("256") - 4, lineHeight, items, "", 0, + StaticTextWidget* s = new StaticTextWidget(this, _font, xpos, ypos + 1, "Variation "); + myVariationWidget = new PopUpWidget(this, _font, s->getRight(), ypos, + _font.getStringWidth("256") - 4, lineHeight, items, "", 0, kVariationChanged); wid.push_back(myVariationWidget); ypos += lineHeight + VGAP * 4; int xposRank = HBORDER; - int xposScore = xposRank + font.getStringWidth("Rank") + 16; - int xposSpecial = xposScore + font.getStringWidth("Score") + 24; - int xposName = xposSpecial + font.getStringWidth("Round") + 16; - int xposDate = xposName + font.getStringWidth("Name") + 16; - int xposDelete = xposDate + font.getStringWidth("YY-MM-DD HH:MM") + 16; - int nWidth = font.getStringWidth("ABC") + 4; + int xposScore = xposRank + _font.getStringWidth("Rank") + 16; + int xposSpecial = xposScore + _font.getStringWidth("Score") + 24; + int xposName = xposSpecial + _font.getStringWidth("Round") + 16; + int xposDate = xposName + _font.getStringWidth("Name") + 16; + int xposDelete = xposDate + _font.getStringWidth("YY-MM-DD HH:MM") + 16; + int nWidth = _font.getStringWidth("ABC") + 4; - new StaticTextWidget(this, font, xposRank, ypos + 1, "Rank"); - new StaticTextWidget(this, font, xposScore, ypos + 1, " Score"); - mySpecialLabelWidget = new StaticTextWidget(this, font, xposSpecial, ypos + 1, "Round"); - new StaticTextWidget(this, font, xposName - 2, ypos + 1, "Name"); - new StaticTextWidget(this, font, xposDate+16, ypos + 1, "Date Time"); + new StaticTextWidget(this, _font, xposRank, ypos + 1, "Rank"); + new StaticTextWidget(this, _font, xposScore, ypos + 1, " Score"); + mySpecialLabelWidget = new StaticTextWidget(this, _font, xposSpecial, ypos + 1, "Round"); + new StaticTextWidget(this, _font, xposName - 2, ypos + 1, "Name"); + new StaticTextWidget(this, _font, xposDate+16, ypos + 1, "Date Time"); ypos += lineHeight + VGAP; for (uInt32 p = 0; p < NUM_POSITIONS; ++p) { - myPositionsWidget[p] = new StaticTextWidget(this, font, xposRank + 8, ypos + 1, + myPositionsWidget[p] = new StaticTextWidget(this, _font, xposRank + 8, ypos + 1, (p < 9 ? " " : "") + std::to_string(p + 1)); - myScoresWidget[p] = new StaticTextWidget(this, font, xposScore, ypos + 1, "123456"); - mySpecialsWidget[p] = new StaticTextWidget(this, font, xposSpecial + 8, ypos + 1, "123"); - myNamesWidget[p] = new StaticTextWidget(this, font, xposName + 2, ypos + 1, " "); - myEditNamesWidget[p] = new EditTextWidget(this, font, xposName, ypos - 1, nWidth, lineHeight); + myScoresWidget[p] = new StaticTextWidget(this, _font, xposScore, ypos + 1, "123456"); + mySpecialsWidget[p] = new StaticTextWidget(this, _font, xposSpecial + 8, ypos + 1, "123"); + 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]->setEnabled(false); wid.push_back(myEditNamesWidget[p]); - myDatesWidget[p] = new StaticTextWidget(this, font, xposDate, ypos + 1, "12-02-20 17:15"); - myDeleteButtons[p] = new ButtonWidget(this, font, xposDelete, ypos + 1, 18, 18, "X", + myDatesWidget[p] = new StaticTextWidget(this, _font, xposDate, ypos + 1, "12-02-20 17:15"); + myDeleteButtons[p] = new ButtonWidget(this, _font, xposDelete, ypos + 1, 18, 18, "X", kDeleteSingle); myDeleteButtons[p]->setID(p); wid.push_back(myDeleteButtons[p]); @@ -103,9 +106,8 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, myMD5Widget = new StaticTextWidget(this, ifont, xpos, ypos + 1, "MD5: 12345678901234567890123456789012"); - addDefaultsOKCancelBGroup(wid, font, "Save", "Cancel", " Reset "); - addToFocusList(wid); -} + addDefaultsOKCancelBGroup(wid, _font, "Save", "Cancel", " Reset "); + addToFocusList(wid); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HighScoresDialog::~HighScoresDialog() @@ -142,7 +144,11 @@ void HighScoresDialog::loadConfig() label = label.substr(label.length() - 5); mySpecialLabelWidget->setLabel(label); - myMD5 = instance().console().properties().get(PropType::Cart_MD5); + if (instance().hasConsole()) + myMD5 = instance().console().properties().get(PropType::Cart_MD5); + else + myMD5 = instance().launcher().selectedRomMD5(); + myMD5Widget->setLabel("MD5: " + myMD5); myEditPos = myHighScorePos = -1; @@ -173,7 +179,10 @@ void HighScoresDialog::handleCommand(CommandSender* sender, int cmd, int data, i saveConfig(); [[fallthrough]]; case kCloseCmd: - instance().eventHandler().leaveMenuMode(); + if(myMode != Menu::AppMode::emulator) + close(); + else + instance().eventHandler().leaveMenuMode(); break; case kVariationChanged: @@ -269,7 +278,6 @@ void HighScoresDialog::updateWidgets(bool init) myEditNamesWidget[p]->setEditable(false); } } - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -363,33 +371,39 @@ bool HighScoresDialog::handleDirty() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void HighScoresDialog::saveHighScores(Int32 variation) const +string HighScoresDialog::cartName() const { if(instance().hasConsole()) + return instance().console().properties().get(PropType::Cart_Name); + else + return instance().launcher().currentNode().getNameWithExt(""); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void HighScoresDialog::saveHighScores(Int32 variation) const +{ + ostringstream buf; + + buf << instance().stateDir() << cartName() << ".hs" << variation; + + // Make sure the file can be opened for writing + Serializer out(buf.str()); + + if(!out) { - ostringstream buf; - buf << instance().stateDir() - << instance().console().properties().get(PropType::Cart_Name) - << ".hs" << variation; - - // 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 " << variation; - instance().frameBuffer().showMessage(buf.str()); - } - - // Do a complete high scores save - if (!save(out, variation)) - { - buf.str(""); - buf << "Error saving high scores for variation" << variation; - instance().frameBuffer().showMessage(buf.str()); - } + buf.str(""); + buf << "Can't open/save to high scores file for variation " << variation; + instance().frameBuffer().showMessage(buf.str()); } + + // Do a complete high scores save + if(!save(out, variation)) + { + buf.str(""); + buf << "Error saving high scores for variation" << variation; + instance().frameBuffer().showMessage(buf.str()); + } + } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -403,41 +417,37 @@ void HighScoresDialog::loadHighScores(Int32 variation) myDates[p] = ""; } - if(instance().hasConsole()) + ostringstream buf; + + buf << instance().stateDir() << cartName() << ".hs" << variation; + + // Make sure the file can be opened in read-only mode + Serializer in(buf.str(), Serializer::Mode::ReadOnly); + + if(!in) + return; + + // First test if we have a valid header + // If so, do a complete high scores load + buf.str(""); + try { - 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) - 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 (in.getString() != HIGHSCORE_HEADER) - buf << "Incompatible high scores for variation " << variation << " file"; + if (load(in, variation)) + return; else - { - if (load(in, variation)) - return; - else - buf << "Invalid data in high scores for variation " << variation << " file"; - } + 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()); } + catch(...) + { + buf << "Invalid data in high scores for variation " << variation << " file"; + } + + instance().frameBuffer().showMessage(buf.str()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/HighScoresDialog.hxx b/src/gui/HighScoresDialog.hxx index ea2eeb236..a6f4edb25 100644 --- a/src/gui/HighScoresDialog.hxx +++ b/src/gui/HighScoresDialog.hxx @@ -31,6 +31,7 @@ namespace GUI { } class Serializer; +#include "Menu.hxx" #include "Dialog.hxx" /** @@ -45,7 +46,7 @@ class HighScoresDialog : public Dialog static const uInt32 NUM_POSITIONS = 10; HighScoresDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font, int max_w, int max_h); + int max_w, int max_h, Menu::AppMode mode); virtual ~HighScoresDialog(); protected: @@ -60,6 +61,7 @@ class HighScoresDialog : public Dialog void deletePos(int pos); bool handleDirty(); + string cartName() const; void saveHighScores(Int32 variation) const; void loadHighScores(Int32 variation); @@ -119,6 +121,8 @@ class HighScoresDialog : public Dialog StaticTextWidget* myMD5Widget{nullptr}; + Menu::AppMode myMode{Menu::AppMode::emulator}; + private: // Following constructors and assignment operators not supported HighScoresDialog() = delete; diff --git a/src/gui/HighScoresMenu.cxx b/src/gui/HighScoresMenu.cxx index 3bcb7321d..0011c9bc1 100644 --- a/src/gui/HighScoresMenu.cxx +++ b/src/gui/HighScoresMenu.cxx @@ -36,8 +36,9 @@ HighScoresMenu::~HighScoresMenu() Dialog* HighScoresMenu::baseDialog() { if (myHighScoresDialog == nullptr) - myHighScoresDialog = new HighScoresDialog(myOSystem, *this, myOSystem.frameBuffer().font(), - FBMinimum::Width, FBMinimum::Height); + myHighScoresDialog = new HighScoresDialog(myOSystem, *this, + FBMinimum::Width, FBMinimum::Height, + Menu::AppMode::emulator); return myHighScoresDialog; } diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index 761c08e1c..7350b6873 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -26,6 +26,8 @@ #include "FSNode.hxx" #include "MD5.hxx" #include "OptionsDialog.hxx" +#include "HighScoresDialog.hxx" +#include "HighScoresManager.hxx" #include "GlobalPropsDialog.hxx" #include "StellaSettingsDialog.hxx" #include "MessageBox.hxx" @@ -204,11 +206,8 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, addToFocusList(wid); - // Create context menu for ROM list options - VariantList l; - VarList::push_back(l, "Power-on options" + ELLIPSIS, "override"); - VarList::push_back(l, "Reload listing", "reload"); - myMenu = make_unique(this, osystem.frameBuffer().font(), l); + // Create (empty) context menu for ROM list options + myMenu = make_unique(this, osystem.frameBuffer().font(), EmptyVarList); // Create global props dialog, which is used to temporarily overrride // ROM properties @@ -353,6 +352,8 @@ void LauncherDialog::handleContextMenu() myGlobalProps->open(); else if(cmd == "reload") reload(); + else if(cmd == "highscores") + openHighScores(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -460,6 +461,15 @@ void LauncherDialog::handleMouseDown(int x, int y, MouseButton b, int clickCount // Grab right mouse button for context menu, send left to base class if(b == MouseButton::RIGHT) { + // Dynamically create context menu for ROM list options + VariantList items; + + VarList::push_back(items, "Power-on options" + ELLIPSIS, "override"); + if(instance().highScores().enabled()) + VarList::push_back(items, "High scores" + ELLIPSIS, "highscores"); + VarList::push_back(items, "Reload listing", "reload"); + myMenu->addItems(items); + // Add menu at current x,y mouse location myMenu->show(x + getAbsX(), y + getAbsY(), surface().dstRect()); } @@ -565,3 +575,14 @@ void LauncherDialog::openSettings() myOptionsDialog->open(); } } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void LauncherDialog::openHighScores() +{ + // Create an options dialog, similar to the in-game one + if(myHighScoresDialog == nullptr) + myHighScoresDialog = make_unique(instance(), parent(), _w, _h, + Menu::AppMode::launcher); + + myHighScoresDialog->open(); +} diff --git a/src/gui/LauncherDialog.hxx b/src/gui/LauncherDialog.hxx index f43a57439..7aba78f22 100644 --- a/src/gui/LauncherDialog.hxx +++ b/src/gui/LauncherDialog.hxx @@ -24,6 +24,7 @@ class ContextMenu; class DialogContainer; class BrowserDialog; class OptionsDialog; +class HighScoresDialog; class GlobalPropsDialog; class StellaSettingsDialog; class OSystem; @@ -103,9 +104,11 @@ class LauncherDialog : public Dialog void handleContextMenu(); void showOnlyROMs(bool state); void openSettings(); + void openHighScores(); private: unique_ptr myOptionsDialog; + unique_ptr myHighScoresDialog; unique_ptr myStellaSettingsDialog; unique_ptr myMenu; unique_ptr myGlobalProps;