diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx index 0389928aa..4bbd24ff4 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -507,6 +507,7 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo {Event::UnwindAllMenu, KBDK_UP, MOD3}, {Event::ShowScore, KBDK_S, KBDM_SHIFT | KBDM_CTRL}, {Event::ShowVariation, KBDK_V, KBDM_SHIFT | KBDM_CTRL}, + {Event::HighScoresMenuMode, KBDK_HOME}, #if defined(RETRON77) {Event::ConsoleColorToggle, KBDK_F4}, // back ("COLOR","B/W") diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx index 9a3925650..df16ae5cd 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, + ShowScore, ShowVariation, HighScoresMenuMode, LastType }; @@ -135,7 +135,7 @@ class Event }; // Event list version, update only if the id of existing(!) event types changed - static constexpr Int32 VERSION = 3; + static constexpr Int32 VERSION = 4; using EventSet = std::set; diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index b8a081ac6..3c71cc9ef 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -56,6 +56,7 @@ #ifdef GUI_SUPPORT #include "Menu.hxx" #include "CommandMenu.hxx" + #include "HighScoresMenu.hxx" #include "MessageMenu.hxx" #include "DialogContainer.hxx" #include "Launcher.hxx" @@ -1057,6 +1058,15 @@ bool EventHandler::changeStateByEvent(Event::Type type) handled = false; break; + case Event::HighScoresMenuMode: + if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE) + enterMenuMode(EventHandlerState::HIGHSCORESMENU); + else if(myState == EventHandlerState::HIGHSCORESMENU) + leaveMenuMode(); + else + handled = false; + break; + case Event::TimeMachineMode: if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE) enterTimeMachineMenuMode(0, false); @@ -1758,6 +1768,11 @@ void EventHandler::setState(EventHandlerState state) enableTextEvents(true); break; + case EventHandlerState::HIGHSCORESMENU: + myOverlay = &myOSystem.highscoresMenu(); + enableTextEvents(true); + break; + case EventHandlerState::MESSAGEMENU: myOverlay = &myOSystem.messageMenu(); enableTextEvents(true); diff --git a/src/emucore/EventHandlerConstants.hxx b/src/emucore/EventHandlerConstants.hxx index d25d5bf67..b9df629d8 100644 --- a/src/emucore/EventHandlerConstants.hxx +++ b/src/emucore/EventHandlerConstants.hxx @@ -26,6 +26,7 @@ enum class EventHandlerState { LAUNCHER, OPTIONSMENU, CMDMENU, + HIGHSCORESMENU, MESSAGEMENU, DEBUGGER, NONE diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index a503d89b3..62ef5362f 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -42,6 +42,7 @@ #include "Launcher.hxx" #include "Menu.hxx" #include "CommandMenu.hxx" + #include "HighScoresMenu.hxx" #include "MessageMenu.hxx" #include "TimeMachine.hxx" #endif @@ -332,6 +333,18 @@ void FrameBuffer::update(bool force) break; // EventHandlerState::CMDMENU } + case EventHandlerState::HIGHSCORESMENU: + { + force = force || myOSystem.highscoresMenu().needsRedraw(); + if (force) + { + clear(); + myTIASurface->render(); + myOSystem.highscoresMenu().draw(force); + } + break; // EventHandlerState::HIGHSCORESMENU + } + case EventHandlerState::MESSAGEMENU: { force = force || myOSystem.messageMenu().needsRedraw(); diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index d98827b47..4258e72b9 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -33,6 +33,7 @@ #ifdef GUI_SUPPORT #include "Menu.hxx" #include "CommandMenu.hxx" + #include "HighScoresMenu.hxx" #include "MessageMenu.hxx" #include "Launcher.hxx" #include "TimeMachine.hxx" @@ -180,6 +181,7 @@ bool OSystem::create() // Create various subsystems (menu and launcher GUI objects, etc) myMenu = make_unique(*this); myCommandMenu = make_unique(*this); + myHighScoresMenu = make_unique(*this); myMessageMenu = make_unique(*this); myTimeMachine = make_unique(*this); myLauncher = make_unique(*this); diff --git a/src/emucore/OSystem.hxx b/src/emucore/OSystem.hxx index 0377f6539..876824231 100644 --- a/src/emucore/OSystem.hxx +++ b/src/emucore/OSystem.hxx @@ -38,6 +38,7 @@ class AudioSettings; #endif #ifdef GUI_SUPPORT class CommandMenu; + class HighScoresMenu; class Launcher; class Menu; class MessageMenu; @@ -219,6 +220,13 @@ class OSystem */ CommandMenu& commandMenu() const { return *myCommandMenu; } + /** + Get the highscores menu of the system. + + @return The highscores menu object + */ + HighScoresMenu& highscoresMenu() const { return *myHighScoresMenu; } + /** Get the message menu of the system. @@ -506,12 +514,15 @@ class OSystem // Pointer to the CommandMenu object unique_ptr myCommandMenu; - // Pointer to the CommandMenu object - unique_ptr myMessageMenu; + // Pointer to the HighScoresMenu object + unique_ptr myHighScoresMenu; // Pointer to the Launcher object unique_ptr myLauncher; + // Pointer to the MessageMenu object + unique_ptr myMessageMenu; + // Pointer to the TimeMachine object unique_ptr myTimeMachine; #endif diff --git a/src/gui/CommandDialog.hxx b/src/gui/CommandDialog.hxx index bd366fc08..c92441b39 100644 --- a/src/gui/CommandDialog.hxx +++ b/src/gui/CommandDialog.hxx @@ -18,7 +18,6 @@ #ifndef COMMAND_DIALOG_HXX #define COMMAND_DIALOG_HXX -class Properties; class CommandSender; class DialogContainer; class OSystem; diff --git a/src/gui/CommandMenu.cxx b/src/gui/CommandMenu.cxx index 68e9a0fef..a45d99062 100644 --- a/src/gui/CommandMenu.cxx +++ b/src/gui/CommandMenu.cxx @@ -24,10 +24,6 @@ CommandMenu::CommandMenu(OSystem& osystem) : DialogContainer(osystem) { - if (osystem.settings().getBool("minimal_ui")) - myBaseDialog = new MinUICommandDialog(myOSystem, *this); - else - myBaseDialog = new CommandDialog(myOSystem, *this); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -39,5 +35,11 @@ CommandMenu::~CommandMenu() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Dialog* CommandMenu::baseDialog() { + if (myBaseDialog == nullptr) + if (myOSystem.settings().getBool("minimal_ui")) + myBaseDialog = new MinUICommandDialog(myOSystem, *this); + else + myBaseDialog = new CommandDialog(myOSystem, *this); + return myBaseDialog; } diff --git a/src/gui/HighScoresDialog.cxx b/src/gui/HighScoresDialog.cxx new file mode 100644 index 000000000..1645ca14c --- /dev/null +++ b/src/gui/HighScoresDialog.cxx @@ -0,0 +1,138 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "Console.hxx" +#include "EventHandler.hxx" +#include "Font.hxx" +#include "FBSurface.hxx" +//#include "StringParser.hxx" +#include "EditTextWidget.hxx" +#include "PopUpWidget.hxx" + + +#include "HighScoresDialog.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, + const GUI::Font& font, int max_w, int max_h) + : Dialog(osystem, parent, font, "High Scores") +{ + 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; + + int xpos, ypos, lwidth, fwidth, pwidth, tabID; + WidgetArray wid; + VariantList items; + + _w = 400; // max_w - 20; + _h = 400; // max_h - 20; + + ypos = VBORDER + _th; xpos = HBORDER; + + + //items.clear(); + + StaticTextWidget* s = new StaticTextWidget(this, font, xpos, ypos + 1, "Variation "); + myVariation = new PopUpWidget(this, font, s->getRight(), ypos, + font.getStringWidth("256"), lineHeight, items, "", 0, 0); + + ypos += lineHeight + VGAP * 2; + + 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 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, 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; + + for (uInt32 p = 0; p < NUM_POSITIONS; ++p) + { + 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"); + + //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"); + + ypos += lineHeight + VGAP; + } + ypos += VGAP; + myMD5 = new StaticTextWidget(this, ifont, xpos, ypos + 1, "MD5: 9ad36e699ef6f45d9eb6c4cf90475c9f"); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +HighScoresDialog::~HighScoresDialog() +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void HighScoresDialog::loadConfig() +{ + // Enable blending (only once is necessary) + if(!surface().attributes().blending) + { + surface().attributes().blending = true; + surface().attributes().blendalpha = 90; + surface().applyAttributes(); + } + + VariantList items; + + items.clear(); + + for (Int32 i = 1; i <= 10; ++i) + VarList::push_back(items, i, i); + myVariation->addItems(items); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void HighScoresDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) +{ + switch (cmd) + { + case kOKCmd: + case kCloseCmd: + instance().eventHandler().handleEvent(Event::ExitMode); + break; + + default: + Dialog::handleCommand(sender, cmd, data, 0); + } +} diff --git a/src/gui/HighScoresDialog.hxx b/src/gui/HighScoresDialog.hxx new file mode 100644 index 000000000..142f7c6ba --- /dev/null +++ b/src/gui/HighScoresDialog.hxx @@ -0,0 +1,64 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef MESSAGE_DIALOG_HXX +#define MESSAGE_DIALOG_HXX + +//class Properties; +class CommandSender; +class DialogContainer; +class OSystem; +class EditTextWidget; +class PopUpWidget; + +#include "Dialog.hxx" + +/** + The dialog for displaying high scores in Stella. + + @author Thomas Jentzsch +*/ + +class HighScoresDialog : public Dialog +{ + public: + static const uInt32 NUM_POSITIONS = 10; + + HighScoresDialog(OSystem& osystem, DialogContainer& parent, + const GUI::Font& font, int max_w, int max_h); + virtual ~HighScoresDialog(); + + protected: + void loadConfig() override; + void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + + private: + PopUpWidget* myVariation; + StaticTextWidget* myPositions[NUM_POSITIONS]; + StaticTextWidget* myScores[NUM_POSITIONS]; + EditTextWidget* myNames[NUM_POSITIONS]; + StaticTextWidget* myMD5; + + private: + // Following constructors and assignment operators not supported + HighScoresDialog() = delete; + HighScoresDialog(const HighScoresDialog&) = delete; + HighScoresDialog(HighScoresDialog&&) = delete; + HighScoresDialog& operator=(const HighScoresDialog&) = delete; + HighScoresDialog& operator=(HighScoresDialog&&) = delete; +}; +#endif diff --git a/src/gui/HighScoresMenu.cxx b/src/gui/HighScoresMenu.cxx new file mode 100644 index 000000000..3bcb7321d --- /dev/null +++ b/src/gui/HighScoresMenu.cxx @@ -0,0 +1,43 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "Dialog.hxx" +#include "FrameBuffer.hxx" +#include "HighScoresDialog.hxx" +#include "HighScoresMenu.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +HighScoresMenu::HighScoresMenu(OSystem& osystem) + : DialogContainer(osystem) +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +HighScoresMenu::~HighScoresMenu() +{ + delete myHighScoresDialog; myHighScoresDialog = nullptr; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Dialog* HighScoresMenu::baseDialog() +{ + if (myHighScoresDialog == nullptr) + myHighScoresDialog = new HighScoresDialog(myOSystem, *this, myOSystem.frameBuffer().font(), + FBMinimum::Width, FBMinimum::Height); + + return myHighScoresDialog; +} diff --git a/src/gui/HighScoresMenu.hxx b/src/gui/HighScoresMenu.hxx new file mode 100644 index 000000000..68c4cc1c4 --- /dev/null +++ b/src/gui/HighScoresMenu.hxx @@ -0,0 +1,52 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef HIGHSCORES_MENU_HXX +#define HIGHSCORES_MENU_HXX + +class OSystem; +class HighScoresDialog; + +#include "DialogContainer.hxx" + +/** + The base menu for the high scores dialog in Stella. + + @author Thomas Jentzsch +*/ +class HighScoresMenu : public DialogContainer +{ + public: + /** + Create a new menu stack + */ + explicit HighScoresMenu(OSystem& osystem); + virtual ~HighScoresMenu(); + + private: + Dialog* baseDialog() override; + HighScoresDialog* myHighScoresDialog{nullptr}; + + private: + // Following constructors and assignment operators not supported + HighScoresMenu() = delete; + HighScoresMenu(const HighScoresMenu&) = delete; + HighScoresMenu(HighScoresMenu&&) = delete; + HighScoresMenu& operator=(const HighScoresMenu&) = delete; + HighScoresMenu& operator=(HighScoresMenu&&) = delete; +}; +#endif diff --git a/src/gui/MessageDialog.hxx b/src/gui/MessageDialog.hxx index 4ebb6607a..c9c061583 100644 --- a/src/gui/MessageDialog.hxx +++ b/src/gui/MessageDialog.hxx @@ -18,7 +18,6 @@ #ifndef MESSAGE_DIALOG_HXX #define MESSAGE_DIALOG_HXX -class Properties; class CommandSender; class DialogContainer; class OSystem; diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index 146e77234..9b6592655 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -517,6 +517,8 @@ + + @@ -1254,6 +1256,8 @@ + + diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index d9cc94dd4..0efaa3686 100644 --- a/src/windows/Stella.vcxproj.filters +++ b/src/windows/Stella.vcxproj.filters @@ -1008,6 +1008,12 @@ Source Files + + Source Files\gui + + + Source Files\gui + @@ -2060,6 +2066,12 @@ Header Files + + Header Files\gui + + + Source Files\gui +