diff --git a/Makefile b/Makefile index 24754e222..ba9abf7e3 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,11 @@ endif # Misc stuff - you should never have to edit this # ####################################################################### -OBJECT_ROOT := out +ifdef STELLA_BUILD_ROOT + OBJECT_ROOT := $(STELLA_BUILD_ROOT)/stella-out +else + OBJECT_ROOT := out +endif OBJECT_ROOT_PROFILE_GENERERATE := out.pgen OBJECT_ROOT_PROFILE_USE := out.pgo diff --git a/src/common/FSNodeZIP.cxx b/src/common/FSNodeZIP.cxx index 452e326a0..f88714841 100644 --- a/src/common/FSNodeZIP.cxx +++ b/src/common/FSNodeZIP.cxx @@ -95,6 +95,11 @@ FilesystemNodeZIP::FilesystemNodeZIP(const string& p) else _isDirectory = true; + // Create a concrete FSNode to use + // This *must not* be a ZIP file; it must be a real FSNode object that + // has direct access to the actual filesystem (aka, a 'System' node) + // Behind the scenes, this node is actually a platform-specific object + // for whatever system we are running on _realNode = FilesystemNodeFactory::create(_zipFile, FilesystemNodeFactory::Type::SYSTEM); setFlags(_zipFile, _virtualPath, _realNode); diff --git a/src/common/FSNodeZIP.hxx b/src/common/FSNodeZIP.hxx index 4e10d1d04..c76cca1c1 100644 --- a/src/common/FSNodeZIP.hxx +++ b/src/common/FSNodeZIP.hxx @@ -93,7 +93,10 @@ class FilesystemNodeZIP : public AbstractFSNode NO_ROMS }; + // Since a ZIP file is itself an abstraction, it still needs access to + // an actual concrete filesystem node AbstractFSNodePtr _realNode; + string _zipFile, _virtualPath; string _name, _path, _shortPath; zip_error _error; diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx index 36f97132e..78b21373f 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -163,11 +163,11 @@ void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mod // use the '1' define for testing #if defined(RETRON77) // #if 1 - setDefaultKey( KBDK_F4, Event::ConsoleColorToggle ); - setDefaultKey( KBDK_F6, Event::ConsoleLeftDiffToggle ); - setDefaultKey( KBDK_F8, Event::ConsoleRightDiffToggle ); - setDefaultKey( KBDK_F13, Event::VidmodeIncrease ); - setDefaultKey( KBDK_BACKSPACE, Event::LauncherMode ); + setDefaultKey( KBDK_F4, Event::ConsoleColorToggle ); // back ("COLOR","B/W") + setDefaultKey( KBDK_F6, Event::ConsoleLeftDiffToggle ); // front ("SKILL P1") + setDefaultKey( KBDK_F8, Event::ConsoleRightDiffToggle ); // front ("SKILL P2") + setDefaultKey( KBDK_F13, Event::CmdMenuMode ); // back ("4:3","16:9") + setDefaultKey( KBDK_BACKSPACE, Event::LauncherMode ); // back ("FRY") #endif break; @@ -189,13 +189,14 @@ void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mod // use the '1' define for testing #if defined(RETRON77) // #if 1 - setDefaultKey( KBDK_F9, Event::UIUp ); - setDefaultKey( KBDK_F2, Event::UIDown ); - setDefaultKey( KBDK_F11, Event::UINavPrev ); - setDefaultKey( KBDK_F1, Event::UINavNext ); - setDefaultKey( KBDK_F6, Event::UISelect ); - setDefaultKey( KBDK_F13, Event::UIPgUp ); - setDefaultKey( KBDK_BACKSPACE, Event::UIPgDown ); + setDefaultKey( KBDK_F9, Event::UIUp ); // front ("SAVE") + setDefaultKey( KBDK_F2, Event::UIDown ); // front ("RESET") + setDefaultKey( KBDK_F11, Event::UINavPrev ); // front ("LOAD") + setDefaultKey( KBDK_F1, Event::UINavNext ); // front ("MODE") + setDefaultKey( KBDK_F6, Event::UISelect ); // front ("SKILL P1") + setDefaultKey( KBDK_F8, Event::UICancel ); // front ("SKILL P2") + setDefaultKey( KBDK_F13, Event::UIPgUp ); // back ("4:3","16:9")(redundant) + setDefaultKey( KBDK_BACKSPACE, Event::UIPgDown ); // back (FRY)(redundant) #endif break; diff --git a/src/debugger/gui/DataGridOpsWidget.cxx b/src/debugger/gui/DataGridOpsWidget.cxx index 21da254a4..e9fd01889 100644 --- a/src/debugger/gui/DataGridOpsWidget.cxx +++ b/src/debugger/gui/DataGridOpsWidget.cxx @@ -72,13 +72,13 @@ DataGridOpsWidget::DataGridOpsWidget(GuiObject* boss, const GUI::Font& font, // We don't enable the buttons until the DataGridWidget is attached // Don't call setEnabled(false), since that does an immediate redraw - _zeroButton->clearFlags(WIDGET_ENABLED); - _invButton->clearFlags(WIDGET_ENABLED); - _negButton->clearFlags(WIDGET_ENABLED); - _incButton->clearFlags(WIDGET_ENABLED); - _decButton->clearFlags(WIDGET_ENABLED); - _shiftLeftButton->clearFlags(WIDGET_ENABLED); - _shiftRightButton->clearFlags(WIDGET_ENABLED); + _zeroButton->clearFlags(Widget::FLAG_ENABLED); + _invButton->clearFlags(Widget::FLAG_ENABLED); + _negButton->clearFlags(Widget::FLAG_ENABLED); + _incButton->clearFlags(Widget::FLAG_ENABLED); + _decButton->clearFlags(Widget::FLAG_ENABLED); + _shiftLeftButton->clearFlags(Widget::FLAG_ENABLED); + _shiftRightButton->clearFlags(Widget::FLAG_ENABLED); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/gui/DataGridWidget.cxx b/src/debugger/gui/DataGridWidget.cxx index da5e68d9d..fbb763baa 100644 --- a/src/debugger/gui/DataGridWidget.cxx +++ b/src/debugger/gui/DataGridWidget.cxx @@ -50,7 +50,7 @@ DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font, _opsWidget(nullptr), _scrollBar(nullptr) { - _flags = WIDGET_ENABLED | WIDGET_RETAIN_FOCUS | WIDGET_WANTS_RAWDATA; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_RETAIN_FOCUS | Widget::FLAG_WANTS_RAWDATA; _editMode = false; // The item is selected, thus _bgcolor is used to draw the caret and @@ -252,14 +252,14 @@ void DataGridWidget::setRange(int lower, int upper) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DataGridWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); setDirty(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DataGridWidget::handleMouseLeft() { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); setDirty(); } diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index bd6aadc51..d3ab25ae1 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -67,7 +67,7 @@ DebuggerDialog::DebuggerDialog(OSystem& osystem, DialogContainer& parent, myTiaOutput->setZoomWidget(myTiaZoom); myOptions = make_unique(osystem, parent, this, w, h, - OptionsDialog::AppMode::debugger); + Menu::AppMode::debugger); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -504,7 +504,7 @@ void DebuggerDialog::addStatusArea() xpos, ypos, myTiaZoom->getWidth(), myLFont->getLineHeight(), ""); myMessageBox->setEditable(false, false); - myMessageBox->clearFlags(WIDGET_RETAIN_FOCUS); + myMessageBox->clearFlags(Widget::FLAG_RETAIN_FOCUS); myMessageBox->setTextColor(kTextColorEm); } @@ -577,7 +577,7 @@ void DebuggerDialog::addRomArea() myRewindButton = new ButtonWidget(this, *myLFont, buttonX, buttonY, bwidth, bheight, LEFT_ARROW, 7, 11, kDDRewindCmd); - myRewindButton->clearFlags(WIDGET_ENABLED); + myRewindButton->clearFlags(Widget::FLAG_ENABLED); buttonY += bheight + 4; bheight = (myLFont->getLineHeight() + 2) * 2 + 4 * 1; @@ -585,7 +585,7 @@ void DebuggerDialog::addRomArea() myUnwindButton = new ButtonWidget(this, *myLFont, buttonX, buttonY, bwidth, bheight, RIGHT_ARROW, 7, 11, kDDUnwindCmd); - myUnwindButton->clearFlags(WIDGET_ENABLED); + myUnwindButton->clearFlags(Widget::FLAG_ENABLED); int xpos = buttonX - 8*myLFont->getMaxCharWidth() - 20, ypos = 30; diff --git a/src/debugger/gui/PromptWidget.cxx b/src/debugger/gui/PromptWidget.cxx index c49732c8d..a9740ca44 100644 --- a/src/debugger/gui/PromptWidget.cxx +++ b/src/debugger/gui/PromptWidget.cxx @@ -41,8 +41,8 @@ PromptWidget::PromptWidget(GuiObject* boss, const GUI::Font& font, _firstTime(true), _exitedEarly(false) { - _flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | - WIDGET_WANTS_TAB | WIDGET_WANTS_RAWDATA; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS | + Widget::FLAG_WANTS_TAB | Widget::FLAG_WANTS_RAWDATA; _textcolor = kTextColor; _bgcolor = kWidColor; _bgcolorlo = kDlgColor; diff --git a/src/debugger/gui/RamWidget.cxx b/src/debugger/gui/RamWidget.cxx index ad4d78b43..6bbfcbced 100644 --- a/src/debugger/gui/RamWidget.cxx +++ b/src/debugger/gui/RamWidget.cxx @@ -158,8 +158,8 @@ RamWidget::RamWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n myInputBox->setTarget(this); // Start with these buttons disabled - myCompareButton->clearFlags(WIDGET_ENABLED); - myRestartButton->clearFlags(WIDGET_ENABLED); + myCompareButton->clearFlags(Widget::FLAG_ENABLED); + myRestartButton->clearFlags(Widget::FLAG_ENABLED); // Calculate final height if(_h == 0) _h = ypos + myLineHeight - y; diff --git a/src/debugger/gui/RomListWidget.cxx b/src/debugger/gui/RomListWidget.cxx index 9e16eca4a..91123f8e5 100644 --- a/src/debugger/gui/RomListWidget.cxx +++ b/src/debugger/gui/RomListWidget.cxx @@ -43,7 +43,7 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont, myDisasm(nullptr), myBPState(nullptr) { - _flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS; _bgcolor = kWidColor; _bgcolorhi = kWidColor; _textcolor = kTextColor; @@ -130,12 +130,12 @@ void RomListWidget::setList(const CartDebug::Disassembly& disasm, // Enable all checkboxes for(int i = 0; i < _rows; ++i) - myCheckList[i]->setFlags(WIDGET_ENABLED); + myCheckList[i]->setFlags(Widget::FLAG_ENABLED); // Then turn off any extras if(int(myDisasm->list.size()) < _rows) for(int i = int(myDisasm->list.size()); i < _rows; ++i) - myCheckList[i]->clearFlags(WIDGET_ENABLED); + myCheckList[i]->clearFlags(Widget::FLAG_ENABLED); recalc(); } @@ -290,14 +290,14 @@ void RomListWidget::handleMouseWheel(int x, int y, int direction) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RomListWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); setDirty(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RomListWidget::handleMouseLeft() { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); setDirty(); } diff --git a/src/debugger/gui/TiaZoomWidget.cxx b/src/debugger/gui/TiaZoomWidget.cxx index f78232da3..0c4fb7256 100644 --- a/src/debugger/gui/TiaZoomWidget.cxx +++ b/src/debugger/gui/TiaZoomWidget.cxx @@ -32,8 +32,8 @@ TiaZoomWidget::TiaZoomWidget(GuiObject* boss, const GUI::Font& font, : Widget(boss, font, x, y, 16, 16), CommandSender(boss) { - _flags = WIDGET_ENABLED | WIDGET_CLEARBG | - WIDGET_RETAIN_FOCUS | WIDGET_TRACK_MOUSE; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | + Widget::FLAG_RETAIN_FOCUS | Widget::FLAG_TRACK_MOUSE; _bgcolor = _bgcolorhi = kDlgColor; // Use all available space, up to the maximum bounds of the TIA image @@ -167,14 +167,14 @@ void TiaZoomWidget::handleMouseMoved(int x, int y) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TiaZoomWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); setDirty(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TiaZoomWidget::handleMouseLeft() { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); setDirty(); myMouseMoving = false; } diff --git a/src/debugger/gui/ToggleWidget.cxx b/src/debugger/gui/ToggleWidget.cxx index 9df615c82..93847709f 100644 --- a/src/debugger/gui/ToggleWidget.cxx +++ b/src/debugger/gui/ToggleWidget.cxx @@ -36,21 +36,21 @@ ToggleWidget::ToggleWidget(GuiObject* boss, const GUI::Font& font, _clicksToChange(clicksToChange), _editable(true) { - _flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | - WIDGET_WANTS_RAWDATA; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS | + Widget::FLAG_WANTS_RAWDATA; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ToggleWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); setDirty(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ToggleWidget::handleMouseLeft() { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); setDirty(); } diff --git a/src/emucore/Bankswitch.cxx b/src/emucore/Bankswitch.cxx index db3b570c8..200fc1ca0 100644 --- a/src/emucore/Bankswitch.cxx +++ b/src/emucore/Bankswitch.cxx @@ -137,7 +137,7 @@ Bankswitch::Description Bankswitch::BSList[int(Bankswitch::Type::NumSchemes)] = { "UA", "UA (8K UA Ltd.)" }, { "WD", "WD (Experimental)" }, { "X07", "X07 (64K AtariAge)" }, -#ifdef CUSTOM_ARM +#if defined(CUSTOM_ARM) { "CUSTOM", "CUSTOM (ARM)" } #endif }; @@ -149,11 +149,12 @@ Bankswitch::ExtensionMap Bankswitch::ourExtensions = { { "a26", Bankswitch::Type::_AUTO }, { "bin", Bankswitch::Type::_AUTO }, { "rom", Bankswitch::Type::_AUTO }, - { "gz", Bankswitch::Type::_AUTO }, +#if defined(ZIP_SUPPORT) { "zip", Bankswitch::Type::_AUTO }, +#endif { "cu", Bankswitch::Type::_AUTO }, - // All bankswitch types (tose that UnoCart and HarmonyCart support have the same name) + // All bankswitch types (those that UnoCart and HarmonyCart support have the same name) { "084", Bankswitch::Type::_0840 }, { "2N1", Bankswitch::Type::_2IN1 }, { "4N1", Bankswitch::Type::_4IN1 }, diff --git a/src/emucore/M6532.hxx b/src/emucore/M6532.hxx index 1cfd5da5e..f6330cba4 100644 --- a/src/emucore/M6532.hxx +++ b/src/emucore/M6532.hxx @@ -123,6 +123,13 @@ class M6532 : public Device */ void updateEmulation(); + /** + Get a pointer to the RAM contents. + + @return Pointer to RAM array. + */ + const uInt8* getRAM() const { return myRAM; } + private: void setTimerRegister(uInt8 data, uInt8 interval); diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index c7c7df3f0..8b6851fb8 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -121,6 +121,7 @@ Settings::Settings() setPermanent("uipalette", "standard"); setPermanent("listdelay", "300"); setPermanent("mwheel", "4"); + setPermanent("basic_settings", false); // Misc options setPermanent("autoslot", "false"); diff --git a/src/gui/AboutDialog.cxx b/src/gui/AboutDialog.cxx index c3a4857e2..8ddf1038c 100644 --- a/src/gui/AboutDialog.cxx +++ b/src/gui/AboutDialog.cxx @@ -47,7 +47,7 @@ AboutDialog::AboutDialog(OSystem& osystem, DialogContainer& parent, myPrevButton = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Previous", GuiObject::kPrevCmd); - myPrevButton->clearFlags(WIDGET_ENABLED); + myPrevButton->clearFlags(Widget::FLAG_ENABLED); wid.push_back(myPrevButton); xpos += buttonWidth + 8; @@ -237,9 +237,9 @@ void AboutDialog::handleCommand(CommandSender* sender, int cmd, int data, int id case GuiObject::kNextCmd: myPage++; if(myPage >= myNumPages) - myNextButton->clearFlags(WIDGET_ENABLED); + myNextButton->clearFlags(Widget::FLAG_ENABLED); if(myPage >= 2) - myPrevButton->setFlags(WIDGET_ENABLED); + myPrevButton->setFlags(Widget::FLAG_ENABLED); displayInfo(); break; @@ -247,9 +247,9 @@ void AboutDialog::handleCommand(CommandSender* sender, int cmd, int data, int id case GuiObject::kPrevCmd: myPage--; if(myPage <= myNumPages) - myNextButton->setFlags(WIDGET_ENABLED); + myNextButton->setFlags(Widget::FLAG_ENABLED); if(myPage <= 1) - myPrevButton->clearFlags(WIDGET_ENABLED); + myPrevButton->clearFlags(Widget::FLAG_ENABLED); displayInfo(); break; diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index ea11a43f0..701a4a5c8 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -117,23 +117,23 @@ void BrowserDialog::show(const string& startpath, _fileList->setFileListMode(FilesystemNode::ListMode::All); _fileList->setFileExtension(ext); _selected->setEditable(false); - _selected->clearFlags(WIDGET_INVISIBLE); - _type->clearFlags(WIDGET_INVISIBLE); + _selected->clearFlags(Widget::FLAG_INVISIBLE); + _type->clearFlags(Widget::FLAG_INVISIBLE); break; case FileSave: _fileList->setFileListMode(FilesystemNode::ListMode::All); _fileList->setFileExtension(ext); _selected->setEditable(false); // FIXME - disable user input for now - _selected->clearFlags(WIDGET_INVISIBLE); - _type->clearFlags(WIDGET_INVISIBLE); + _selected->clearFlags(Widget::FLAG_INVISIBLE); + _type->clearFlags(Widget::FLAG_INVISIBLE); break; case Directories: _fileList->setFileListMode(FilesystemNode::ListMode::DirectoriesOnly); _selected->setEditable(false); - _selected->setFlags(WIDGET_INVISIBLE); - _type->setFlags(WIDGET_INVISIBLE); + _selected->setFlags(Widget::FLAG_INVISIBLE); + _type->setFlags(Widget::FLAG_INVISIBLE); break; } diff --git a/src/gui/CheckListWidget.cxx b/src/gui/CheckListWidget.cxx index 83d96059d..56ceec54b 100644 --- a/src/gui/CheckListWidget.cxx +++ b/src/gui/CheckListWidget.cxx @@ -49,14 +49,14 @@ CheckListWidget::CheckListWidget(GuiObject* boss, const GUI::Font& font, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CheckListWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); setDirty(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CheckListWidget::handleMouseLeft() { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); setDirty(); } @@ -70,12 +70,12 @@ void CheckListWidget::setList(const StringList& list, const BoolArray& state) // Enable all checkboxes for(int i = 0; i < _rows; ++i) - _checkList[i]->setFlags(WIDGET_ENABLED); + _checkList[i]->setFlags(Widget::FLAG_ENABLED); // Then turn off any extras if(int(_stateList.size()) < _rows) for(int i = int(_stateList.size()); i < _rows; ++i) - _checkList[i]->clearFlags(WIDGET_ENABLED); + _checkList[i]->clearFlags(Widget::FLAG_ENABLED); ListWidget::recalc(); } diff --git a/src/gui/ColorWidget.cxx b/src/gui/ColorWidget.cxx index e70ca0022..86ee01260 100644 --- a/src/gui/ColorWidget.cxx +++ b/src/gui/ColorWidget.cxx @@ -32,7 +32,7 @@ ColorWidget::ColorWidget(GuiObject* boss, const GUI::Font& font, _cmd(cmd), _crossGrid(false) { - _flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/CommandMenu.cxx b/src/gui/CommandMenu.cxx index ae6f8197f..131ab1924 100644 --- a/src/gui/CommandMenu.cxx +++ b/src/gui/CommandMenu.cxx @@ -17,11 +17,15 @@ #include "Dialog.hxx" #include "CommandDialog.hxx" +#include "MinUICommandDialog.hxx" #include "CommandMenu.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CommandMenu::CommandMenu(OSystem& osystem) : DialogContainer(osystem) { - myBaseDialog = new CommandDialog(myOSystem, *this); + if (osystem.settings().getBool("minimal_ui")) + myBaseDialog = new MinUICommandDialog(myOSystem, *this); + else + myBaseDialog = new CommandDialog(myOSystem, *this); } diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx index 7c6ab5efd..eaa0663be 100644 --- a/src/gui/DeveloperDialog.cxx +++ b/src/gui/DeveloperDialog.cxx @@ -559,8 +559,8 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font) #endif if(!debuggerAvailable) { - myDebuggerWidthSlider->clearFlags(WIDGET_ENABLED); - myDebuggerHeightSlider->clearFlags(WIDGET_ENABLED); + myDebuggerWidthSlider->clearFlags(Widget::FLAG_ENABLED); + myDebuggerHeightSlider->clearFlags(Widget::FLAG_ENABLED); } #else new StaticTextWidget(myTab, font, 0, 20, _w - 20, font.getFontHeight(), @@ -1331,8 +1331,8 @@ void DeveloperDialog::handleDebugColours(int idx, int color) if(!instance().hasConsole()) { - myDbgColour[idx]->clearFlags(WIDGET_ENABLED); - myDbgColourSwatch[idx]->clearFlags(WIDGET_ENABLED); + myDbgColour[idx]->clearFlags(Widget::FLAG_ENABLED); + myDbgColourSwatch[idx]->clearFlags(Widget::FLAG_ENABLED); return; } diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index c94572e25..2feaa68b8 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -62,7 +62,7 @@ Dialog::Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font _th(0), _surface(nullptr), _tabID(0), - _flags(WIDGET_ENABLED | WIDGET_BORDER | WIDGET_CLEARBG), + _flags(Widget::FLAG_ENABLED | Widget::FLAG_BORDER | Widget::FLAG_CLEARBG), _max_w(0), _max_h(0) { @@ -198,7 +198,7 @@ void Dialog::addFocusWidget(Widget* w) return; // All focusable widgets should retain focus - w->setFlags(WIDGET_RETAIN_FOCUS); + w->setFlags(Widget::FLAG_RETAIN_FOCUS); _myFocus.widget = w; _myFocus.list.push_back(w); @@ -209,7 +209,7 @@ void Dialog::addToFocusList(WidgetArray& list) { // All focusable widgets should retain focus for(const auto& w: list) - w->setFlags(WIDGET_RETAIN_FOCUS); + w->setFlags(Widget::FLAG_RETAIN_FOCUS); Vec::append(_myFocus.list, list); _focusList = _myFocus.list; @@ -222,14 +222,14 @@ void Dialog::addToFocusList(WidgetArray& list) void Dialog::addToFocusList(WidgetArray& list, TabWidget* w, int tabId) { // Only add the list if the tab actually exists - if(!w || w->getID() < 0 || uInt32(w->getID()) >= _myTabList.size()) + if(!w || w->getID() >= _myTabList.size()) return; assert(w == _myTabList[w->getID()].widget); // All focusable widgets should retain focus for(const auto& fw: list) - fw->setFlags(WIDGET_RETAIN_FOCUS); + fw->setFlags(Widget::FLAG_RETAIN_FOCUS); // First get the appropriate focus list FocusList& focus = _myTabList[w->getID()].focus; @@ -254,7 +254,7 @@ void Dialog::addToFocusList(WidgetArray& list, TabWidget* w, int tabId) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Dialog::addTabWidget(TabWidget* w) { - if(!w || w->getID() < 0) + if(!w) return; // Make sure the array is large enough @@ -341,7 +341,7 @@ void Dialog::drawDialog() || (parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this && !parent().myDialogStack.top()->hasTitle()); - if(_flags & WIDGET_CLEARBG) + if(_flags & Widget::FLAG_CLEARBG) { // cerr << "Dialog::drawDialog(): w = " << _w << ", h = " << _h << " @ " << &s << endl << endl; s.fillRect(_x, _y + _th, _w, _h - _th, _onTop ? kDlgColor : kBGColorLo); @@ -354,7 +354,7 @@ void Dialog::drawDialog() } else s.invalidate(); - if(_flags & WIDGET_BORDER) // currently only used by Dialog itself + if(_flags & Widget::FLAG_BORDER) // currently only used by Dialog itself s.frameRect(_x, _y, _w, _h, _onTop ? kColor : kShadowColor); // Make all child widget dirty @@ -459,7 +459,7 @@ void Dialog::handleMouseUp(int x, int y, MouseButton b, int clickCount) if(_focusedWidget) { // Lose focus on mouseup unless the widget requested to retain the focus - if(! (_focusedWidget->getFlags() & WIDGET_RETAIN_FOCUS )) + if(! (_focusedWidget->getFlags() & Widget::FLAG_RETAIN_FOCUS )) releaseFocus(); } @@ -531,7 +531,7 @@ void Dialog::handleMouseMoved(int x, int y) _mouseWidget = w; } - if (w && (w->getFlags() & WIDGET_TRACK_MOUSE)) + if (w && (w->getFlags() & Widget::FLAG_TRACK_MOUSE)) w->handleMouseMoved(x - (w->getAbsX() - _x), y - (w->getAbsY() - _y)); } diff --git a/src/gui/DialogContainer.cxx b/src/gui/DialogContainer.cxx index 3bf3f9e90..d7a2f2e56 100644 --- a/src/gui/DialogContainer.cxx +++ b/src/gui/DialogContainer.cxx @@ -157,7 +157,7 @@ void DialogContainer::reStack() while(!myDialogStack.empty()) myDialogStack.top()->close(); - myBaseDialog->open(); + getBaseDialog()->open(); // Reset all continuous events reset(); diff --git a/src/gui/DialogContainer.hxx b/src/gui/DialogContainer.hxx index 81718c2e1..84ad9235f 100644 --- a/src/gui/DialogContainer.hxx +++ b/src/gui/DialogContainer.hxx @@ -141,6 +141,11 @@ class DialogContainer */ const Dialog* baseDialog() const { return myBaseDialog; } + /** + Return the bottom-most dialog of this container. Can be overwritten. + */ + virtual Dialog* getBaseDialog() { return myBaseDialog; } + /** Inform the container that it should resize according to the current screen dimensions. We make this virtual, since the container may or diff --git a/src/gui/EditTextWidget.cxx b/src/gui/EditTextWidget.cxx index f7d8eb801..85e1778ba 100644 --- a/src/gui/EditTextWidget.cxx +++ b/src/gui/EditTextWidget.cxx @@ -27,7 +27,7 @@ EditTextWidget::EditTextWidget(GuiObject* boss, const GUI::Font& font, : EditableWidget(boss, font, x, y, w, h + 2, text), _changed(false) { - _flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS; startEditMode(); // We're always in edit mode } @@ -43,14 +43,14 @@ void EditTextWidget::setText(const string& str, bool changed) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EditTextWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); setDirty(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EditTextWidget::handleMouseLeft() { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); setDirty(); } diff --git a/src/gui/EditableWidget.cxx b/src/gui/EditableWidget.cxx index f214173e5..689b6c546 100644 --- a/src/gui/EditableWidget.cxx +++ b/src/gui/EditableWidget.cxx @@ -70,12 +70,12 @@ void EditableWidget::setEditable(bool editable, bool hiliteBG) _editable = editable; if(_editable) { - setFlags(WIDGET_WANTS_RAWDATA | WIDGET_RETAIN_FOCUS); + setFlags(Widget::FLAG_WANTS_RAWDATA | Widget::FLAG_RETAIN_FOCUS); _bgcolor = kWidColor; } else { - clearFlags(WIDGET_WANTS_RAWDATA | WIDGET_RETAIN_FOCUS); + clearFlags(Widget::FLAG_WANTS_RAWDATA | Widget::FLAG_RETAIN_FOCUS); _bgcolor = hiliteBG ? kBGColorHi : kWidColor; } } diff --git a/src/gui/EditableWidget.hxx b/src/gui/EditableWidget.hxx index d6a5dab6e..66fb75174 100644 --- a/src/gui/EditableWidget.hxx +++ b/src/gui/EditableWidget.hxx @@ -64,9 +64,9 @@ class EditableWidget : public Widget, public CommandSender void setTextFilter(const TextFilter& filter) { _filter = filter; } protected: - virtual void startEditMode() { setFlags(WIDGET_WANTS_RAWDATA); } - virtual void endEditMode() { clearFlags(WIDGET_WANTS_RAWDATA); } - virtual void abortEditMode() { clearFlags(WIDGET_WANTS_RAWDATA); } + virtual void startEditMode() { setFlags(Widget::FLAG_WANTS_RAWDATA); } + virtual void endEditMode() { clearFlags(Widget::FLAG_WANTS_RAWDATA); } + virtual void abortEditMode() { clearFlags(Widget::FLAG_WANTS_RAWDATA); } virtual GUI::Rect getEditRect() const = 0; virtual int getCaretOffset() const; diff --git a/src/gui/EventMappingWidget.cxx b/src/gui/EventMappingWidget.cxx index 4437213d5..21edc2d6a 100644 --- a/src/gui/EventMappingWidget.cxx +++ b/src/gui/EventMappingWidget.cxx @@ -78,7 +78,7 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, buttonWidth, buttonHeight, "Cancel", kStopMapCmd); myCancelMapButton->setTarget(this); - myCancelMapButton->clearFlags(WIDGET_ENABLED); + myCancelMapButton->clearFlags(Widget::FLAG_ENABLED); addFocusWidget(myCancelMapButton); ypos += lineHeight + 20; @@ -119,7 +119,7 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, myKeyMapping = new EditTextWidget(boss, font, xpos + t->getWidth() + 8, ypos, _w - xpos - t->getWidth() - 8 - HBORDER, lineHeight, ""); myKeyMapping->setEditable(false, true); - myKeyMapping->clearFlags(WIDGET_RETAIN_FOCUS); + myKeyMapping->clearFlags(Widget::FLAG_RETAIN_FOCUS); // Add information for hardcoded keys ypos += lineHeight + 8; @@ -178,7 +178,7 @@ void EventMappingWidget::startRemapping() // Make sure that this widget receives all raw data, before any // pre-processing occurs - myActionsList->setFlags(WIDGET_WANTS_RAWDATA); + myActionsList->setFlags(Widget::FLAG_WANTS_RAWDATA); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -223,7 +223,7 @@ void EventMappingWidget::stopRemapping() drawKeyMapping(); // Widget is now free to process events normally - myActionsList->clearFlags(WIDGET_WANTS_RAWDATA); + myActionsList->clearFlags(Widget::FLAG_WANTS_RAWDATA); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/HelpDialog.cxx b/src/gui/HelpDialog.cxx index 21706b2fa..6ae094eab 100644 --- a/src/gui/HelpDialog.cxx +++ b/src/gui/HelpDialog.cxx @@ -45,7 +45,7 @@ HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent, myPrevButton = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Previous", GuiObject::kPrevCmd); - myPrevButton->clearFlags(WIDGET_ENABLED); + myPrevButton->clearFlags(Widget::FLAG_ENABLED); wid.push_back(myPrevButton); xpos += buttonWidth + 8; @@ -195,9 +195,9 @@ void HelpDialog::handleCommand(CommandSender* sender, int cmd, case GuiObject::kNextCmd: ++myPage; if(myPage >= myNumPages) - myNextButton->clearFlags(WIDGET_ENABLED); + myNextButton->clearFlags(Widget::FLAG_ENABLED); if(myPage >= 2) - myPrevButton->setFlags(WIDGET_ENABLED); + myPrevButton->setFlags(Widget::FLAG_ENABLED); displayInfo(); break; @@ -205,9 +205,9 @@ void HelpDialog::handleCommand(CommandSender* sender, int cmd, case GuiObject::kPrevCmd: --myPage; if(myPage <= myNumPages) - myNextButton->setFlags(WIDGET_ENABLED); + myNextButton->setFlags(Widget::FLAG_ENABLED); if(myPage <= 1) - myPrevButton->clearFlags(WIDGET_ENABLED); + myPrevButton->clearFlags(Widget::FLAG_ENABLED); displayInfo(); break; diff --git a/src/gui/InputDialog.cxx b/src/gui/InputDialog.cxx index 773a512f3..9e4f8a9f7 100644 --- a/src/gui/InputDialog.cxx +++ b/src/gui/InputDialog.cxx @@ -136,7 +136,7 @@ void InputDialog::addDevicePortTab(const GUI::Font& font) "Mouse cursor visibility ", lwidth); wid.push_back(myCursorState); #ifndef WINDOWED_SUPPORT - myCursorState->clearFlags(WIDGET_ENABLED); + myCursorState->clearFlags(Widget::FLAG_ENABLED); #endif lwidth = font.getStringWidth("Digital paddle sensitivity "); @@ -196,7 +196,7 @@ void InputDialog::addDevicePortTab(const GUI::Font& font) "Grab mouse in emulation mode"); wid.push_back(myGrabMouse); #ifndef WINDOWED_SUPPORT - myGrabMouse->clearFlags(WIDGET_ENABLED); + myGrabMouse->clearFlags(Widget::FLAG_ENABLED); #endif // Enable/disable control key-combos diff --git a/src/gui/JoystickDialog.cxx b/src/gui/JoystickDialog.cxx index 8f15f4aeb..a0412f9f9 100644 --- a/src/gui/JoystickDialog.cxx +++ b/src/gui/JoystickDialog.cxx @@ -61,7 +61,7 @@ JoystickDialog::JoystickDialog(GuiObject* boss, const GUI::Font& font, xpos -= buttonWidth + 8; myRemoveBtn = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Remove", kRemoveCmd); - myRemoveBtn->clearFlags(WIDGET_ENABLED); + myRemoveBtn->clearFlags(Widget::FLAG_ENABLED); // Now we can finally add the widgets to the focus list wid.push_back(myRemoveBtn); diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index 9f24cab64..f8b05b310 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -164,7 +164,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, xpos += lwidth; myDir = new EditTextWidget(this, font, xpos, ypos, _w - xpos - HBORDER, lineHeight, ""); myDir->setEditable(false, true); - myDir->clearFlags(WIDGET_RETAIN_FOCUS); + myDir->clearFlags(Widget::FLAG_RETAIN_FOCUS); if(!myUseMinimalUI) { @@ -206,10 +206,6 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, } mySelectedItem = 0; // Highlight 'Rom Listing' - // Create an options dialog, similar to the in-game one - myOptions = make_unique(osystem, parent, this, w, h, - OptionsDialog::AppMode::launcher); - // Create a game list, which contains all the information about a ROM that // the launcher needs myGameList = make_unique(); @@ -226,9 +222,6 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, // ROM properties myGlobalProps = make_unique(this, myUseMinimalUI ? osystem.frameBuffer().launcherFont() : osystem.frameBuffer().font()); - if (myUseMinimalUI) - myStellaSettingsDialog = - make_unique(osystem, parent, osystem.frameBuffer().launcherFont(), w, h); // Do we show only ROMs or all files? bool onlyROMs = instance().settings().getBool("launcherroms"); @@ -467,20 +460,20 @@ void LauncherDialog::handleKeyDown(StellaKey key, StellaMod mod) // handle keys used by R77 switch(key) { - case KBDK_F8: - myStellaSettingsDialog->open(); + case KBDK_F8: // front ("Skill P2") + openSettings(); break; - case KBDK_F4: + case KBDK_F4: // back ("COLOR", "B/W") myGlobalProps->open(); break; - case KBDK_F11: + case KBDK_F11: // front ("LOAD") // convert unused previous item key into page-up key Dialog::handleKeyDown(KBDK_F13, mod); break; - case KBDK_F1: + case KBDK_F1: // front ("MODE") // convert unused next item key into page-down key Dialog::handleKeyDown(KBDK_BACKSPACE, mod); break; @@ -553,7 +546,7 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd, } case kOptionsCmd: - myOptions->open(); + openSettings(); break; case kPrevDirCmd: @@ -640,3 +633,22 @@ void LauncherDialog::startGame() } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void LauncherDialog::openSettings() +{ + // Create an options dialog, similar to the in-game one + if (instance().settings().getBool("basic_settings")) + { + if (myStellaSettingsDialog == nullptr) + myStellaSettingsDialog = make_unique(instance(), parent(), + instance().frameBuffer().launcherFont(), _w, _h, Menu::AppMode::launcher); + myStellaSettingsDialog->open(); + } + else + { + if (myOptionsDialog == nullptr) + myOptionsDialog = make_unique(instance(), parent(), this, _w, _h, + Menu::AppMode::launcher); + myOptionsDialog->open(); + } +} diff --git a/src/gui/LauncherDialog.hxx b/src/gui/LauncherDialog.hxx index 3044d736e..cf525fcb5 100644 --- a/src/gui/LauncherDialog.hxx +++ b/src/gui/LauncherDialog.hxx @@ -99,13 +99,14 @@ class LauncherDialog : public Dialog void showOnlyROMs(bool state); bool matchPattern(const string& s, const string& pattern) const; void startGame(); + void openSettings(); private: - unique_ptr myOptions; + unique_ptr myOptionsDialog; + unique_ptr myStellaSettingsDialog; unique_ptr myGameList; unique_ptr myMenu; unique_ptr myGlobalProps; - unique_ptr myStellaSettingsDialog; unique_ptr myRomDir; ButtonWidget* myStartButton; diff --git a/src/gui/ListWidget.cxx b/src/gui/ListWidget.cxx index f6fb6cd26..f0515c6ce 100644 --- a/src/gui/ListWidget.cxx +++ b/src/gui/ListWidget.cxx @@ -41,7 +41,7 @@ ListWidget::ListWidget(GuiObject* boss, const GUI::Font& font, _quickSelect(quickSelect), _quickSelectTime(0) { - _flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS; _bgcolor = kWidColor; _bgcolorhi = kWidColor; _textcolor = kTextColor; diff --git a/src/gui/Menu.cxx b/src/gui/Menu.cxx index d8baa83f0..782549d3f 100644 --- a/src/gui/Menu.cxx +++ b/src/gui/Menu.cxx @@ -18,13 +18,33 @@ #include "Dialog.hxx" #include "FrameBufferConstants.hxx" #include "OptionsDialog.hxx" +#include "StellaSettingsDialog.hxx" +#include "FrameBuffer.hxx" #include "bspf.hxx" #include "Menu.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Menu::Menu(OSystem& osystem) - : DialogContainer(osystem) + : DialogContainer(osystem), + stellaSettingDialog(nullptr), + optionsDialog(nullptr) +{} + +Dialog* Menu::getBaseDialog() { - myBaseDialog = new OptionsDialog(myOSystem, *this, nullptr, - FBMinimum::Width, FBMinimum::Height, OptionsDialog::AppMode::emulator); + if (myOSystem.settings().getBool("basic_settings")) + { + if (stellaSettingDialog == nullptr) + stellaSettingDialog = new StellaSettingsDialog(myOSystem, *this, myOSystem.frameBuffer().font(), + FBMinimum::Width, FBMinimum::Height, AppMode::emulator); + return stellaSettingDialog; + } + else + { + if (optionsDialog == nullptr) + optionsDialog = new OptionsDialog(myOSystem, *this, nullptr, + FBMinimum::Width, FBMinimum::Height, AppMode::emulator); + return optionsDialog; + } } + diff --git a/src/gui/Menu.hxx b/src/gui/Menu.hxx index ab66c9427..eaa1dc9c8 100644 --- a/src/gui/Menu.hxx +++ b/src/gui/Menu.hxx @@ -19,6 +19,8 @@ #define MENU_HXX class OSystem; +class StellaSettingsDialog; +class OptionsDialog; #include "DialogContainer.hxx" @@ -30,12 +32,20 @@ class OSystem; class Menu : public DialogContainer { public: + // Current Stella mode + enum class AppMode { launcher, emulator, debugger }; + /** Create a new menu stack */ explicit Menu(OSystem& osystem); virtual ~Menu() = default; + StellaSettingsDialog* stellaSettingDialog; + OptionsDialog* optionsDialog; + + Dialog* getBaseDialog() override; + private: // Following constructors and assignment operators not supported Menu() = delete; diff --git a/src/gui/MinUICommandDialog.cxx b/src/gui/MinUICommandDialog.cxx new file mode 100644 index 000000000..1c3a397ba --- /dev/null +++ b/src/gui/MinUICommandDialog.cxx @@ -0,0 +1,295 @@ +//============================================================================ +// +// 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-2019 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 "TIA.hxx" +#include "Switches.hxx" +#include "Dialog.hxx" +#include "Font.hxx" +#include "EventHandler.hxx" +#include "StateManager.hxx" +#include "RewindManager.hxx" +#include "OSystem.hxx" +#include "Widget.hxx" +#include "StellaSettingsDialog.hxx" +#include "OptionsDialog.hxx" +#include "TIASurface.hxx" +#include "MinUICommandDialog.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +MinUICommandDialog::MinUICommandDialog(OSystem& osystem, DialogContainer& parent) + : Dialog(osystem, parent, osystem.frameBuffer().font(), "Commands"), + myStellaSettingsDialog(nullptr), + myOptionsDialog(nullptr) +{ + const int HBORDER = 10; + const int VBORDER = 10; + const int HGAP = 8; + const int VGAP = 5; + const int buttonWidth = _font.getStringWidth(" Load State 0") + 20, + buttonHeight = _font.getLineHeight() + 8, + rowHeight = buttonHeight + VGAP; + + // Set real dimensions + _w = 3 * (buttonWidth + 5) + HBORDER * 2; + _h = 6 * rowHeight - VGAP + VBORDER * 2 + _th; + ButtonWidget* bw = nullptr; + WidgetArray wid; + int xoffset = HBORDER, yoffset = VBORDER + _th; + + auto ADD_CD_BUTTON = [&](const string& label, int cmd) + { + ButtonWidget* b = new ButtonWidget(this, _font, xoffset, yoffset, + buttonWidth, buttonHeight, label, cmd); + yoffset += buttonHeight + VGAP; + return b; + }; + + // Column 1 + bw = ADD_CD_BUTTON("Select", kSelectCmd); + wid.push_back(bw); + bw = ADD_CD_BUTTON("Reset", kResetCmd); + wid.push_back(bw); + myColorButton = ADD_CD_BUTTON("", kColorCmd); + wid.push_back(myColorButton); + myLeftDiffButton = ADD_CD_BUTTON("", kLeftDiffCmd); + wid.push_back(myLeftDiffButton); + myRightDiffButton = ADD_CD_BUTTON("", kLeftDiffCmd); + wid.push_back(myRightDiffButton); + + // Column 2 + xoffset += buttonWidth + HGAP; + yoffset = VBORDER + _th; + + mySaveStateButton = ADD_CD_BUTTON("", kSaveStateCmd); + wid.push_back(mySaveStateButton); + myStateSlotButton = ADD_CD_BUTTON("", kStateSlotCmd); + wid.push_back(myStateSlotButton); + myLoadStateButton = ADD_CD_BUTTON("", kLoadStateCmd); + wid.push_back(myLoadStateButton); + myRewindButton = ADD_CD_BUTTON("Rewind", kRewindCmd); + wid.push_back(myRewindButton); + myUnwindButton = ADD_CD_BUTTON("Unwind", kUnwindCmd); + wid.push_back(myUnwindButton); + bw = ADD_CD_BUTTON("Close", GuiObject::kCloseCmd); + wid.push_back(bw); + + // Column 3 + xoffset += buttonWidth + HGAP; + yoffset = VBORDER + _th; + + myTVFormatButton = ADD_CD_BUTTON("", kFormatCmd); + wid.push_back(myTVFormatButton); + myStretchButton = ADD_CD_BUTTON("", kStretchCmd); + wid.push_back(myStretchButton); + myPhosphorButton = ADD_CD_BUTTON("", kPhosphorCmd); + wid.push_back(myPhosphorButton); + bw = ADD_CD_BUTTON("Settings"+ ELLIPSIS, kSettings); + wid.push_back(bw); + bw = ADD_CD_BUTTON("Exit Game", kExitGameCmd); + wid.push_back(bw); + + addToFocusList(wid); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void MinUICommandDialog::loadConfig() +{ + // Column 1 + myColorButton->setLabel(instance().console().switches().tvColor() ? "Color Mode" : "B/W Mode"); + myLeftDiffButton->setLabel(instance().console().switches().leftDifficultyA() ? "P1 Skill A" : "P1 Skill B"); + myRightDiffButton->setLabel(instance().console().switches().rightDifficultyA() ? "P2 Skill A" : "P2 Skill B"); + // Column 2 + updateSlot(instance().state().currentSlot()); + updateWinds(); + + // Column 3 + updateTVFormat(); + myStretchButton->setLabel(instance().settings().getBool("tia.fs_stretch") ? "Stretched" : "4:3 Format"); + myPhosphorButton->setLabel(instance().frameBuffer().tiaSurface().phosphorEnabled() ? "Phosphor On" : "Phosphor Off"); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void MinUICommandDialog::handleKeyDown(StellaKey key, StellaMod mod) +{ + switch (key) + { + case KBDK_F8: // front ("Skill P2") + instance().eventHandler().leaveMenuMode(); + break; + + default: + Dialog::handleKeyDown(key, mod); + break; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void MinUICommandDialog::handleCommand(CommandSender* sender, int cmd, + int data, int id) +{ + bool consoleCmd = false, stateCmd = false; + Event::Type event = Event::NoType; + + switch(cmd) + { + // Column 1 + case kSelectCmd: + event = Event::ConsoleSelect; + consoleCmd = true; + break; + + case kResetCmd: + event = Event::ConsoleReset; + consoleCmd = true; + break; + + case kColorCmd: + event = Event::ConsoleColorToggle; + consoleCmd = true; + break; + + case kLeftDiffCmd: + event = Event::ConsoleLeftDiffToggle; + consoleCmd = true; + break; + + case kRightDiffCmd: + event = Event::ConsoleRightDiffToggle; + consoleCmd = true; + break; + + // Column 2 + case kSaveStateCmd: + event = Event::SaveState; + consoleCmd = true; + break; + + case kStateSlotCmd: + { + event = Event::ChangeState; + stateCmd = true; + int slot = (instance().state().currentSlot() + 1) % 10; + updateSlot(slot); + break; + } + + case kLoadStateCmd: + event = Event::LoadState; + consoleCmd = true; + break; + + case kRewindCmd: + // rewind 5s + instance().state().rewindStates(5); + updateWinds(); + break; + + case kUnwindCmd: + // unwind 5s + instance().state().unwindStates(5); + updateWinds(); + break; + + case GuiObject::kCloseCmd: + instance().eventHandler().leaveMenuMode(); + break; + + // Column 3 + case kFormatCmd: + instance().console().toggleFormat(); + updateTVFormat(); + break; + + case kStretchCmd: + instance().eventHandler().leaveMenuMode(); + instance().settings().setValue("tia.fs_stretch", !instance().settings().getBool("tia.fs_stretch")); + break; + + case kPhosphorCmd: + instance().eventHandler().leaveMenuMode(); + instance().console().togglePhosphor(); + break; + + case kSettings: + openSettings(); + break; + + case kExitGameCmd: + instance().eventHandler().handleEvent(Event::LauncherMode); + break; + } + + // Console commands should be performed right away, after leaving the menu + // State commands require you to exit the menu manually + if(consoleCmd) + { + instance().eventHandler().leaveMenuMode(); + instance().eventHandler().handleEvent(event); + instance().console().switches().update(); + instance().console().tia().update(); + instance().eventHandler().handleEvent(event, false); + } + else if(stateCmd) + instance().eventHandler().handleEvent(event); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void MinUICommandDialog::updateSlot(int slot) +{ + ostringstream buf; + buf << " " << slot; + + mySaveStateButton->setLabel("Save State" + buf.str()); + myStateSlotButton->setLabel("State Slot" + buf.str()); + myLoadStateButton->setLabel("Load State" + buf.str()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void MinUICommandDialog::updateTVFormat() +{ + myTVFormatButton->setLabel(instance().console().getFormatString() + " Mode"); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void MinUICommandDialog::updateWinds() +{ + RewindManager& r = instance().state().rewindManager(); + + myRewindButton->setEnabled(!r.atFirst()); + myUnwindButton->setEnabled(!r.atLast()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void MinUICommandDialog::openSettings() +{ + // Create an options dialog, similar to the in-game one + if (instance().settings().getBool("basic_settings")) + { + if (myStellaSettingsDialog == nullptr) + myStellaSettingsDialog = make_unique(instance(), parent(), + instance().frameBuffer().launcherFont(), FBMinimum::Width, FBMinimum::Height, Menu::AppMode::launcher); + myStellaSettingsDialog->open(); + } + else + { + if (myOptionsDialog == nullptr) + myOptionsDialog = make_unique(instance(), parent(), this, + FBMinimum::Width, FBMinimum::Height, Menu::AppMode::launcher); + myOptionsDialog->open(); + } +} diff --git a/src/gui/MinUICommandDialog.hxx b/src/gui/MinUICommandDialog.hxx new file mode 100644 index 000000000..e569a9835 --- /dev/null +++ b/src/gui/MinUICommandDialog.hxx @@ -0,0 +1,92 @@ +//============================================================================ +// +// 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-2019 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 MIN_UI_COMMAND_DIALOG_HXX +#define MIN_UI_COMMAND_DIALOG_HXX + +class Properties; +class CommandSender; +class DialogContainer; +class OSystem; +class StellaSettingsDialog; +class OptionsDialog; + +#include "Dialog.hxx" + +class MinUICommandDialog : public Dialog +{ + public: + MinUICommandDialog(OSystem& osystem, DialogContainer& parent); + virtual ~MinUICommandDialog() = default; + + protected: + void loadConfig() override; + void handleKeyDown(StellaKey key, StellaMod mod) override; + void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + void updateSlot(int slot); + void updateWinds(); + void updateTVFormat(); + void openSettings(); + + // column 0 + ButtonWidget* myColorButton; + ButtonWidget* myLeftDiffButton; + ButtonWidget* myRightDiffButton; + // column 1 + ButtonWidget* mySaveStateButton; + ButtonWidget* myStateSlotButton; + ButtonWidget* myLoadStateButton; + ButtonWidget* myRewindButton; + ButtonWidget* myUnwindButton; + // column 2 + ButtonWidget* myTVFormatButton; + ButtonWidget* myStretchButton; + ButtonWidget* myPhosphorButton; + + unique_ptr myStellaSettingsDialog; + unique_ptr myOptionsDialog; + + enum + { + kSelectCmd = 'Csel', + kResetCmd = 'Cres', + kColorCmd = 'Ccol', + kLeftDiffCmd = 'Cldf', + kRightDiffCmd = 'Crdf', + kSaveStateCmd = 'Csst', + kStateSlotCmd = 'Ccst', + kLoadStateCmd = 'Clst', + kSnapshotCmd = 'Csnp', + kRewindCmd = 'Crew', + kUnwindCmd = 'Cunw', + kFormatCmd = 'Cfmt', + kStretchCmd = 'Cstr', + kPhosphorCmd = 'Cpho', + kSettings = 'Cscn', + kExitGameCmd = 'Cext', + }; + + private: + // Following constructors and assignment operators not supported + MinUICommandDialog() = delete; + MinUICommandDialog(const MinUICommandDialog&) = delete; + MinUICommandDialog(MinUICommandDialog&&) = delete; + MinUICommandDialog& operator=(const MinUICommandDialog&) = delete; + MinUICommandDialog& operator=(MinUICommandDialog&&) = delete; +}; + +#endif diff --git a/src/gui/OptionsDialog.cxx b/src/gui/OptionsDialog.cxx index e8f7df890..55375bb10 100644 --- a/src/gui/OptionsDialog.cxx +++ b/src/gui/OptionsDialog.cxx @@ -32,12 +32,12 @@ #include "GameInfoDialog.hxx" #include "LoggerDialog.hxx" #include "DeveloperDialog.hxx" -#include "StellaSettingsDialog.hxx" #include "HelpDialog.hxx" #include "AboutDialog.hxx" #include "OptionsDialog.hxx" #include "Launcher.hxx" #include "Settings.hxx" +#include "Menu.hxx" #ifdef CHEATCODE_SUPPORT #include "CheatCodeDialog.hxx" @@ -47,14 +47,16 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, - GuiObject* boss, int max_w, int max_h, AppMode mode) + GuiObject* boss, int max_w, int max_h, Menu::AppMode mode) : Dialog(osystem, parent, osystem.frameBuffer().font(), "Options"), myMode(mode) { - const int buttonWidth = _font.getStringWidth("Game Properties" + ELLIPSIS) + 20, - buttonHeight = _font.getLineHeight() + 6, + // do not show basic settings options in debugger + bool minSettings = osystem.settings().getBool("minimal_ui") && mode != Menu::AppMode::debugger; + const int buttonHeight = _font.getLineHeight() + 6, rowHeight = _font.getLineHeight() + 10; const int VBORDER = 10 + _th; + int buttonWidth = _font.getStringWidth("Game Properties" + ELLIPSIS) + 20; _w = 2 * buttonWidth + 30; _h = 7 * rowHeight + 15 + _th; @@ -63,6 +65,15 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, WidgetArray wid; ButtonWidget* b = nullptr; + if (minSettings) + { + ButtonWidget* bw = new ButtonWidget(this, _font, xoffset, yoffset, + _w - 10 * 2, buttonHeight, "Switch to Basic Settings" + ELLIPSIS, kBasSetCmd); + wid.push_back(bw); + yoffset += rowHeight + 8; + _h += rowHeight + 8; + } + auto ADD_OD_BUTTON = [&](const string& label, int cmd) { ButtonWidget* bw = new ButtonWidget(this, _font, xoffset, yoffset, @@ -76,7 +87,7 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, b = ADD_OD_BUTTON("Audio" + ELLIPSIS, kAudCmd); #ifndef SOUND_SUPPORT - b->clearFlags(WIDGET_ENABLED); + b->clearFlags(Widget::FLAG_ENABLED); #endif wid.push_back(b); @@ -90,23 +101,18 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, wid.push_back(b); //yoffset += rowHeight; - // R77 TEST - b = ADD_OD_BUTTON("Stella Options" + ELLIPSIS, kStellaOptionsCmd); - wid.push_back(b); - - b = ADD_OD_BUTTON("Developer" + ELLIPSIS, kDevelopCmd); wid.push_back(b); // Move to second column - xoffset += buttonWidth + 10; yoffset = VBORDER; + xoffset += buttonWidth + 10; yoffset = minSettings ? VBORDER + rowHeight + 8 : VBORDER; myGameInfoButton = ADD_OD_BUTTON("Game Properties" + ELLIPSIS, kInfoCmd); wid.push_back(myGameInfoButton); myCheatCodeButton = ADD_OD_BUTTON("Cheat Codes" + ELLIPSIS, kCheatCmd); #ifndef CHEATCODE_SUPPORT - myCheatCodeButton->clearFlags(WIDGET_ENABLED); + myCheatCodeButton->clearFlags(Widget::FLAG_ENABLED); #endif wid.push_back(myCheatCodeButton); @@ -122,6 +128,8 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, b = ADD_OD_BUTTON("About" + ELLIPSIS, kAboutCmd); wid.push_back(b); + buttonWidth = _font.getStringWidth(" Close ") + 20; + xoffset -= (buttonWidth + 10) / 2; b = ADD_OD_BUTTON("Close", kExitCmd); wid.push_back(b); addCancelWidget(b); @@ -132,7 +140,6 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, myInputDialog = make_unique(osystem, parent, _font, max_w, max_h); myUIDialog = make_unique(osystem, parent, _font, boss, max_w, max_h); mySnapshotDialog = make_unique(osystem, parent, _font, max_w, max_h); - myStellaOptionsDialog = make_unique(osystem, parent, _font, max_w, max_h); myDeveloperDialog = make_unique(osystem, parent, _font, max_w, max_h); myGameInfoDialog = make_unique(osystem, parent, _font, this, max_w, max_h); #ifdef CHEATCODE_SUPPORT @@ -145,13 +152,13 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, addToFocusList(wid); // Certain buttons are disabled depending on mode - if(myMode == AppMode::launcher) + if(myMode == Menu::AppMode::launcher) { - myCheatCodeButton->clearFlags(WIDGET_ENABLED); + myCheatCodeButton->clearFlags(Widget::FLAG_ENABLED); } else { - myRomAuditButton->clearFlags(WIDGET_ENABLED); + myRomAuditButton->clearFlags(Widget::FLAG_ENABLED); } } @@ -169,13 +176,13 @@ void OptionsDialog::loadConfig() switch(instance().eventHandler().state()) { case EventHandlerState::EMULATION: - myGameInfoButton->setFlags(WIDGET_ENABLED); + myGameInfoButton->setFlags(Widget::FLAG_ENABLED); break; case EventHandlerState::LAUNCHER: if(instance().launcher().selectedRomMD5() != "") - myGameInfoButton->setFlags(WIDGET_ENABLED); + myGameInfoButton->setFlags(Widget::FLAG_ENABLED); else - myGameInfoButton->clearFlags(WIDGET_ENABLED); + myGameInfoButton->clearFlags(Widget::FLAG_ENABLED); break; default: break; @@ -188,6 +195,15 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd, { switch(cmd) { + case kBasSetCmd: + // enable basic settings + instance().settings().setValue("basic_settings", true); + if (myMode != Menu::AppMode::emulator) + close(); + else + instance().eventHandler().leaveMenuMode(); + break; + case kVidCmd: { // This dialog is resizable under certain conditions, so we need @@ -257,21 +273,6 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd, break; } - case kStellaOptionsCmd: - { - // This dialog is resizable under certain conditions, so we need - // to re-create it as necessary - uInt32 w = 0, h = 0; - - if (myStellaOptionsDialog == nullptr || myStellaOptionsDialog->shouldResize(w, h)) - { - myStellaOptionsDialog = make_unique(instance(), parent(), - instance().frameBuffer().font(), w, h); - } - myStellaOptionsDialog->open(); - break; - } - case kInfoCmd: { // This dialog is resizable under certain conditions, so we need @@ -322,7 +323,7 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd, break; case kExitCmd: - if(myMode != AppMode::emulator) + if(myMode != Menu::AppMode::emulator) close(); else instance().eventHandler().leaveMenuMode(); diff --git a/src/gui/OptionsDialog.hxx b/src/gui/OptionsDialog.hxx index 80505b171..3f91ecc79 100644 --- a/src/gui/OptionsDialog.hxx +++ b/src/gui/OptionsDialog.hxx @@ -35,20 +35,16 @@ class RomAuditDialog; class HelpDialog; class AboutDialog; class LoggerDialog; - -#include "Dialog.hxx" - class DeveloperDialog; -class StellaSettingsDialog; + +#include "Menu.hxx" +#include "Dialog.hxx" class OptionsDialog : public Dialog { public: - // Current Stella mode - enum class AppMode { launcher, emulator, debugger }; - OptionsDialog(OSystem& osystem, DialogContainer& parent, GuiObject* boss, - int max_w, int max_h, AppMode mode); + int max_w, int max_h, Menu::AppMode mode); virtual ~OptionsDialog(); private: @@ -62,7 +58,6 @@ class OptionsDialog : public Dialog unique_ptr myUIDialog; unique_ptr mySnapshotDialog; unique_ptr myDeveloperDialog; - unique_ptr myStellaOptionsDialog; unique_ptr myGameInfoDialog; #ifdef CHEATCODE_SUPPORT unique_ptr myCheatCodeDialog; @@ -77,9 +72,10 @@ class OptionsDialog : public Dialog ButtonWidget* myCheatCodeButton; // Indicates if this dialog is used for global (vs. in-game) settings - AppMode myMode; + Menu::AppMode myMode; enum { + kBasSetCmd = 'BAST', kVidCmd = 'VIDO', kAudCmd = 'AUDO', kInptCmd = 'INPT', @@ -90,7 +86,6 @@ class OptionsDialog : public Dialog kCheatCmd = 'CHET', kLoggerCmd = 'LOGG', kDevelopCmd = 'DEVL', - kStellaOptionsCmd = 'STOP', kHelpCmd = 'HELP', kAboutCmd = 'ABOU', kExitCmd = 'EXIM' diff --git a/src/gui/PopUpWidget.cxx b/src/gui/PopUpWidget.cxx index 8368cba4a..e24d80cf7 100644 --- a/src/gui/PopUpWidget.cxx +++ b/src/gui/PopUpWidget.cxx @@ -45,7 +45,7 @@ PopUpWidget::PopUpWidget(GuiObject* boss, const GUI::Font& font, _labelWidth(labelWidth), _changed(false) { - _flags = WIDGET_ENABLED | WIDGET_RETAIN_FOCUS; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_RETAIN_FOCUS; _bgcolor = kDlgColor; _bgcolorhi = kDlgColor; // do not highlight the background _textcolor = kTextColor; @@ -143,14 +143,14 @@ void PopUpWidget::handleMouseWheel(int x, int y, int direction) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PopUpWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); setDirty(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PopUpWidget::handleMouseLeft() { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); setDirty(); } diff --git a/src/gui/RadioButtonWidget.cxx b/src/gui/RadioButtonWidget.cxx index 3a94d80ab..c7ae84106 100644 --- a/src/gui/RadioButtonWidget.cxx +++ b/src/gui/RadioButtonWidget.cxx @@ -91,7 +91,7 @@ RadioButtonWidget::RadioButtonWidget(GuiObject* boss, const GUI::Font& font, : CheckboxWidget(boss, font, x, y, label, cmd), myGroup(group) { - _flags = WIDGET_ENABLED; + _flags = Widget::FLAG_ENABLED; _bgcolor = _bgcolorhi = kWidColor; _editable = true; diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx index 2df8e243c..5bd2a98c9 100644 --- a/src/gui/RomAuditDialog.cxx +++ b/src/gui/RomAuditDialog.cxx @@ -36,7 +36,6 @@ RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) : Dialog(osystem, parent, font, "Audit ROMs"), - myConfirmMsg(nullptr), myMaxWidth(max_w), myMaxHeight(max_h) { diff --git a/src/gui/RomInfoWidget.cxx b/src/gui/RomInfoWidget.cxx index 3000137d5..6f2a6a1a8 100644 --- a/src/gui/RomInfoWidget.cxx +++ b/src/gui/RomInfoWidget.cxx @@ -39,7 +39,7 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font, GUI::Size(TIAConstants::viewableWidth*2, TIAConstants::viewableHeight*2) : GUI::Size(TIAConstants::viewableWidth, TIAConstants::viewableHeight)) { - _flags = WIDGET_ENABLED; + _flags = Widget::FLAG_ENABLED; _bgcolor = kDlgColor; _bgcolorlo = kBGColorLo; } diff --git a/src/gui/ScrollBarWidget.cxx b/src/gui/ScrollBarWidget.cxx index b2e032b74..de0298325 100644 --- a/src/gui/ScrollBarWidget.cxx +++ b/src/gui/ScrollBarWidget.cxx @@ -68,7 +68,7 @@ ScrollBarWidget::ScrollBarWidget(GuiObject* boss, const GUI::Font& font, _sliderPos(0), _sliderDeltaMouseDownPos(0) { - _flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_TRACK_MOUSE | Widget::FLAG_CLEARBG; _bgcolor = kWidColor; _bgcolorhi = kWidColor; } @@ -208,7 +208,7 @@ void ScrollBarWidget::checkBounds(int old_pos) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ScrollBarWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); setDirty(); } @@ -216,7 +216,7 @@ void ScrollBarWidget::handleMouseEntered() void ScrollBarWidget::handleMouseLeft() { _part = kNoPart; - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); setDirty(); } diff --git a/src/gui/StellaSettingsDialog.cxx b/src/gui/StellaSettingsDialog.cxx index e065f14f1..88dedd1e6 100644 --- a/src/gui/StellaSettingsDialog.cxx +++ b/src/gui/StellaSettingsDialog.cxx @@ -22,35 +22,43 @@ #include "ControllerDetector.hxx" #include "NTSCFilter.hxx" #include "PopUpWidget.hxx" +#include "MessageBox.hxx" #include "StellaSettingsDialog.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - StellaSettingsDialog::StellaSettingsDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font, int max_w, int max_h) - : Dialog(osystem, parent, font, "Stella settings") + const GUI::Font& font, int max_w, int max_h, Menu::AppMode mode) + : Dialog(osystem, parent, font, "Stella settings"), + myMode(mode) { - const int VGAP = 4; const int VBORDER = 8; const int HBORDER = 10; const int INDENT = 20; - const int lineHeight = font.getLineHeight(), + const int buttonHeight = font.getLineHeight() + 6, + lineHeight = font.getLineHeight(), fontWidth = font.getMaxCharWidth(); + const int VGAP = 5; int xpos, ypos; WidgetArray wid; VariantList items; // Set real dimensions - setSize(33 * fontWidth + HBORDER * 2, 15 * (lineHeight + VGAP) + _th, max_w, max_h); + setSize(33 * fontWidth + HBORDER * 2, 14 * (lineHeight + VGAP) + VGAP * 9 + 6 + _th, max_w, max_h); xpos = HBORDER; ypos = VBORDER + _th; + myAdvancedSettings = new ButtonWidget(this, font, xpos, ypos, _w - HBORDER * 2, buttonHeight, + "Switch to Advanced Settings" + ELLIPSIS, kAdvancedSettings); + ypos += lineHeight + VGAP*4; + new StaticTextWidget(this, font, xpos, ypos + 1, "Global settings:"); xpos += INDENT; ypos += lineHeight + VGAP; + addUIOptions(wid, xpos, ypos, font); ypos += VGAP * 4; addVideoOptions(wid, xpos, ypos, font); @@ -75,7 +83,7 @@ void StellaSettingsDialog::addUIOptions(WidgetArray& wid, int& xpos, int& ypos, const int VGAP = 4; const int lineHeight = font.getLineHeight(); VariantList items; - int pwidth = font.getStringWidth("Bad adjust"); + int pwidth = font.getStringWidth("Bad adjust"); // align width with other popup ypos += 1; VarList::push_back(items, "Standard", "standard"); @@ -284,15 +292,32 @@ void StellaSettingsDialog::handleCommand(CommandSender* sender, int cmd, { switch (cmd) { - case GuiObject::kOKCmd: - saveConfig(); - close(); - break; - case GuiObject::kDefaultsCmd: setDefaults(); break; + case GuiObject::kOKCmd: + saveConfig(); + [[fallthrough]]; + case GuiObject::kCloseCmd: + if (myMode != Menu::AppMode::emulator) + close(); + else + instance().eventHandler().leaveMenuMode(); + break; + + case kAdvancedSettings: + switchSettingsMode(); + break; + + case kConfirmSwitchCmd: + instance().settings().setValue("basic_settings", false); + if (myMode != Menu::AppMode::emulator) + close(); + else + instance().eventHandler().leaveMenuMode(); + break; + case kScanlinesChanged: if(myTVScanIntense->getValue() == 0) myTVScanIntense->setValueLabel("Off"); @@ -309,6 +334,26 @@ void StellaSettingsDialog::handleCommand(CommandSender* sender, int cmd, } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void StellaSettingsDialog::switchSettingsMode() +{ + StringList msg; + + msg.push_back("Warning!"); + msg.push_back(""); + msg.push_back("Advanced settings should be"); + msg.push_back("handled with care! When in"); + msg.push_back("doubt, read the manual."); + msg.push_back(""); + msg.push_back("If you are sure you want to"); + msg.push_back("proceed with the switch, click"); + msg.push_back("'OK', otherwise click 'Cancel'."); + + myConfirmMsg = make_unique(this, instance().frameBuffer().font(), msg, + _w-16, _h, kConfirmSwitchCmd, "OK", "Cancel", "Switch settings mode", false); + myConfirmMsg->show(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void StellaSettingsDialog::loadControllerProperties(const Properties& props) { @@ -321,6 +366,7 @@ void StellaSettingsDialog::loadControllerProperties(const Properties& props) switch (instance().eventHandler().state()) { case EventHandlerState::OPTIONSMENU: // game is running! + case EventHandlerState::CMDMENU: // game is running! enable = true; break; case EventHandlerState::LAUNCHER: diff --git a/src/gui/StellaSettingsDialog.hxx b/src/gui/StellaSettingsDialog.hxx index b8e2f8f1d..87c414d87 100644 --- a/src/gui/StellaSettingsDialog.hxx +++ b/src/gui/StellaSettingsDialog.hxx @@ -21,7 +21,9 @@ class PopUpWidget; #include "Props.hxx" +#include "Menu.hxx" #include "Dialog.hxx" +#include "MessageBox.hxx" namespace GUI { class Font; @@ -31,7 +33,7 @@ class StellaSettingsDialog : public Dialog { public: StellaSettingsDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font, int max_w, int max_h); + const GUI::Font& font, int max_w, int max_h, Menu::AppMode mode); virtual ~StellaSettingsDialog() = default; private: @@ -45,6 +47,9 @@ class StellaSettingsDialog : public Dialog void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + // switch to advanced settings after user confirmation + void switchSettingsMode(); + // load the properties for the controller settings void loadControllerProperties(const Properties& props); @@ -53,6 +58,9 @@ class StellaSettingsDialog : public Dialog int valueToLevel(int value); private: + // advanced settings mode: + ButtonWidget* myAdvancedSettings; + // UI theme PopUpWidget* myThemePopup; @@ -76,7 +84,14 @@ class StellaSettingsDialog : public Dialog PopUpWidget* myRightPort; StaticTextWidget* myRightPortDetected; + unique_ptr myConfirmMsg; + + // Indicates if this dialog is used for global (vs. in-game) settings + Menu::AppMode myMode; + enum { + kAdvancedSettings = 'SSad', + kConfirmSwitchCmd = 'SScf', kScanlinesChanged = 'SSsc', kPhosphorChanged = 'SSph' }; diff --git a/src/gui/StringListWidget.cxx b/src/gui/StringListWidget.cxx index 4de437571..8ce4394b1 100644 --- a/src/gui/StringListWidget.cxx +++ b/src/gui/StringListWidget.cxx @@ -43,14 +43,14 @@ void StringListWidget::setList(const StringList& list) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void StringListWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); setDirty(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void StringListWidget::handleMouseLeft() { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); setDirty(); } diff --git a/src/gui/TabWidget.cxx b/src/gui/TabWidget.cxx index 108678ac4..999ca8013 100644 --- a/src/gui/TabWidget.cxx +++ b/src/gui/TabWidget.cxx @@ -35,7 +35,7 @@ TabWidget::TabWidget(GuiObject* boss, const GUI::Font& font, { _id = 0; // For dialogs with multiple tab widgets, they should specifically // call ::setID to differentiate among them - _flags = WIDGET_ENABLED | WIDGET_CLEARBG; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG; _bgcolor = kDlgColor; _bgcolorhi = kDlgColor; _textcolor = kTextColor; @@ -219,14 +219,14 @@ void TabWidget::handleMouseDown(int x, int y, MouseButton b, int clickCount) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TabWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); setDirty(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TabWidget::handleMouseLeft() { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); setDirty(); } diff --git a/src/gui/TimeLineWidget.cxx b/src/gui/TimeLineWidget.cxx index cd69175ae..923ec7ddf 100644 --- a/src/gui/TimeLineWidget.cxx +++ b/src/gui/TimeLineWidget.cxx @@ -39,7 +39,7 @@ TimeLineWidget::TimeLineWidget(GuiObject* boss, const GUI::Font& font, _isDragging(false), _labelWidth(labelWidth) { - _flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_TRACK_MOUSE; _bgcolor = kDlgColor; _bgcolorhi = kDlgColor; diff --git a/src/gui/TimeMachineDialog.cxx b/src/gui/TimeMachineDialog.cxx index 56d0a7f08..b31870791 100644 --- a/src/gui/TimeMachineDialog.cxx +++ b/src/gui/TimeMachineDialog.cxx @@ -177,8 +177,8 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent, _w = width; // Parent determines our width (based on window size) _h = V_BORDER * 2 + rowHeight + buttonHeight + 2; - this->clearFlags(WIDGET_CLEARBG); // does only work combined with blending (0..100)! - this->clearFlags(WIDGET_BORDER); + this->clearFlags(Widget::FLAG_CLEARBG); // does only work combined with blending (0..100)! + this->clearFlags(Widget::FLAG_BORDER); xpos = H_BORDER; ypos = V_BORDER; diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 7fca1d21e..2d80617b5 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -207,7 +207,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, // All ROM settings are disabled while in game mode if(!myIsGlobal) { - romButton->clearFlags(WIDGET_ENABLED); + romButton->clearFlags(Widget::FLAG_ENABLED); myRomPath->setEditable(false); } diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index d1917b667..5598e55d0 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -321,8 +321,8 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, // Disable certain functions when we know they aren't present #ifndef WINDOWED_SUPPORT - myFullscreen->clearFlags(WIDGET_ENABLED); - myCenter->clearFlags(WIDGET_ENABLED); + myFullscreen->clearFlags(Widget::FLAG_ENABLED); + myCenter->clearFlags(Widget::FLAG_ENABLED); #endif } diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index 6889e456b..89c46189b 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -81,7 +81,7 @@ void Widget::draw() bool onTop = _boss->dialog().isOnTop(); - bool hasBorder = _flags & WIDGET_BORDER; // currently only used by Dialog widget + bool hasBorder = _flags & Widget::FLAG_BORDER; // currently only used by Dialog widget int oldX = _x, oldY = _y; // Account for our relative position in the dialog @@ -89,20 +89,20 @@ void Widget::draw() _y = getAbsY(); // Clear background (unless alpha blending is enabled) - if(_flags & WIDGET_CLEARBG) + if(_flags & Widget::FLAG_CLEARBG) { int x = _x, y = _y, w = _w, h = _h; if(hasBorder) { x++; y++; w-=2; h-=2; } - s.fillRect(x, y, w, h, !onTop ? _bgcolorlo : (_flags & WIDGET_HILITED) && isEnabled() ? _bgcolorhi : _bgcolor); + s.fillRect(x, y, w, h, !onTop ? _bgcolorlo : (_flags & Widget::FLAG_HILITED) && isEnabled() ? _bgcolorhi : _bgcolor); } // Draw border if(hasBorder) { - s.frameRect(_x, _y, _w, _h, !onTop ? kColor : (_flags & WIDGET_HILITED) && isEnabled() ? kWidColorHi : kColor); + s.frameRect(_x, _y, _w, _h, !onTop ? kColor : (_flags & Widget::FLAG_HILITED) && isEnabled() ? kWidColorHi : kColor); _x += 4; _y += 4; _w -= 8; @@ -110,7 +110,7 @@ void Widget::draw() } // Now perform the actual widget draw - drawWidget((_flags & WIDGET_HILITED) ? true : false); + drawWidget((_flags & Widget::FLAG_HILITED) ? true : false); // Restore x/y if (hasBorder) @@ -156,8 +156,8 @@ void Widget::lostFocus() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Widget::setEnabled(bool e) { - if(e) setFlags(WIDGET_ENABLED); - else clearFlags(WIDGET_ENABLED); + if(e) setFlags(Widget::FLAG_ENABLED); + else clearFlags(Widget::FLAG_ENABLED); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -311,7 +311,7 @@ StaticTextWidget::StaticTextWidget(GuiObject* boss, const GUI::Font& font, : Widget(boss, font, x, y, w, h), _align(align) { - _flags = WIDGET_ENABLED; + _flags = Widget::FLAG_ENABLED; _bgcolor = kDlgColor; _bgcolorhi = kDlgColor; _textcolor = kTextColor; @@ -373,7 +373,7 @@ ButtonWidget::ButtonWidget(GuiObject* boss, const GUI::Font& font, _bmw(0), _bmh(0) { - _flags = WIDGET_ENABLED | WIDGET_CLEARBG; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG; _bgcolor = kBtnColor; _bgcolorhi = kBtnColorHi; _bgcolorlo = kColor; @@ -416,13 +416,13 @@ ButtonWidget::ButtonWidget(GuiObject* boss, const GUI::Font& font, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ButtonWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ButtonWidget::handleMouseLeft() { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -447,7 +447,7 @@ void ButtonWidget::handleMouseUp(int x, int y, MouseButton b, int clickCount) { if(isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h) { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); sendCommand(_cmd, 0, _id); } } @@ -541,7 +541,7 @@ CheckboxWidget::CheckboxWidget(GuiObject* boss, const GUI::Font& font, _boxY(0), _textY(0) { - _flags = WIDGET_ENABLED; + _flags = Widget::FLAG_ENABLED; _bgcolor = _bgcolorhi = kWidColor; _bgcolorlo = kDlgColor; @@ -567,13 +567,13 @@ CheckboxWidget::CheckboxWidget(GuiObject* boss, const GUI::Font& font, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CheckboxWidget::handleMouseEntered() { - setFlags(WIDGET_HILITED); + setFlags(Widget::FLAG_HILITED); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CheckboxWidget::handleMouseLeft() { - clearFlags(WIDGET_HILITED); + clearFlags(Widget::FLAG_HILITED); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -677,7 +677,7 @@ SliderWidget::SliderWidget(GuiObject* boss, const GUI::Font& font, _valueLabelWidth(valueLabelWidth), _numIntervals(0) { - _flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE; + _flags = Widget::FLAG_ENABLED | Widget::FLAG_TRACK_MOUSE; _bgcolor = kDlgColor; _bgcolorhi = kDlgColor; diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index 4a89b0744..084164e87 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -34,18 +34,6 @@ namespace GUI { #include "GuiObject.hxx" #include "Font.hxx" -enum { - WIDGET_ENABLED = 1 << 0, - WIDGET_INVISIBLE = 1 << 1, - WIDGET_HILITED = 1 << 2, - WIDGET_BORDER = 1 << 3, - WIDGET_CLEARBG = 1 << 4, - WIDGET_TRACK_MOUSE = 1 << 5, - WIDGET_RETAIN_FOCUS = 1 << 6, - WIDGET_WANTS_TAB = 1 << 7, - WIDGET_WANTS_RAWDATA = 1 << 8 -}; - /** This is the base class for all widgets. @@ -55,6 +43,19 @@ class Widget : public GuiObject { friend class Dialog; + public: + enum : uInt32 { + FLAG_ENABLED = 1 << 0, + FLAG_INVISIBLE = 1 << 1, + FLAG_HILITED = 1 << 2, + FLAG_BORDER = 1 << 3, + FLAG_CLEARBG = 1 << 4, + FLAG_TRACK_MOUSE = 1 << 5, + FLAG_RETAIN_FOCUS = 1 << 6, + FLAG_WANTS_TAB = 1 << 7, + FLAG_WANTS_RAWDATA = 1 << 8 + }; + public: Widget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h); virtual ~Widget(); @@ -91,21 +92,21 @@ class Widget : public GuiObject Vec::append(_focusList, list); } - /** Set/clear WIDGET_ENABLED flag */ + /** Set/clear FLAG_ENABLED */ void setEnabled(bool e); - void setFlags(int flags) { _flags |= flags; setDirty(); } - void clearFlags(int flags) { _flags &= ~flags; setDirty(); } - int getFlags() const { return _flags; } + void setFlags(uInt32 flags) { _flags |= flags; setDirty(); } + void clearFlags(uInt32 flags) { _flags &= ~flags; setDirty(); } + uInt32 getFlags() const { return _flags; } - bool isEnabled() const { return _flags & WIDGET_ENABLED; } - bool isVisible() const override { return !(_flags & WIDGET_INVISIBLE); } - virtual bool wantsFocus() const { return _flags & WIDGET_RETAIN_FOCUS; } - bool wantsTab() const { return _flags & WIDGET_WANTS_TAB; } - bool wantsRaw() const { return _flags & WIDGET_WANTS_RAWDATA; } + bool isEnabled() const { return _flags & FLAG_ENABLED; } + bool isVisible() const override { return !(_flags & FLAG_INVISIBLE); } + virtual bool wantsFocus() const { return _flags & FLAG_RETAIN_FOCUS; } + bool wantsTab() const { return _flags & FLAG_WANTS_TAB; } + bool wantsRaw() const { return _flags & FLAG_WANTS_RAWDATA; } - void setID(int id) { _id = id; } - int getID() const { return _id; } + void setID(uInt32 id) { _id = id; } + uInt32 getID() const { return _id; } virtual const GUI::Font& font() const { return _font; } @@ -135,8 +136,8 @@ class Widget : public GuiObject GuiObject* _boss; const GUI::Font& _font; Widget* _next; - int _id; - int _flags; + uInt32 _id; + uInt32 _flags; bool _hasFocus; int _fontWidth; int _fontHeight; diff --git a/src/gui/module.mk b/src/gui/module.mk index 466ad3670..68bf66af8 100644 --- a/src/gui/module.mk +++ b/src/gui/module.mk @@ -31,6 +31,7 @@ MODULE_OBJS := \ src/gui/LoggerDialog.o \ src/gui/Menu.o \ src/gui/MessageBox.o \ + src/gui/MinUICommandDialog.o\ src/gui/OptionsDialog.o \ src/gui/PopUpWidget.o \ src/gui/ProgressDialog.o \ diff --git a/src/libretro/Makefile.common b/src/libretro/Makefile.common index 60e1b9d52..a69062d6f 100644 --- a/src/libretro/Makefile.common +++ b/src/libretro/Makefile.common @@ -79,6 +79,7 @@ SOURCES_CXX := \ $(CORE_DIR)/gui/FileListWidget.cxx \ $(CORE_DIR)/gui/JoystickDialog.cxx \ $(CORE_DIR)/gui/LoggerDialog.cxx \ + $(CORE_DIR)/gui/MinUICommandDialog.cxx \ $(CORE_DIR)/gui/RadioButtonWidget.cxx \ $(CORE_DIR)/gui/SnapshotDialog.cxx \ $(CORE_DIR)/gui/TimeLineWidget.cxx \ diff --git a/src/libretro/Stella.vcxproj b/src/libretro/Stella.vcxproj index 2b199effd..8c07ef75c 100644 --- a/src/libretro/Stella.vcxproj +++ b/src/libretro/Stella.vcxproj @@ -210,6 +210,7 @@ + @@ -401,6 +402,7 @@ + diff --git a/src/libretro/StellaLIBRETRO.cxx b/src/libretro/StellaLIBRETRO.cxx index 0e6a9bacf..6dfb4d36f 100644 --- a/src/libretro/StellaLIBRETRO.cxx +++ b/src/libretro/StellaLIBRETRO.cxx @@ -41,7 +41,7 @@ StellaLIBRETRO::StellaLIBRETRO() video_aspect_pal = 0; video_palette = "standard"; - video_filter = NTSCFilter::Preset::OFF; + video_filter = 0; video_ready = false; audio_samples = 0; @@ -108,7 +108,7 @@ bool StellaLIBRETRO::create(bool logging) //fastscbios // Fast loading of Supercharger BIOS - settings.setValue("tv.filter", static_cast(video_filter)); + settings.setValue("tv.filter", video_filter); settings.setValue("tv.phosphor", video_phosphor); settings.setValue("tv.phosblend", video_phosphor_blend); @@ -131,6 +131,7 @@ bool StellaLIBRETRO::create(bool logging) if(myOSystem->createConsole(rom) != EmptyString) return false; + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if(video_phosphor == "never") setVideoPhosphor(1, video_phosphor_blend); @@ -157,6 +158,10 @@ void StellaLIBRETRO::destroy() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void StellaLIBRETRO::runFrame() { + // write ram updates + for(int lcv = 0; lcv <= 127; lcv++) + myOSystem->console().system().m6532().poke(lcv | 0x80, system_ram[lcv]); + // poll input right at vsync updateInput(); @@ -166,7 +171,8 @@ void StellaLIBRETRO::runFrame() // drain generated audio updateAudio(); - // give user time to respond + // refresh ram copy + memcpy(system_ram, myOSystem->console().system().m6532().getRAM(), 128); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -250,30 +256,57 @@ size_t StellaLIBRETRO::getStateSize() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -float StellaLIBRETRO::getVideoAspect() +float StellaLIBRETRO::getVideoAspectPar() { - uInt32 width = myOSystem->console().tia().width() * 2; float par; if (getVideoNTSC()) { - if (!video_aspect_ntsc) - // non-interlace square pixel clock -- 1.0 pixel @ color burst -- double-width pixels - par = (6.1363635f / 3.579545454f) / 2; - else - par = video_aspect_ntsc / 100.0; + if (!video_aspect_ntsc) + { + if (!video_filter) + { + // non-interlace square pixel clock -- 1.0 pixel @ color burst -- double-width pixels + par = (6.1363635f / 3.579545454f) / 2.0; + } + else + { + // blargg filter + par = 1.0; + } + } + else + par = video_aspect_ntsc / 100.0; } else { - if (!video_aspect_pal) - // non-interlace square pixel clock -- 0.8 pixel @ color burst -- double-width pixels - par = (7.3750000f / (4.43361875f * 4/5)) / 2; - else - par = video_aspect_pal / 100.0; + if (!video_aspect_pal) + { + if (!video_filter) + { + // non-interlace square pixel clock -- 0.8 pixel @ color burst -- double-width pixels + par = (7.3750000f / (4.43361875f * 4.0f / 5.0f)) / 2.0f; + } + else + { + // blargg filter + par = 1.0; + } + } + else + par = video_aspect_pal / 100.0; } + + return par; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +float StellaLIBRETRO::getVideoAspect() +{ + uInt32 width = myOSystem->console().tia().width() * 2; // display aspect ratio - return (width * par) / getVideoHeight(); + return (width * getVideoAspectPar()) / getVideoHeight(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -322,13 +355,13 @@ void StellaLIBRETRO::setConsoleFormat(uInt32 mode) { switch(mode) { - case 0: console_format = "AUTO"; break; - case 1: console_format = "NTSC"; break; - case 2: console_format = "PAL"; break; - case 3: console_format = "SECAM"; break; - case 4: console_format = "NTSC50"; break; - case 5: console_format = "PAL60"; break; - case 6: console_format = "SECAM60"; break; + case 0: console_format = "AUTO"; break; + case 1: console_format = "NTSC"; break; + case 2: console_format = "PAL"; break; + case 3: console_format = "SECAM"; break; + case 4: console_format = "NTSC50"; break; + case 5: console_format = "PAL60"; break; + case 6: console_format = "SECAM60"; break; } if (system_ready) @@ -338,7 +371,9 @@ void StellaLIBRETRO::setConsoleFormat(uInt32 mode) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void StellaLIBRETRO::setVideoFilter(uInt32 mode) { - if (system_ready && mode <= 5) + video_filter = mode; + + if (system_ready) { myOSystem->settings().setValue("tv.filter", mode); myOSystem->frameBuffer().tiaSurface().setNTSC(static_cast(mode)); @@ -350,9 +385,9 @@ void StellaLIBRETRO::setVideoPalette(uInt32 mode) { switch (mode) { - case 0: video_palette = "standard"; break; - case 1: video_palette = "z26"; break; - case 2: video_palette = "custom"; break; + case 0: video_palette = "standard"; break; + case 1: video_palette = "z26"; break; + case 2: video_palette = "custom"; break; } if (system_ready) @@ -367,9 +402,9 @@ void StellaLIBRETRO::setVideoPhosphor(uInt32 mode, uInt32 blend) { switch (mode) { - case 0: video_phosphor = "byrom"; break; - case 1: video_phosphor = "never"; break; - case 2: video_phosphor = "always"; break; + case 0: video_phosphor = "byrom"; break; + case 1: video_phosphor = "never"; break; + case 2: video_phosphor = "always"; break; } video_phosphor_blend = blend; @@ -381,9 +416,9 @@ void StellaLIBRETRO::setVideoPhosphor(uInt32 mode, uInt32 blend) switch (mode) { - case 0: myOSystem->frameBuffer().tiaSurface().enablePhosphor(phosphor_default, blend); break; - case 1: myOSystem->frameBuffer().tiaSurface().enablePhosphor(false, blend); break; - case 2: myOSystem->frameBuffer().tiaSurface().enablePhosphor(true, blend); break; + case 0: myOSystem->frameBuffer().tiaSurface().enablePhosphor(phosphor_default, blend); break; + case 1: myOSystem->frameBuffer().tiaSurface().enablePhosphor(false, blend); break; + case 2: myOSystem->frameBuffer().tiaSurface().enablePhosphor(true, blend); break; } } } @@ -393,9 +428,9 @@ void StellaLIBRETRO::setAudioStereo(int mode) { switch (mode) { - case 0: audio_mode = "byrom"; break; - case 1: audio_mode = "mono"; break; - case 2: audio_mode = "stereo"; break; + case 0: audio_mode = "byrom"; break; + case 1: audio_mode = "mono"; break; + case 2: audio_mode = "stereo"; break; } if (system_ready) diff --git a/src/libretro/StellaLIBRETRO.hxx b/src/libretro/StellaLIBRETRO.hxx index 3de7cc585..c57a18344 100644 --- a/src/libretro/StellaLIBRETRO.hxx +++ b/src/libretro/StellaLIBRETRO.hxx @@ -23,9 +23,11 @@ #include "Console.hxx" #include "ConsoleTiming.hxx" +#include "Control.hxx" #include "EmulationTiming.hxx" #include "EventHandler.hxx" #include "M6532.hxx" +#include "Paddles.hxx" #include "System.hxx" #include "TIA.hxx" #include "TIASurface.hxx" @@ -60,13 +62,14 @@ class StellaLIBRETRO uInt32 getROMSize() { return rom_size; } uInt32 getROMMax() { return 512 * 1024; } - //uInt8* getRAM() { return myOSystem->console().system().m6532().getRAM(); } - //uInt32 getRAMSize() { return 128; } + uInt8* getRAM() { return system_ram; } + uInt32 getRAMSize() { return 128; } size_t getStateSize(); bool getConsoleNTSC() { return console_timing == ConsoleTiming::ntsc; } + float getVideoAspectPar(); float getVideoAspect(); bool getVideoNTSC(); float getVideoRate() { return getVideoNTSC() ? 60.0 : 50.0; } @@ -108,6 +111,17 @@ class StellaLIBRETRO void setInputEvent(Event::Type type, Int32 state) { myOSystem->eventHandler().handleEvent(type, state); } + Controller::Type getLeftControllerType() { return myOSystem->console().leftController().type(); } + Controller::Type getRightControllerType() { return myOSystem->console().rightController().type(); } + + void setPaddleJoypadSensitivity(int sensitivity) + { + if(getLeftControllerType() == Controller::Type::Paddles) + static_cast(myOSystem->console().leftController()).setDigitalSensitivity(sensitivity); + if(getRightControllerType() == Controller::Type::Paddles) + static_cast(myOSystem->console().rightController()).setDigitalSensitivity(sensitivity); + } + protected: void updateInput(); void updateVideo(); @@ -136,8 +150,10 @@ class StellaLIBRETRO unique_ptr audio_buffer; uInt32 audio_samples; - // (31440 rate / 50 Hz) * 16-bit stereo * 1.25x padding - static const uInt32 audio_buffer_max = (31440 / 50 * 4 * 5) / 4; + // (31440 rate / 50 Hz) * 16-bit stereo * 1.25x padding + const uInt32 audio_buffer_max = (31440 / 50 * 4 * 5) / 4; + + uInt8 system_ram[128]; private: string video_palette; @@ -146,7 +162,7 @@ class StellaLIBRETRO uInt32 video_aspect_ntsc; uInt32 video_aspect_pal; - NTSCFilter::Preset video_filter; + uInt32 video_filter; string audio_mode; diff --git a/src/libretro/libretro.cxx b/src/libretro/libretro.cxx index ca80c0216..779fb430b 100644 --- a/src/libretro/libretro.cxx +++ b/src/libretro/libretro.cxx @@ -32,10 +32,14 @@ static struct retro_system_av_info g_av_info; static int setting_ntsc, setting_pal; static int setting_stereo, setting_filter, setting_palette; static int setting_phosphor, setting_console, setting_phosphor_blend; +static int stella_paddle_joypad_sensitivity; +static int setting_crop_hoverscan, crop_left; static bool system_reset; -static unsigned input_devices[2]; +static unsigned input_devices[4]; +static Controller::Type input_type[2]; + // TODO input: // https://github.com/libretro/blueMSX-libretro/blob/master/libretro.c @@ -58,17 +62,68 @@ static void update_input() #define EVENT stella.setInputEvent - EVENT(Event::JoystickZeroUp, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP)); - EVENT(Event::JoystickZeroDown, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)); - EVENT(Event::JoystickZeroLeft, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); - EVENT(Event::JoystickZeroRight, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); - EVENT(Event::JoystickZeroFire, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); + switch(input_type[0]) + { + case Controller::Type::BoosterGrip: + EVENT(Event::JoystickZeroFire5, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A)); + EVENT(Event::JoystickZeroFire9, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y)); + // Fallthrough + + case Controller::Type::Joystick: + default: + EVENT(Event::JoystickZeroUp, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP)); + EVENT(Event::JoystickZeroDown, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)); + // Fallthrough + + case Controller::Type::Driving: + EVENT(Event::JoystickZeroLeft, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); + EVENT(Event::JoystickZeroRight, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); + EVENT(Event::JoystickZeroFire, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); + break; + + case Controller::Type::Paddles: + EVENT(Event::PaddleZeroIncrease, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); + EVENT(Event::PaddleZeroDecrease, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); + EVENT(Event::PaddleZeroFire, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); + //WIP = Event::PaddleZeroAnalog + + EVENT(Event::PaddleOneIncrease, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); + EVENT(Event::PaddleOneDecrease, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); + EVENT(Event::PaddleOneFire, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); + break; + } + + + switch(input_type[1]) + { + case Controller::Type::BoosterGrip: + EVENT(Event::JoystickOneFire5, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A)); + EVENT(Event::JoystickOneFire9, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y)); + // Fallthrough + + case Controller::Type::Joystick: + default: + EVENT(Event::JoystickOneUp, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP)); + EVENT(Event::JoystickOneDown, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)); + // Fallthrough + + case Controller::Type::Driving: + EVENT(Event::JoystickOneLeft, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); + EVENT(Event::JoystickOneRight, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); + EVENT(Event::JoystickOneFire, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); + break; + + case Controller::Type::Paddles: + EVENT(Event::PaddleTwoIncrease, input_state_cb(2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); + EVENT(Event::PaddleTwoDecrease, input_state_cb(2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); + EVENT(Event::PaddleTwoFire, input_state_cb(2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); + + EVENT(Event::PaddleThreeIncrease, input_state_cb(3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); + EVENT(Event::PaddleThreeDecrease, input_state_cb(3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); + EVENT(Event::PaddleThreeFire, input_state_cb(3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); + break; + } - EVENT(Event::JoystickOneUp, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP)); - EVENT(Event::JoystickOneDown, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)); - EVENT(Event::JoystickOneLeft, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); - EVENT(Event::JoystickOneRight, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); - EVENT(Event::JoystickOneFire, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); EVENT(Event::ConsoleLeftDiffA, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L)); EVENT(Event::ConsoleLeftDiffB, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2)); @@ -112,7 +167,7 @@ static void update_variables(bool init = false) #define RETRO_GET(x) \ var.key = x; \ var.value = NULL; \ - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) + if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) RETRO_GET("stella_filter") { @@ -133,6 +188,13 @@ static void update_variables(bool init = false) } } + RETRO_GET("stella_crop_hoverscan") + { + setting_crop_hoverscan = !strcmp(var.value, "enabled"); + + geometry_update = true; + } + RETRO_GET("stella_ntsc_aspect") { int value = 0; @@ -246,9 +308,25 @@ static void update_variables(bool init = false) setting_phosphor_blend = value; } } + + RETRO_GET("stella_paddle_joypad_sensitivity") + { + int value = 0; + + value = atoi(var.value); + + if(stella_paddle_joypad_sensitivity != value) + { + if(!init) stella.setPaddleJoypadSensitivity(value); + + stella_paddle_joypad_sensitivity = value; + } + } if(!init && !system_reset) { + crop_left = setting_crop_hoverscan ? (stella.getVideoZoom() == 2 ? 26 : 8) : 0; + if(geometry_update) update_geometry(); } @@ -261,16 +339,22 @@ static bool reset_system() // clean restart stella.destroy(); - // apply libretro settings first + // apply pre-boot settings first update_variables(true); // start system if(!stella.create(log_cb ? true : false)) return false; - // reset libretro window - update_geometry(); + // get auto-detect controllers + input_type[0] = stella.getLeftControllerType(); + input_type[1] = stella.getRightControllerType(); + stella.setPaddleJoypadSensitivity(stella_paddle_joypad_sensitivity); system_reset = false; + + // reset libretro window, apply post-boot settings + update_variables(false); + return true; } @@ -316,41 +400,41 @@ void retro_get_system_av_info(struct retro_system_av_info *info) info->timing.fps = stella.getVideoRate(); info->timing.sample_rate = stella.getAudioRate(); - info->geometry.base_width = stella.getRenderWidth(); + info->geometry.base_width = stella.getRenderWidth() - crop_left * (stella.getVideoZoom() == 1 ? 2 : 1); info->geometry.base_height = stella.getRenderHeight(); info->geometry.max_width = stella.getVideoWidthMax(); info->geometry.max_height = stella.getVideoHeightMax(); - info->geometry.aspect_ratio = stella.getVideoAspect(); + info->geometry.aspect_ratio = stella.getVideoAspectPar() * (float) info->geometry.base_width / (float) info->geometry.base_height; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void retro_set_controller_port_device(unsigned port, unsigned device) { - if(port < 2) + if(port < 4) { switch (device) { - case RETRO_DEVICE_NONE: - input_devices[port] = RETRO_DEVICE_NONE; - break; + case RETRO_DEVICE_NONE: + input_devices[port] = RETRO_DEVICE_NONE; + break; - case RETRO_DEVICE_JOYPAD: - input_devices[port] = RETRO_DEVICE_JOYPAD; - break; + case RETRO_DEVICE_JOYPAD: + input_devices[port] = RETRO_DEVICE_JOYPAD; + break; - case RETRO_DEVICE_MOUSE: - input_devices[port] = RETRO_DEVICE_MOUSE; - break; + case RETRO_DEVICE_MOUSE: + input_devices[port] = RETRO_DEVICE_MOUSE; + break; - case RETRO_DEVICE_KEYBOARD: - input_devices[port] = RETRO_DEVICE_KEYBOARD; - break; + case RETRO_DEVICE_KEYBOARD: + input_devices[port] = RETRO_DEVICE_KEYBOARD; + break; - default: - if (log_cb) log_cb(RETRO_LOG_ERROR, "%s\n", "[libretro]: Invalid device, setting type to RETRO_DEVICE_JOYPAD ..."); - input_devices[port] = RETRO_DEVICE_JOYPAD; + default: + if (log_cb) log_cb(RETRO_LOG_ERROR, "%s\n", "[libretro]: Invalid device, setting type to RETRO_DEVICE_JOYPAD ..."); + input_devices[port] = RETRO_DEVICE_JOYPAD; } } } @@ -362,14 +446,16 @@ void retro_set_environment(retro_environment_t cb) struct retro_variable variables[] = { // Adding more variables and rearranging them is safe. - { "stella_console", "Console display; auto|ntsc|pal|secam|ntsc50|pal60|secam60"}, - { "stella_filter", "TV effects; disabled|composite|s-video|rgb|badly adjusted"}, - { "stella_ntsc_aspect", "NTSC aspect %; par|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85"}, - { "stella_pal_aspect", "PAL aspect %; par|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103"}, - { "stella_stereo", "Stereo sound; auto|off|on"}, - { "stella_palette", "Palette colors; standard|z26"}, - { "stella_phosphor", "Phosphor mode; auto|off|on"}, - { "stella_phosphor_blend", "Phosphor blend %; 60|65|70|75|80|85|90|95|100|0|5|10|15|20|25|30|35|40|45|50|55"}, + { "stella_console", "Console display; auto|ntsc|pal|secam|ntsc50|pal60|secam60" }, + { "stella_filter", "TV effects; disabled|composite|s-video|rgb|badly adjusted" }, + { "stella_ntsc_aspect", "NTSC aspect %; par|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85" }, + { "stella_pal_aspect", "PAL aspect %; par|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103" }, + { "stella_crop_hoverscan", "Crop horizontal overscan; disabled|enabled" }, + { "stella_stereo", "Stereo sound; auto|off|on" }, + { "stella_palette", "Palette colors; standard|z26" }, + { "stella_phosphor", "Phosphor mode; auto|off|on" }, + { "stella_phosphor_blend", "Phosphor blend %; 60|65|70|75|80|85|90|95|100|0|5|10|15|20|25|30|35|40|45|50|55" }, + { "stella_paddle_joypad_sensitivity", "Paddle joypad sensitivity; 3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|1|2" }, { NULL, NULL }, }; @@ -399,6 +485,8 @@ bool retro_load_game(const struct retro_game_info *info) { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Fire" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Trigger" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Booster" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Left Difficulty A" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "Left Difficulty B" }, @@ -414,6 +502,16 @@ bool retro_load_game(const struct retro_game_info *info) { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Fire" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Trigger" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Booster" }, + + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Fire" }, + + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Fire" }, { 0 }, }; @@ -474,7 +572,7 @@ void retro_run() //printf("retro_run - %d %d %d - %d\n", stella.getVideoWidth(), stella.getVideoHeight(), stella.getVideoPitch(), stella.getAudioSize() ); if(stella.getVideoReady()) - video_cb(stella.getVideoBuffer(), stella.getVideoWidth(), stella.getVideoHeight(), stella.getVideoPitch()); + video_cb(reinterpret_cast(stella.getVideoBuffer()) + crop_left, stella.getVideoWidth() - crop_left, stella.getVideoHeight(), stella.getVideoPitch()); if(stella.getAudioReady()) audio_batch_cb(stella.getAudioBuffer(), stella.getAudioSize()); @@ -515,8 +613,11 @@ void *retro_get_memory_data(unsigned id) { switch (id) { - //case RETRO_MEMORY_SYSTEM_RAM: return stella.getRAM(); - default: return NULL; + case RETRO_MEMORY_SYSTEM_RAM: + return stella.getRAM(); + + default: + return NULL; } } @@ -525,8 +626,11 @@ size_t retro_get_memory_size(unsigned id) { switch (id) { - //case RETRO_MEMORY_SYSTEM_RAM: return stella.getRAMSize(); - default: return 0; + case RETRO_MEMORY_SYSTEM_RAM: + return stella.getRAMSize(); + + default: + return 0; } } diff --git a/src/macos/stella.xcodeproj/project.pbxproj b/src/macos/stella.xcodeproj/project.pbxproj index 7da168caa..32b88cc9a 100644 --- a/src/macos/stella.xcodeproj/project.pbxproj +++ b/src/macos/stella.xcodeproj/project.pbxproj @@ -233,6 +233,8 @@ DC21E5C021CA903E007D0E1A /* OSystemMACOS.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC21E5BA21CA903E007D0E1A /* OSystemMACOS.hxx */; }; DC21E5C121CA903E007D0E1A /* SerialPortMACOS.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC21E5BB21CA903E007D0E1A /* SerialPortMACOS.cxx */; }; DC21E5C221CA903E007D0E1A /* SerialPortMACOS.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC21E5BC21CA903E007D0E1A /* SerialPortMACOS.hxx */; }; + DC2410E32274BDA8007A4CBF /* MinUICommandDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2410E12274BDA7007A4CBF /* MinUICommandDialog.hxx */; }; + DC2410E42274BDA8007A4CBF /* MinUICommandDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2410E22274BDA8007A4CBF /* MinUICommandDialog.cxx */; }; DC2874071F8F2278004BF21A /* TrapArray.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2874061F8F2278004BF21A /* TrapArray.hxx */; }; DC2AADAE194F389C0026C7A4 /* CartDASH.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */; }; DC2AADAF194F389C0026C7A4 /* CartDASH.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */; }; @@ -945,6 +947,8 @@ DC21E5BA21CA903E007D0E1A /* OSystemMACOS.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OSystemMACOS.hxx; sourceTree = SOURCE_ROOT; }; DC21E5BB21CA903E007D0E1A /* SerialPortMACOS.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SerialPortMACOS.cxx; sourceTree = SOURCE_ROOT; }; DC21E5BC21CA903E007D0E1A /* SerialPortMACOS.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SerialPortMACOS.hxx; sourceTree = SOURCE_ROOT; }; + DC2410E12274BDA7007A4CBF /* MinUICommandDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MinUICommandDialog.hxx; sourceTree = ""; }; + DC2410E22274BDA8007A4CBF /* MinUICommandDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MinUICommandDialog.cxx; sourceTree = ""; }; DC2874061F8F2278004BF21A /* TrapArray.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TrapArray.hxx; sourceTree = ""; }; DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDASH.cxx; sourceTree = ""; }; DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDASH.hxx; sourceTree = ""; }; @@ -1997,6 +2001,8 @@ 2DDBEAC3084578BF00812C11 /* Menu.hxx */, DC98F35411F5B56200AA520F /* MessageBox.cxx */, DC98F35511F5B56200AA520F /* MessageBox.hxx */, + DC2410E22274BDA8007A4CBF /* MinUICommandDialog.cxx */, + DC2410E12274BDA7007A4CBF /* MinUICommandDialog.hxx */, 2DDBEAC4084578BF00812C11 /* OptionsDialog.cxx */, 2DDBEAC5084578BF00812C11 /* OptionsDialog.hxx */, 2DDBEAC6084578BF00812C11 /* PopUpWidget.cxx */, @@ -2566,6 +2572,7 @@ DC676A4A1729A0B000E4E73D /* CartCTYWidget.hxx in Headers */, DC676A4C1729A0B000E4E73D /* CartDPCPlusWidget.hxx in Headers */, DC676A4E1729A0B000E4E73D /* CartDPCWidget.hxx in Headers */, + DC2410E32274BDA8007A4CBF /* MinUICommandDialog.hxx in Headers */, DCCA26B31FA64D5E000EE4D8 /* AbstractFrameManager.hxx in Headers */, DC3EE8631E2C0E6D00905161 /* inffast.h in Headers */, DC676A501729A0B000E4E73D /* CartE0Widget.hxx in Headers */, @@ -2808,6 +2815,7 @@ 2D9174CF09BA90380026E9FF /* CpuDebug.cxx in Sources */, 2D9174F109BA90380026E9FF /* InputTextDialog.cxx in Sources */, DC6DC920205DB879004A5FC3 /* PJoystickHandler.cxx in Sources */, + DC2410E42274BDA8007A4CBF /* MinUICommandDialog.cxx in Sources */, DC74E5C6198AF12700F37E36 /* CartDASHWidget.cxx in Sources */, 2D9174F209BA90380026E9FF /* CheckListWidget.cxx in Sources */, 2D9174F309BA90380026E9FF /* StringListWidget.cxx in Sources */, diff --git a/src/tools/evdev-joystick/Makefile b/src/tools/evdev-joystick/Makefile index 2e878144a..32864e921 100644 --- a/src/tools/evdev-joystick/Makefile +++ b/src/tools/evdev-joystick/Makefile @@ -1,7 +1,7 @@ all : evdev-joystick evdev-joystick: evdev-joystick.c - gcc -Wall -O2 -o evdev-joystick evdev-joystick.c + $(CC) -Wall -O2 -o evdev-joystick evdev-joystick.c install: evdev-joystick 80-stelladaptor-joystick.rules install -s evdev-joystick /usr/local/bin/ diff --git a/src/tools/evdev-joystick/evdev-joystick.c b/src/tools/evdev-joystick/evdev-joystick.c index 5f37c75ec..bd42e9de9 100644 --- a/src/tools/evdev-joystick/evdev-joystick.c +++ b/src/tools/evdev-joystick/evdev-joystick.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -32,16 +33,20 @@ */ #define test_bit(bit, array) (array[bit/8] & (1<<(bit%8))) -/* The default location for evdev devices in Linux */ +// The default location for evdev devices in Linux #define EVDEV_DIR "/dev/input/by-id/" -/* Function signatures; see actual functions for documentation */ +//////////////////////////////////////////////////////////////// +// Function signatures; see actual functions for documentation void help(void); void listDevices(void); void printAxisType(int i); int showCalibration(const char* const evdev); -int setDeadzoneAndFuzz(const char* const evdev, int axisindex, - __s32 deadzonevalue, __s32 fuzzvalue); +int setAxisInfo(const char* evdev, int axisindex, + __s32 minvalue, __s32 maxvalue, + __s32 deadzonevalue, __s32 fuzzvalue); +//////////////////////////////////////////////////////////////// + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void help(void) @@ -51,6 +56,8 @@ void help(void) " --listdevs, --l List all joystick devices found\n" " --showcal, --s [path] Show current calibration for joystick device\n" " --evdev, --e [path] Set the joystick device to modify\n" + " --minimum, --m [val] Change minimum for current joystick\n" + " --maximum, --M [val] Change maximum for current joystick\n" " --deadzone, --d [val] Change deadzone for current joystick\n" " --fuzz, --f [val] Change fuzz for current joystick\n" " --axis, --a [val] The axis to modify for current joystick (by default, all axes)\n" @@ -61,18 +68,21 @@ void help(void) "To set the deadzone values:\n" " evdev-joystick [ --e /path/to/event/device/file --d deadzone_value [ --a axis_index ] ]\n" "\n" + "To set the minimum and maximum range values:\n" + " evdev-joystick [ --e /path/to/event/device/file --m minimum_value --M maximum_value [ --a axis_index ] ]\n" + "\n" "Example:\n" "\n" "I want to see the calibration values of my event managed joystick:\n" " evdev-joystick --s /dev/input/event6\n" "\n" "Supported Absolute axes:\n" - " Absolute axis 0x00 (0) (X Axis) (min: 0, max: 16383, flatness: 1023 (=6.24%), fuzz: 63)\n" - " Absolute axis 0x01 (1) (Y Axis) (min: 0, max: 255, flatness: 15 (=5.88%), fuzz: 0)\n" - " Absolute axis 0x02 (2) (Z Axis) (min: 0, max: 255, flatness: 15 (=5.88%), fuzz: 0)\n" - " Absolute axis 0x05 (5) (Z Rate Axis) (min: 0, max: 255, flatness: 15 (=5.88%), fuzz: 0)\n" - " Absolute axis 0x10 (16) (Hat zero, x axis) (min: -1, max: 1, flatness: 0 (=0.00%), fuzz: 0)\n" - " Absolute axis 0x11 (17) (Hat zero, y axis) (min: -1, max: 1, flatness: 0 (=0.00%), fuzz: 0)\n" + " Absolute axis 0x00 (0) (X Axis) (value: 387, min: 0, max: 16383, flatness: 1023 (=6.24%), fuzz: 63)\n" + " Absolute axis 0x01 (1) (Y Axis) (value: 216, min: 0, max: 255, flatness: 15 (=5.88%), fuzz: 0)\n" + " Absolute axis 0x02 (2) (Z Axis) (value: 0, min: 0, max: 255, flatness: 15 (=5.88%), fuzz: 0)\n" + " Absolute axis 0x05 (5) (Z Rate Axis) (value: 101, min: 0, max: 255, flatness: 15 (=5.88%), fuzz: 0)\n" + " Absolute axis 0x10 (16) (Hat zero, x axis) (value: 0, min: -1, max: 1, flatness: 0 (=0.00%), fuzz: 0)\n" + " Absolute axis 0x11 (17) (Hat zero, y axis) (value: 0, min: -1, max: 1, flatness: 0 (=0.00%), fuzz: 0)\n" "\n" "I want to get rid of the deadzone on all axes on my joystick:\n" " evdev-joystick --e /dev/input/event6 --d 0\n" @@ -167,10 +177,10 @@ int showCalibration(const char* const evdev) if(ioctl(fd, EVIOCGABS(axisindex), &abs_features)) perror("evdev EVIOCGABS ioctl"); - percent_deadzone = (double)(abs_features.flat * 100.0 / abs_features.maximum); - printf("(min: %d, max: %d, flatness: %d (=%.2f%%), fuzz: %d)\n", - abs_features.minimum, abs_features.maximum, abs_features.flat, - percent_deadzone, abs_features.fuzz); + percent_deadzone = (double)abs_features.flat * 100 / (double)abs_features.maximum; + printf("(value: %d, min: %d, max: %d, flatness: %d (=%.2f%%), fuzz: %d)\n", + abs_features.value, abs_features.minimum, abs_features.maximum, + abs_features.flat, percent_deadzone, abs_features.fuzz); } } @@ -179,8 +189,9 @@ int showCalibration(const char* const evdev) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int setDeadzoneAndFuzz(const char* const evdev, int axisindex, - __s32 deadzonevalue, __s32 fuzzvalue) +int setAxisInfo(const char* evdev, int axisindex, + __s32 minvalue, __s32 maxvalue, + __s32 deadzonevalue, __s32 fuzzvalue) { int fd = -1; uint8_t abs_bitmask[ABS_MAX/8 + 1]; @@ -218,7 +229,19 @@ int setDeadzoneAndFuzz(const char* const evdev, int axisindex, return 1; } - if(deadzonevalue != -1) + if(minvalue != INT_MIN) + { + printf("Setting min value to : %d\n", minvalue); + abs_features.minimum = minvalue; + } + + if(maxvalue != INT_MIN) + { + printf("Setting max value to : %d\n", maxvalue); + abs_features.maximum = maxvalue; + } + + if(deadzonevalue != INT_MIN) { if(deadzonevalue < abs_features.minimum || deadzonevalue > abs_features.maximum ) @@ -232,7 +255,7 @@ int setDeadzoneAndFuzz(const char* const evdev, int axisindex, abs_features.flat = deadzonevalue; } - if(fuzzvalue != -1) + if(fuzzvalue != INT_MIN) { if(fuzzvalue < abs_features.minimum || fuzzvalue > abs_features.maximum ) @@ -256,10 +279,10 @@ int setDeadzoneAndFuzz(const char* const evdev, int axisindex, perror("evdev EVIOCGABS ioctl"); return 1; } - percent_deadzone = (double)(abs_features.flat * 100.0 / abs_features.maximum); - printf(" (min: %d, max: %d, flatness: %d (=%.2f%%), fuzz: %d)\n", - abs_features.minimum, abs_features.maximum, abs_features.flat, - percent_deadzone, abs_features.fuzz); + percent_deadzone = (double)abs_features.flat * 100 / (double)abs_features.maximum; + printf(" (value: %d, min: %d, max: %d, flatness: %d (=%.2f%%), fuzz: %d)\n", + abs_features.value, abs_features.minimum, abs_features.maximum, + abs_features.flat, percent_deadzone, abs_features.fuzz); } } @@ -272,7 +295,7 @@ int main(int argc, char* argv[]) { char* evdevice = NULL; int c, axisindex = -1; - __s32 flat = -1, fuzz = -1; + __s32 min = INT_MIN, max = INT_MIN, flat = INT_MIN, fuzz = INT_MIN; // Show help by default if(argc == 1) @@ -289,6 +312,8 @@ int main(int argc, char* argv[]) { "listdevs", no_argument, 0, 'l' }, { "showcal", required_argument, 0, 's' }, { "evdev", required_argument, 0, 'e' }, + { "minimum", required_argument, 0, 'm' }, + { "maximum", required_argument, 0, 'M' }, { "deadzone", required_argument, 0, 'd' }, { "fuzz", required_argument, 0, 'f' }, { "axis", required_argument, 0, 'a' }, @@ -297,7 +322,7 @@ int main(int argc, char* argv[]) // getopt_long stores the option index here int option_index = 0; - c = getopt_long(argc, argv, "h:l:s:e:d:f:a:", long_options, &option_index); + c = getopt_long(argc, argv, "h:l:s:e:d:m:M:f:a:", long_options, &option_index); // Detect the end of the options if(c == -1) @@ -338,6 +363,16 @@ int main(int argc, char* argv[]) printf("New dead zone value: %d\n", flat); break; + case 'm': + min = atoi(optarg); + printf("New min value: %d\n", min); + break; + + case 'M': + max = atoi(optarg); + printf("New max value: %d\n", max); + break; + case 'f': fuzz = atoi(optarg); printf("New fuzz value: %d\n", fuzz); @@ -366,7 +401,7 @@ int main(int argc, char* argv[]) putchar('\n'); } - if(flat != -1 || fuzz != -1) + if(min != INT_MIN || max != INT_MIN || flat != INT_MIN || fuzz != INT_MIN) { if(evdevice == NULL) { @@ -377,20 +412,28 @@ int main(int argc, char* argv[]) { if(axisindex == -1) { - if(flat != -1) + if(min != INT_MIN) + printf( "Trying to set all axes minimum to: %d\n", min); + if(max != INT_MIN) + printf( "Trying to set all axes maximum to: %d\n", max); + if(flat != INT_MIN) printf( "Trying to set all axes deadzone to: %d\n", flat); - if(fuzz != -1) + if(fuzz != INT_MIN) printf( "Trying to set all axes fuzz to: %d\n", fuzz); } else { - if(flat != -1) + if(min != INT_MIN) + printf( "Trying to set axis %d minimum to: %d\n", axisindex, min); + if(max != INT_MIN) + printf( "Trying to set axis %d maximum to: %d\n", axisindex, max); + if(flat != INT_MIN) printf( "Trying to set axis %d deadzone to: %d\n", axisindex, flat); - if(fuzz != -1) + if(fuzz != INT_MIN) printf( "Trying to set axis %d fuzz to: %d\n", axisindex, fuzz); } - setDeadzoneAndFuzz(evdevice, axisindex, flat, fuzz); + setAxisInfo(evdevice, axisindex, min, max, flat, fuzz); } } diff --git a/src/unix/r77/SettingsR77.cxx b/src/unix/r77/SettingsR77.cxx index 5047f6912..e8653dcb9 100644 --- a/src/unix/r77/SettingsR77.cxx +++ b/src/unix/r77/SettingsR77.cxx @@ -43,7 +43,7 @@ SettingsR77::SettingsR77() setPermanent("audio.resampling_quality", "2"); setPermanent("audio.sample_rate", "48000"); setPermanent("audio.stereo", "0"); - setPermanent("audio.volume", "80"); + setPermanent("audio.volume", "100"); setPermanent("romdir", "/mnt/games"); setPermanent("snapsavedir", "/mnt/stella/snapshots"); @@ -55,12 +55,22 @@ SettingsR77::SettingsR77() setPermanent("exitlauncher", "true"); setTemporary("minimal_ui", true); + setPermanent("basic_settings", true); + setPermanent("dev.settings", false); - setPermanent("plr.timemachine", false); + // record states for 60 seconds + setPermanent("plr.timemachine", true); + setPermanent("plr.tm.size", 60); + setPermanent("plr.tm.uncompressed", 60); + setPermanent("plr.tm.interval", "1s"); setPermanent("threads", "1"); - setPermanent("tv.filter", "3"); + + // all TV effects off by default (aligned to StellaSettingsDialog defaults!) + setPermanent("tv.filter", "0"); setPermanent("tv.phosphor", "always"); + setPermanent("tv.phosblend", "0"); + setPermanent("tv.scanlines", "0"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index ad51e46a4..4a825c140 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -501,6 +501,7 @@ + @@ -1219,6 +1220,7 @@ + diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index d3575c73b..b9e97c5f8 100644 --- a/src/windows/Stella.vcxproj.filters +++ b/src/windows/Stella.vcxproj.filters @@ -957,6 +957,9 @@ Source Files\gui + + Source Files\gui + @@ -1958,6 +1961,9 @@ Header Files\emucore + + Header Files\gui +