diff --git a/Changes.txt b/Changes.txt index 845bd1416..0a0fe01cc 100644 --- a/Changes.txt +++ b/Changes.txt @@ -12,29 +12,29 @@ Release History =========================================================================== -5.1.3 to 5.2: (MMM d, 2018) +5.1.3 to 6.0: (MMM d, 2018) * New cycle exact audio core based on work by Chris Brenner (crispy); greatly - improved audio emulation accuracy (i.e. E.T., Ms. Pacman) + improved audio emulation accuracy (i.e. E.T., Ms. Pacman). * Full rewrite of the audio subsystem; resample TIA output to target sample - rate directly in Stella + rate directly in Stella. - * Threading: decouple emulation from frame rendering + * Threading: decouple emulation from frame rendering. * Main loop rewritten; emulating speed and timing is now much more faithful - (i.e. speed in Pick'n'Pile) + (i.e. speed in Pick'n'Pile). - * Audio settings replaced with new audio.xxx settings + * Audio settings replaced with new 'audio.xxx' settings. - * FPS setting replaced with speed setting for adjusting emulation speed + * FPS setting replaced with speed setting for adjusting emulation speed. * Extra functionality for Time Machine dialog (start/stop recording; minor fixes; TODO button and initial key repeats...) - * Fixes for collision corner cases (during HBlank) + * Fixes for collision corner cases (during HBlank). - * UI modernization (new widget look, dialog titles added, dialogs refactored) + * UI modernization (new widget look, dialog titles added, dialogs refactored). * Changes in 'Game Properties' dialog - 'Default' button now affects only current tab like in all other dialogs. @@ -46,8 +46,11 @@ * The Linux builds now use the system-installed PNG and ZLIB libraries by default. + * When starting Stella for the first time, the first ROM selected will + determine which path to use by default for subsequent runs. + * Fixed emulator crash when starting SaveKey ROMs from commandline with - SaveKey messages enabled + SaveKey messages enabled. * Fixed missing TV format update in frame stats dialog when switching display type. @@ -57,7 +60,7 @@ * Updated included PNG library to latest stable version. * For better compatibility, the Windows 32-bit version does not requires SSE2 - anymore + anymore. -Have fun! diff --git a/docs/graphics/cheat.png b/docs/graphics/cheat.png index 9f2187653..63c4bc1be 100644 Binary files a/docs/graphics/cheat.png and b/docs/graphics/cheat.png differ diff --git a/docs/graphics/commandmenu.png b/docs/graphics/commandmenu.png index 448fd61be..fdd894e27 100644 Binary files a/docs/graphics/commandmenu.png and b/docs/graphics/commandmenu.png differ diff --git a/docs/graphics/eventmapping_combo.png b/docs/graphics/eventmapping_combo.png index 96eac8f6d..5f4be9f43 100644 Binary files a/docs/graphics/eventmapping_combo.png and b/docs/graphics/eventmapping_combo.png differ diff --git a/docs/graphics/launcher.png b/docs/graphics/launcher.png index 7ec6e825d..09dd9b107 100644 Binary files a/docs/graphics/launcher.png and b/docs/graphics/launcher.png differ diff --git a/docs/graphics/launcher_filter.png b/docs/graphics/launcher_filter.png index e56e8bee6..6549c986e 100644 Binary files a/docs/graphics/launcher_filter.png and b/docs/graphics/launcher_filter.png differ diff --git a/docs/graphics/launcher_options_files.png b/docs/graphics/launcher_options_files.png index cb39f01d2..fc417a97c 100644 Binary files a/docs/graphics/launcher_options_files.png and b/docs/graphics/launcher_options_files.png differ diff --git a/docs/graphics/launcher_options_snapshots.png b/docs/graphics/launcher_options_snapshots.png index 9441e2479..40de9d003 100644 Binary files a/docs/graphics/launcher_options_snapshots.png and b/docs/graphics/launcher_options_snapshots.png differ diff --git a/docs/graphics/launcher_override.png b/docs/graphics/launcher_override.png index a6c3dcfe0..bd4e7a21d 100644 Binary files a/docs/graphics/launcher_override.png and b/docs/graphics/launcher_override.png differ diff --git a/docs/graphics/options.png b/docs/graphics/options.png index 3d877baa2..f57902fd6 100644 Binary files a/docs/graphics/options.png and b/docs/graphics/options.png differ diff --git a/docs/graphics/romaudit.png b/docs/graphics/romaudit.png index cae6dc145..a4017257e 100644 Binary files a/docs/graphics/romaudit.png and b/docs/graphics/romaudit.png differ diff --git a/docs/index.html b/docs/index.html index 615a894a2..7445bd288 100644 --- a/docs/index.html +++ b/docs/index.html @@ -10,7 +10,7 @@

A multi-platform Atari 2600 VCS emulator

-

Release 5.1.1

+

Release 6.0



User's Guide

@@ -61,7 +61,7 @@


-
February 1999 - February 2018
+
February 1999 - TODO 2018
The Stella Team
Stella Homepage
@@ -2736,8 +2736,8 @@ ItemBrief descriptionFor more information,
see CommandLine Save pathSpecifies where to save snapshots-snapsavedir Load pathSpecifies where to load snapshots-snaploaddir - Save snapshots according toSpecifies how to name saved snapshots-snapname Continuous snapshot intervalInterval (in seconds) between snapshots-ssinterval + Use actual ROM nameUse the actual ROM filename instead of the internal database name.-snapname Overwrite existing filesWhether to overwrite old snapshots-sssingle Ignore scaling (1x mode)Save snapshot in 1x mode without scaling-ss1x diff --git a/src/common/FSNodeFactory.hxx b/src/common/FSNodeFactory.hxx index c3b958c2e..4519c95d5 100644 --- a/src/common/FSNodeFactory.hxx +++ b/src/common/FSNodeFactory.hxx @@ -40,19 +40,19 @@ class FilesystemNodeFactory enum Type { SYSTEM, ZIP }; public: - static AbstractFSNode* create(const string& path, Type type) + static unique_ptr create(const string& path, Type type) { switch(type) { case SYSTEM: #if defined(BSPF_UNIX) || defined(BSPF_MAC_OSX) - return new FilesystemNodePOSIX(path); + return make_unique(path); #elif defined(BSPF_WINDOWS) - return new FilesystemNodeWINDOWS(path); + return make_unique(path); #endif break; case ZIP: - return new FilesystemNodeZIP(path); + return make_unique(path); break; } return nullptr; diff --git a/src/common/FSNodeZIP.cxx b/src/common/FSNodeZIP.cxx index 0528e9469..0af148608 100644 --- a/src/common/FSNodeZIP.cxx +++ b/src/common/FSNodeZIP.cxx @@ -29,8 +29,6 @@ FilesystemNodeZIP::FilesystemNodeZIP() _isDirectory(false), _isFile(false) { - // We need a name, else the node is invalid - _realNode = shared_ptr(nullptr); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -92,9 +90,7 @@ FilesystemNodeZIP::FilesystemNodeZIP(const string& p) else _isDirectory = true; - AbstractFSNode* tmp = - FilesystemNodeFactory::create(_zipFile, FilesystemNodeFactory::SYSTEM); - _realNode = shared_ptr(tmp); + _realNode = FilesystemNodeFactory::create(_zipFile, FilesystemNodeFactory::SYSTEM); setFlags(_zipFile, _virtualPath, _realNode); } @@ -102,7 +98,7 @@ FilesystemNodeZIP::FilesystemNodeZIP(const string& p) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FilesystemNodeZIP::FilesystemNodeZIP( const string& zipfile, const string& virtualpath, - shared_ptr realnode, bool isdir) + AbstractFSNodePtr realnode, bool isdir) : _error(ZIPERR_NONE), _numFiles(0), _isDirectory(isdir), @@ -114,7 +110,7 @@ FilesystemNodeZIP::FilesystemNodeZIP( // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FilesystemNodeZIP::setFlags(const string& zipfile, const string& virtualpath, - shared_ptr realnode) + AbstractFSNodePtr realnode) { _zipFile = zipfile; _virtualPath = virtualpath; @@ -195,7 +191,7 @@ uInt32 FilesystemNodeZIP::read(BytePtr& image) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AbstractFSNode* FilesystemNodeZIP::getParent() const +AbstractFSNodePtr FilesystemNodeZIP::getParent() const { if(_virtualPath == "") return _realNode ? _realNode->getParent() : nullptr; @@ -203,7 +199,7 @@ AbstractFSNode* FilesystemNodeZIP::getParent() const const char* start = _path.c_str(); const char* end = lastPathComponent(_path); - return new FilesystemNodeZIP(string(start, end - start - 1)); + return make_shared(string(start, end - start - 1)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/FSNodeZIP.hxx b/src/common/FSNodeZIP.hxx index 29b51df00..56d83d378 100644 --- a/src/common/FSNodeZIP.hxx +++ b/src/common/FSNodeZIP.hxx @@ -61,16 +61,16 @@ class FilesystemNodeZIP : public AbstractFSNode ////////////////////////////////////////////////////////// bool getChildren(AbstractFSList& list, ListMode mode, bool hidden) const; - AbstractFSNode* getParent() const; + AbstractFSNodePtr getParent() const; uInt32 read(BytePtr& image) const; private: FilesystemNodeZIP(const string& zipfile, const string& virtualpath, - shared_ptr realnode, bool isdir); + AbstractFSNodePtr realnode, bool isdir); void setFlags(const string& zipfile, const string& virtualpath, - shared_ptr realnode); + AbstractFSNodePtr realnode); friend ostream& operator<<(ostream& os, const FilesystemNodeZIP& node) { @@ -91,7 +91,7 @@ class FilesystemNodeZIP : public AbstractFSNode ZIPERR_NO_ROMS }; - shared_ptr _realNode; + AbstractFSNodePtr _realNode; string _zipFile, _virtualPath; string _name, _path, _shortPath; zip_error _error; diff --git a/src/common/Version.hxx b/src/common/Version.hxx index ef52325c7..bc1d304a5 100644 --- a/src/common/Version.hxx +++ b/src/common/Version.hxx @@ -18,7 +18,7 @@ #ifndef VERSION_HXX #define VERSION_HXX -#define STELLA_VERSION "5.2_soundtest-1" -#define STELLA_BUILD "4138" +#define STELLA_VERSION "6.0_pre1" +#define STELLA_BUILD "4409" #endif diff --git a/src/emucore/FSNode.cxx b/src/emucore/FSNode.cxx index c118ece2e..514131c4a 100644 --- a/src/emucore/FSNode.cxx +++ b/src/emucore/FSNode.cxx @@ -30,7 +30,7 @@ FilesystemNode::FilesystemNode() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FilesystemNode::FilesystemNode(AbstractFSNode *realNode) +FilesystemNode::FilesystemNode(AbstractFSNodePtr realNode) : _realNode(realNode) { } @@ -38,15 +38,11 @@ FilesystemNode::FilesystemNode(AbstractFSNode *realNode) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FilesystemNode::FilesystemNode(const string& p) { - AbstractFSNode* tmp = nullptr; - // Is this potentially a ZIP archive? if(BSPF::containsIgnoreCase(p, ".zip")) - tmp = FilesystemNodeFactory::create(p, FilesystemNodeFactory::ZIP); + _realNode = FilesystemNodeFactory::create(p, FilesystemNodeFactory::ZIP); else - tmp = FilesystemNodeFactory::create(p, FilesystemNodeFactory::SYSTEM); - - _realNode = shared_ptr(tmp); + _realNode = FilesystemNodeFactory::create(p, FilesystemNodeFactory::SYSTEM); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -132,7 +128,7 @@ FilesystemNode FilesystemNode::getParent() const if (_realNode == nullptr) return *this; - AbstractFSNode* node = _realNode->getParent(); + AbstractFSNodePtr node = _realNode->getParent(); return node ? FilesystemNode(node) : *this; } diff --git a/src/emucore/FSNode.hxx b/src/emucore/FSNode.hxx index 4291466ce..160274a5b 100644 --- a/src/emucore/FSNode.hxx +++ b/src/emucore/FSNode.hxx @@ -49,6 +49,7 @@ class FilesystemNode; class AbstractFSNode; +using AbstractFSNodePtr = shared_ptr; /** * List of multiple file system nodes. E.g. the contents of a given directory. @@ -144,7 +145,7 @@ class FilesystemNode * @return true if successful, false otherwise (e.g. when the directory * does not exist). */ - virtual bool getChildren(FSList &fslist, ListMode mode = kListDirectoriesOnly, + virtual bool getChildren(FSList& fslist, ListMode mode = kListDirectoriesOnly, bool hidden = false) const; /** @@ -261,8 +262,8 @@ class FilesystemNode string getShortPathWithExt(const string& ext) const; // FIXME - dead code private: - shared_ptr _realNode; - FilesystemNode(AbstractFSNode* realNode); + AbstractFSNodePtr _realNode; + FilesystemNode(AbstractFSNodePtr realNode); }; @@ -275,7 +276,7 @@ class FilesystemNode * the semantics. */ -using AbstractFSList = vector; +using AbstractFSList = vector; class AbstractFSNode { @@ -403,7 +404,7 @@ class AbstractFSNode * The parent node of this directory. * The parent of the root is the root itself. */ - virtual AbstractFSNode* getParent() const = 0; + virtual AbstractFSNodePtr getParent() const = 0; }; #endif diff --git a/src/gui/ComboDialog.cxx b/src/gui/ComboDialog.cxx index 9a3df6087..c9879335e 100644 --- a/src/gui/ComboDialog.cxx +++ b/src/gui/ComboDialog.cxx @@ -29,7 +29,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font, const VariantList& combolist) - : Dialog(boss->instance(), boss->parent(), font, ""), + : Dialog(boss->instance(), boss->parent(), font, "Add..."), myComboEvent(Event::NoType) { const int lineHeight = font.getLineHeight(), @@ -38,7 +38,7 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font, WidgetArray wid; // Set real dimensions - _w = 35 * fontWidth + 10; + _w = 33 * fontWidth + 10*2; _h = 10 * (lineHeight + 4) + 10 + _th; xpos = 10; ypos = 10 + _th; @@ -57,7 +57,6 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font, ypos += lineHeight + 4; }; - xpos = 10; myEvents[0] = nullptr; ADD_EVENT_POPUP(0, "Event 1 "); myEvents[1] = nullptr; ADD_EVENT_POPUP(1, "Event 2 "); myEvents[2] = nullptr; ADD_EVENT_POPUP(2, "Event 3 "); diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index 3d9a76b0a..4f3ffd074 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -56,6 +56,7 @@ Dialog::Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font _okWidget(nullptr), _cancelWidget(nullptr), _visible(false), + _onTop(true), _processCancel(false), _title(title), _th(0), @@ -331,25 +332,25 @@ void Dialog::drawDialog() cerr << COUNT++ << " Dialog::drawDialog()\n"; // Dialog is still on top if e.g a ContextMenu is opened - bool onTop = parent().myDialogStack.top() == this + _onTop = parent().myDialogStack.top() == this || (parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this && !parent().myDialogStack.top()->hasTitle()); if(_flags & WIDGET_CLEARBG) { // cerr << "Dialog::drawDialog(): w = " << _w << ", h = " << _h << " @ " << &s << endl << endl; - s.fillRect(_x, _y + _th, _w, _h - _th, onTop ? kDlgColor : kBGColorLo); + s.fillRect(_x, _y + _th, _w, _h - _th, _onTop ? kDlgColor : kBGColorLo); if(_th) { - s.fillRect(_x, _y, _w, _th, onTop ? kColorTitleBar : kColorTitleBarLo); + s.fillRect(_x, _y, _w, _th, _onTop ? kColorTitleBar : kColorTitleBarLo); s.drawString(_font, _title, _x + 10, _y + 2 + 1, _font.getStringWidth(_title), - onTop ? kColorTitleText : kColorTitleTextLo); + _onTop ? kColorTitleText : kColorTitleTextLo); } } else s.invalidate(); - if(_flags & WIDGET_BORDER) - s.frameRect(_x, _y, _w, _h, onTop ? kColor : kShadowColor); + if(_flags & WIDGET_BORDER) // currently only used by Dialog itself + s.frameRect(_x, _y, _w, _h, _onTop ? kColor : kShadowColor); // Make all child widget dirty Widget* w = _firstWidget; diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 71df684a3..444848ac1 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -55,6 +55,7 @@ class Dialog : public GuiObject void close(); bool isVisible() const override { return _visible; } + bool isOnTop() { return _onTop; } virtual void center(); virtual void drawDialog(); @@ -152,6 +153,7 @@ class Dialog : public GuiObject Widget* _cancelWidget; bool _visible; + bool _onTop; bool _processCancel; string _title; int _th; diff --git a/src/gui/EditTextWidget.cxx b/src/gui/EditTextWidget.cxx index 7223bc834..d0dcf8fa8 100644 --- a/src/gui/EditTextWidget.cxx +++ b/src/gui/EditTextWidget.cxx @@ -28,7 +28,7 @@ EditTextWidget::EditTextWidget(GuiObject* boss, const GUI::Font& font, _changed(false) { _flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS; - + startEditMode(); // We're always in edit mode } @@ -85,7 +85,10 @@ void EditTextWidget::drawWidget(bool hilite) if(_changed) s.fillRect(_x, _y, _w, _h, kDbgChangedColor); else if(!isEditable()) - s.fillRect(_x, _y, _w, _h, kDlgColor); + { + bool onTop = _boss->dialog().isOnTop(); + s.fillRect(_x, _y, _w, _h, onTop ? kDlgColor : kBGColorLo); + } // Draw a thin frame around us. s.frameRect(_x, _y, _w, _h, hilite && isEditable() && isEnabled() ? kWidColorHi : kColor); diff --git a/src/gui/EditableWidget.cxx b/src/gui/EditableWidget.cxx index 24790dfef..47bf5a447 100644 --- a/src/gui/EditableWidget.cxx +++ b/src/gui/EditableWidget.cxx @@ -39,6 +39,7 @@ EditableWidget::EditableWidget(GuiObject* boss, const GUI::Font& font, _bgcolor = kWidColor; _bgcolorhi = kWidColor; + _bgcolorlo = kDlgColor; _textcolor = kTextColor; _textcolorhi = kTextColor; diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index c163e2a6f..fc964af32 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -57,17 +57,19 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, const string ELLIPSIS = "\x1d"; const GUI::Font& font = instance().frameBuffer().launcherFont(); + const int HBORDER = 10; + const int BUTTON_GAP = 8; const int fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), lineHeight = font.getLineHeight(), - bwidth = (_w - 2 * 10 - 8 * (4 - 1)) / 4, + bwidth = (_w - 2 * HBORDER - BUTTON_GAP * (4 - 1)), bheight = lineHeight + 4; - int xpos = 0, ypos = 0, lwidth = 0, lwidth2 = 0; + int xpos, ypos = 0, lwidth = 0, lwidth2 = 0; WidgetArray wid; // Show game name lwidth = font.getStringWidth("Select a ROM from the list" + ELLIPSIS); - xpos += 10; ypos += 8; + xpos = HBORDER; ypos += 8; new StaticTextWidget(this, font, xpos, ypos, lwidth, fontHeight, "Select a ROM from the list" + ELLIPSIS); @@ -131,35 +133,35 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, // Add four buttons at the bottom xpos = 10; ypos += myDir->getHeight() + 8; #ifndef BSPF_MAC_OSX - myStartButton = new ButtonWidget(this, font, xpos, ypos, bwidth, bheight, + myStartButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 0) / 4, bheight, "Select", kLoadROMCmd); wid.push_back(myStartButton); - xpos += bwidth + 8; - myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, bwidth, bheight, - "Go Up", kPrevDirCmd); + xpos += (bwidth + 0) / 4 + BUTTON_GAP; + myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 1) / 4, bheight, + "Go Up", kPrevDirCmd); wid.push_back(myPrevDirButton); - xpos += bwidth + 8; - myOptionsButton = new ButtonWidget(this, font, xpos, ypos, bwidth, bheight, + xpos += (bwidth + 1) / 4 + BUTTON_GAP; + myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 2) / 4, bheight, "Options" + ELLIPSIS, kOptionsCmd); wid.push_back(myOptionsButton); - xpos += bwidth + 8; - myQuitButton = new ButtonWidget(this, font, xpos, ypos, bwidth, bheight, + xpos += (bwidth + 2) / 4 + BUTTON_GAP; + myQuitButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 3) / 4, bheight, "Quit", kQuitCmd); wid.push_back(myQuitButton); #else - myQuitButton = new ButtonWidget(this, font, xpos, ypos, bwidth, bheight, + myQuitButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 0) / 4, bheight, "Quit", kQuitCmd); wid.push_back(myQuitButton); - xpos += bwidth + 8; - myOptionsButton = new ButtonWidget(this, font, xpos, ypos, bwidth, bheight, + xpos += (bwidth + 0) / 4 + BUTTON_GAP; + myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 1) / 4, bheight, "Options" + ELLIPSIS, kOptionsCmd); wid.push_back(myOptionsButton); - xpos += bwidth + 8; - myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, bwidth, bheight, + xpos += (bwidth + 1) / 4 + BUTTON_GAP; + myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 2) / 4, bheight, "Go Up", kPrevDirCmd); wid.push_back(myPrevDirButton); - xpos += bwidth + 8; - myStartButton = new ButtonWidget(this, font, xpos, ypos, bwidth, bheight, + xpos += (bwidth + 2) / 4 + BUTTON_GAP; + myStartButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 3) / 4, bheight, "Select", kLoadROMCmd); wid.push_back(myStartButton); #endif @@ -214,31 +216,12 @@ const string& LauncherDialog::selectedRomMD5() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LauncherDialog::loadConfig() { + // Should we use a temporary directory specified on the commandline, or the + // default one specified by the settings? const string& tmpromdir = instance().settings().getString("tmpromdir"); const string& romdir = tmpromdir != "" ? tmpromdir : instance().settings().getString("romdir"); - // When romdir hasn't been set, it probably indicates that this is the first - // time running Stella; in this case, we should prompt the user - if(romdir == "") - { - if(!myFirstRunMsg) - { - StringList msg; - msg.push_back("This seems to be your first time running Stella."); - msg.push_back("Before you can start a game, you need to"); - msg.push_back("specify where your ROMs are located."); - msg.push_back(""); - msg.push_back("Click 'Default' to select a default ROM directory,"); - msg.push_back("or 'Browse' to browse the filesystem manually."); - myFirstRunMsg = make_unique - (this, instance().frameBuffer().font(), - msg, _w, _h, kFirstRunMsgChosenCmd, - "Default", "Browse", "ROM directory"); - } - myFirstRunMsg->show(); - } - // Assume that if the list is empty, this is the first time that loadConfig() // has been called (and we should reload the list) if(myList->getList().empty()) @@ -486,7 +469,13 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd, const string& result = instance().createConsole(romnode, myGameList->md5(item)); if(result == EmptyString) + { instance().settings().setValue("lastrom", myList->getSelectedString()); + + // If romdir has never been set, set it now based on the selected rom + if(instance().settings().getString("romdir") == EmptyString) + instance().settings().setValue("romdir", romnode.getParent().getShortPath()); + } else instance().frameBuffer().showMessage(result, MessagePosition::MiddleCenter, true); } @@ -513,20 +502,6 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd, instance().eventHandler().quit(); break; - case kFirstRunMsgChosenCmd: - // Show a file browser, starting from the users' home directory - if(!myRomDir) - myRomDir = make_unique(this, instance().frameBuffer().font(), - _w, _h, "Select ROM directory"); - myRomDir->show("~", BrowserDialog::Directories, kStartupRomDirChosenCmd); - break; - - case kStartupRomDirChosenCmd: - { - FilesystemNode dir(myRomDir->getResult()); - instance().settings().setValue("romdir", dir.getShortPath()); - [[fallthrough]]; - } case kRomDirChosenCmd: myCurrentNode = FilesystemNode(instance().settings().getString("romdir")); if(!(myCurrentNode.exists() && myCurrentNode.isDirectory())) diff --git a/src/gui/LauncherDialog.hxx b/src/gui/LauncherDialog.hxx index 61400f461..0b60e0c2f 100644 --- a/src/gui/LauncherDialog.hxx +++ b/src/gui/LauncherDialog.hxx @@ -48,7 +48,7 @@ class LauncherDialog : public Dialog // These must be accessible from dialogs created by this class enum { kLoadROMCmd = 'STRT', // load currently selected ROM - kRomDirChosenCmd = 'romc', // rom chosen + kRomDirChosenCmd = 'romc', // rom dir chosen kReloadRomDirCmd = 'rdrl', // reload the current listing kReloadFiltersCmd = 'rlfl' // reload filtering options and current listing }; @@ -98,7 +98,6 @@ class LauncherDialog : public Dialog unique_ptr myGlobalProps; unique_ptr myFilters; unique_ptr myRomDir; - unique_ptr myFirstRunMsg; ButtonWidget* myStartButton; ButtonWidget* myPrevDirButton; @@ -122,10 +121,7 @@ class LauncherDialog : public Dialog enum { kPrevDirCmd = 'PRVD', kOptionsCmd = 'OPTI', - kQuitCmd = 'QUIT', - - kFirstRunMsgChosenCmd = 'frmc', - kStartupRomDirChosenCmd = 'rmsc' + kQuitCmd = 'QUIT' }; private: diff --git a/src/gui/RomInfoWidget.cxx b/src/gui/RomInfoWidget.cxx index bdd6278ef..744f0e215 100644 --- a/src/gui/RomInfoWidget.cxx +++ b/src/gui/RomInfoWidget.cxx @@ -39,7 +39,8 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font, GUI::Size(320, TIAConstants::maxViewableHeight)) { _flags = WIDGET_ENABLED; - _bgcolor = _bgcolorhi = kWidColor; + _bgcolor = kDlgColor; + _bgcolorlo = kBGColorLo; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -139,10 +140,11 @@ void RomInfoWidget::parseProperties() void RomInfoWidget::drawWidget(bool hilite) { FBSurface& s = dialog().surface(); + bool onTop = _boss->dialog().isOnTop(); const int yoff = myAvail.h + 10; - s.fillRect(_x+2, _y+2, _w-4, _h-4, kDlgColor); + s.fillRect(_x+2, _y+2, _w-4, _h-4, onTop ? _bgcolor : _bgcolorlo); s.frameRect(_x, _y, _w, _h, kColor); s.frameRect(_x, _y+yoff, _w, _h-yoff, kColor); diff --git a/src/gui/StringListWidget.cxx b/src/gui/StringListWidget.cxx index cd5a6fe9b..6ddd46dbe 100644 --- a/src/gui/StringListWidget.cxx +++ b/src/gui/StringListWidget.cxx @@ -29,6 +29,7 @@ StringListWidget::StringListWidget(GuiObject* boss, const GUI::Font& font, boss->instance().settings().getInt("listdelay") >= 300), _hilite(hilite) { + _bgcolorlo = kDlgColor; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -77,7 +78,10 @@ void StringListWidget::drawWidget(bool hilite) textColor = kTextColorInv; } else - s.frameRect(_x + 1, _y + 1 + _fontHeight * i, _w - 1, _fontHeight, kWidColorHi); + { + bool onTop = _boss->dialog().isOnTop(); + s.frameRect(_x + 1, _y + 1 + _fontHeight * i, _w - 1, _fontHeight, onTop ? kWidColorHi : kBGColorLo); + } } GUI::Rect r(getEditRect()); diff --git a/src/gui/TabWidget.cxx b/src/gui/TabWidget.cxx index 55dd450de..64fe23df7 100644 --- a/src/gui/TabWidget.cxx +++ b/src/gui/TabWidget.cxx @@ -262,6 +262,7 @@ void TabWidget::drawWidget(bool hilite) Widget::setDirtyInChain(_tabs[_activeTab].firstWidget); FBSurface& s = dialog().surface(); + bool onTop = _boss->dialog().isOnTop(); // Iterate over all tabs and draw them int i, x = _x + kTabLeftOffset; @@ -269,25 +270,27 @@ void TabWidget::drawWidget(bool hilite) { uInt32 fontcolor = _tabs[i].enabled ? kTextColor : kColor; int yOffset = (i == _activeTab) ? 0 : 1; - s.fillRect(x, _y + 1, _tabWidth, _tabHeight - 1, (i == _activeTab) - ? kDlgColor : kBGColorHi); // ? kWidColor : kDlgColor + s.fillRect(x, _y + 1, _tabWidth, _tabHeight - 1, + (i == _activeTab) + ? onTop ? kDlgColor : kBGColorLo + : onTop ? kBGColorHi : kDlgColor); // ? kWidColor : kDlgColor s.drawString(_font, _tabs[i].title, x + kTabPadding + yOffset, _y + yOffset + (_tabHeight - _fontHeight - 1), _tabWidth - 2 * kTabPadding, fontcolor, TextAlign::Center); if(i == _activeTab) { - s.hLine(x, _y, x + _tabWidth - 1, kWidColor); - s.vLine(x + _tabWidth, _y + 1, _y + _tabHeight - 1, kBGColorLo); + s.hLine(x, _y, x + _tabWidth - 1, onTop ? kWidColor : kDlgColor); + s.vLine(x + _tabWidth, _y + 1, _y + _tabHeight - 1, onTop ? kBGColorLo : kColor); } else - s.hLine(x, _y + _tabHeight, x + _tabWidth, kWidColor); + s.hLine(x, _y + _tabHeight, x + _tabWidth, onTop ? kWidColor : kDlgColor); x += _tabWidth + kTabSpacing; } // fill empty right space - s.hLine(x - kTabSpacing + 1, _y + _tabHeight, _x + _w - 1, kWidColor); - s.hLine(_x, _y + _h - 1, _x + _w - 1, kBGColorLo); + s.hLine(x - kTabSpacing + 1, _y + _tabHeight, _x + _w - 1, onTop ? kWidColor : kDlgColor); + s.hLine(_x, _y + _h - 1, _x + _w - 1, onTop ? kBGColorLo : kColor); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index fad6d82f4..4c20e8745 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -38,8 +38,10 @@ Widget::Widget(GuiObject* boss, const GUI::Font& font, _hasFocus(false), _bgcolor(kWidColor), _bgcolorhi(kWidColor), + _bgcolorlo(kBGColorLo), _textcolor(kTextColor), _textcolorhi(kTextColorHi), + _textcolorlo(kBGColorLo), _shadowcolor(kShadowColor) { // Insert into the widget list of the boss @@ -77,7 +79,9 @@ void Widget::draw() FBSurface& s = _boss->dialog().surface(); - bool hasBorder = _flags & WIDGET_BORDER; + bool onTop = _boss->dialog().isOnTop(); + + bool hasBorder = _flags & WIDGET_BORDER; // currently only used by Dialog widget int oldX = _x, oldY = _y; // Account for our relative position in the dialog @@ -92,13 +96,13 @@ void Widget::draw() { x++; y++; w-=2; h-=2; } - s.fillRect(x, y, w, h, (_flags & WIDGET_HILITED) && isEnabled() ? _bgcolorhi : _bgcolor); + s.fillRect(x, y, w, h, !onTop ? _bgcolorlo : (_flags & WIDGET_HILITED) && isEnabled() ? _bgcolorhi : _bgcolor); } // Draw border if(hasBorder) { - s.frameRect(_x, _y, _w, _h, (_flags & WIDGET_HILITED) && isEnabled() ? kWidColorHi : kColor); + s.frameRect(_x, _y, _w, _h, !onTop ? kColor : (_flags & WIDGET_HILITED) && isEnabled() ? kWidColorHi : kColor); _x += 4; _y += 4; _w -= 8; @@ -203,6 +207,8 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr, FBSurface& s = boss->dialog().surface(); int size = int(arr.size()), pos = -1; Widget* tmp; + bool onTop = boss->dialog().isOnTop(); + for(int i = 0; i < size; ++i) { tmp = arr[i]; @@ -226,7 +232,7 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr, else tmp->_hasFocus = false; - s.frameRect(x, y, w, h, kDlgColor); + s.frameRect(x, y, w, h, onTop ? kDlgColor : kBGColorLo); tmp->setDirty(); } @@ -279,7 +285,8 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr, else tmp->_hasFocus = true; - s.frameRect(x, y, w, h, kWidFrameColor, FrameStyle::Dashed); + if (onTop) + s.frameRect(x, y, w, h, kWidFrameColor, FrameStyle::Dashed); tmp->setDirty(); @@ -368,8 +375,10 @@ ButtonWidget::ButtonWidget(GuiObject* boss, const GUI::Font& font, _flags = WIDGET_ENABLED | WIDGET_CLEARBG; _bgcolor = kBtnColor; _bgcolorhi = kBtnColorHi; + _bgcolorlo = kColor; _textcolor = kBtnTextColor; _textcolorhi = kBtnTextColorHi; + _textcolorlo = kBGColorLo; _editable = false; } @@ -457,16 +466,17 @@ void ButtonWidget::setBitmap(uInt32* bitmap, int bmw, int bmh) void ButtonWidget::drawWidget(bool hilite) { FBSurface& s = _boss->dialog().surface(); + bool onTop = _boss->dialog().isOnTop(); - s.frameRect(_x, _y, _w, _h, hilite && isEnabled() ? kBtnBorderColorHi : kBtnBorderColor); + s.frameRect(_x, _y, _w, _h, !onTop ? kShadowColor : hilite && isEnabled() ? kBtnBorderColorHi : kBtnBorderColor); if (!_useBitmap) s.drawString(_font, _label, _x, _y + (_h - _fontHeight)/2 + 1, _w, - !isEnabled() ? /*hilite ? uInt32(kColor) :*/ uInt32(kBGColorLo) : + !(isEnabled() && onTop) ? _textcolorlo : hilite ? _textcolorhi : _textcolor, _align); else s.drawBitmap(_bitmap, _x + (_w - _bmw) / 2, _y + (_h - _bmh) / 2, - !isEnabled() ? /*hilite ? uInt32(kColor) :*/ uInt32(kBGColorLo) : + !(isEnabled() && onTop) ? _textcolorlo : hilite ? _textcolorhi : _textcolor, _bmw, _bmh); diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index a550073cd..62cb82404 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -142,8 +142,10 @@ class Widget : public GuiObject int _fontHeight; uInt32 _bgcolor; uInt32 _bgcolorhi; + uInt32 _bgcolorlo; uInt32 _textcolor; uInt32 _textcolorhi; + uInt32 _textcolorlo; uInt32 _shadowcolor; public: diff --git a/src/unix/FSNodePOSIX.cxx b/src/unix/FSNodePOSIX.cxx index c9ae65112..8cdff324f 100644 --- a/src/unix/FSNodePOSIX.cxx +++ b/src/unix/FSNodePOSIX.cxx @@ -97,12 +97,11 @@ bool FilesystemNodePOSIX::getChildren(AbstractFSList& myList, ListMode mode, assert(_isDirectory); DIR* dirp = opendir(_path.c_str()); - struct dirent* dp; - if (dirp == nullptr) return false; - // loop over dir entries using readdir + // Loop over dir entries using readdir + struct dirent* dp; while ((dp = readdir(dirp)) != nullptr) { // Skip 'invisible' files if necessary @@ -137,7 +136,6 @@ bool FilesystemNodePOSIX::getChildren(AbstractFSList& myList, ListMode mode, } else { - entry._isValid = (dp->d_type == DT_DIR) || (dp->d_type == DT_REG) || (dp->d_type == DT_LNK); if (dp->d_type == DT_LNK) { struct stat st; @@ -157,6 +155,8 @@ bool FilesystemNodePOSIX::getChildren(AbstractFSList& myList, ListMode mode, if (entry._isDirectory) entry._path += "/"; + + entry._isValid = entry._isDirectory || entry._isFile; } #endif @@ -226,7 +226,7 @@ bool FilesystemNodePOSIX::rename(const string& newfile) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AbstractFSNode* FilesystemNodePOSIX::getParent() const +AbstractFSNodePtr FilesystemNodePOSIX::getParent() const { if (_path == "/") return nullptr; @@ -234,5 +234,5 @@ AbstractFSNode* FilesystemNodePOSIX::getParent() const const char* start = _path.c_str(); const char* end = lastPathComponent(_path); - return new FilesystemNodePOSIX(string(start, size_t(end - start))); + return make_unique(string(start, size_t(end - start))); } diff --git a/src/unix/FSNodePOSIX.hxx b/src/unix/FSNodePOSIX.hxx index f05720d65..d6fb7346b 100644 --- a/src/unix/FSNodePOSIX.hxx +++ b/src/unix/FSNodePOSIX.hxx @@ -72,7 +72,7 @@ class FilesystemNodePOSIX : public AbstractFSNode bool rename(const string& newfile) override; bool getChildren(AbstractFSList& list, ListMode mode, bool hidden) const override; - AbstractFSNode* getParent() const override; + AbstractFSNodePtr getParent() const override; protected: string _path; diff --git a/src/windows/FSNodeWINDOWS.cxx b/src/windows/FSNodeWINDOWS.cxx index acd948b1f..0671d1e05 100644 --- a/src/windows/FSNodeWINDOWS.cxx +++ b/src/windows/FSNodeWINDOWS.cxx @@ -296,7 +296,7 @@ bool FilesystemNodeWINDOWS::rename(const string& newfile) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AbstractFSNode* FilesystemNodeWINDOWS::getParent() const +AbstractFSNodePtr FilesystemNodeWINDOWS::getParent() const { if(_isPseudoRoot) return nullptr; @@ -306,8 +306,8 @@ AbstractFSNode* FilesystemNodeWINDOWS::getParent() const const char* start = _path.c_str(); const char* end = lastPathComponent(_path); - return new FilesystemNodeWINDOWS(string(start, size_t(end - start))); + return make_shared(string(start, size_t(end - start))); } else - return new FilesystemNodeWINDOWS(); + return make_shared(); } diff --git a/src/windows/FSNodeWINDOWS.hxx b/src/windows/FSNodeWINDOWS.hxx index f8b601365..3a700c6b8 100644 --- a/src/windows/FSNodeWINDOWS.hxx +++ b/src/windows/FSNodeWINDOWS.hxx @@ -69,7 +69,7 @@ class FilesystemNodeWINDOWS : public AbstractFSNode bool rename(const string& newfile) override; bool getChildren(AbstractFSList& list, ListMode mode, bool hidden) const override; - AbstractFSNode* getParent() const override; + AbstractFSNodePtr getParent() const override; protected: string _displayName;