diff --git a/Changes.txt b/Changes.txt index 2a5efe3b6..9fa3661e9 100644 --- a/Changes.txt +++ b/Changes.txt @@ -43,6 +43,10 @@ apply the properties to the ROM. [NOTE: this was present in 6.2, but was mistakenly left out of the changelog] + * Added button to Game Info dialog to save properties of the currently + loaded ROM to a separate properties file (in the default save directory). + This is useful in conjunction with the previous item. + * Allow changing custom palette and TV effects adjustables in 1% steps again. diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index 1cc0b3b8c..e455a976c 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -835,6 +835,34 @@ void Dialog::addDefaultsOKCancelBGroup(WidgetArray& wid, const GUI::Font& font, addOKCancelBGroup(wid, font, okText, cancelText, focusOKButton, buttonWidth); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Dialog::addDefaultsExtraOKCancelBGroup( + WidgetArray& wid, const GUI::Font& font, + const string& extraText, int extraCmd, + const string& okText, const string& cancelText, const string& defaultsText, + bool focusOKButton) +{ + const int fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(), + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int BTN_BORDER = fontWidth * 2.5; + const int BUTTON_GAP = fontWidth; + const int buttonWidth = font.getStringWidth(defaultsText) + BTN_BORDER; + + addDefaultWidget(new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER, + buttonWidth, buttonHeight, defaultsText, GuiObject::kDefaultsCmd)); + wid.push_back(_defaultWidget); + + wid.push_back(new ButtonWidget(this, font, HBORDER + buttonWidth + BUTTON_GAP, + _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, + extraText, extraCmd) + ); + + addOKCancelBGroup(wid, font, okText, cancelText, focusOKButton, buttonWidth); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Dialog::TabFocus::appendFocusList(WidgetArray& list) { diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 5b95fe5e0..0dc5e7118 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -158,6 +158,15 @@ class Dialog : public GuiObject const string& defaultsText = "Defaults", bool focusOKButton = true); + // NOTE: This method, and the two above it, are due to be refactored at some + // point, since the parameter list is kind of getting ridiculous + void addDefaultsExtraOKCancelBGroup(WidgetArray& wid, const GUI::Font& font, + const string& extraText, int extraCmd, + const string& okText = "OK", + const string& cancelText = "Cancel", + const string& defaultsText = "Defaults", + bool focusOKButton = true); + void processCancelWithoutWidget(bool state) { _processCancel = state; } virtual void processCancel() { close(); } diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index fd646c6ed..2348e047d 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -383,7 +383,7 @@ GameInfoDialog::GameInfoDialog( // Add Defaults, OK and Cancel buttons wid.clear(); - addDefaultsOKCancelBGroup(wid, font); + addDefaultsExtraOKCancelBGroup(wid, font, "Save", kSavePressed); addBGroupToFocusList(wid); } @@ -393,11 +393,13 @@ void GameInfoDialog::loadConfig() if(instance().hasConsole()) { myGameProperties = instance().console().properties(); + myGameFile = instance().romFile(); } else { const string& md5 = instance().launcher().selectedRomMD5(); instance().propSet().getMD5(md5, myGameProperties); + myGameFile = FilesystemNode(instance().launcher().selectedRom()); } loadEmulationProperties(myGameProperties); @@ -568,7 +570,7 @@ void GameInfoDialog::loadCartridgeProperties(const Properties& props) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void GameInfoDialog::saveConfig() +void GameInfoDialog::saveProperties() { // Emulation properties myGameProperties.set(PropType::Cart_Type, myBSType->getSelectedTag().toString()); @@ -613,6 +615,12 @@ void GameInfoDialog::saveConfig() myGameProperties.set(PropType::Cart_ModelNo, myModelNo->getText()); myGameProperties.set(PropType::Cart_Rarity, myRarity->getText()); myGameProperties.set(PropType::Cart_Note, myNote->getText()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void GameInfoDialog::saveConfig() +{ + saveProperties(); // Always insert; if the properties are already present, nothing will happen instance().propSet().insert(myGameProperties); @@ -626,7 +634,7 @@ void GameInfoDialog::saveConfig() // update 'Emulation' tab settings immediately instance().console().setFormat(myFormat->getSelected()); instance().frameBuffer().tiaSurface().enablePhosphor(myPhosphor->getState(), myPPBlend->getValue()); - instance().console().updateVcenter(vcenter); + instance().console().updateVcenter(myVCenter->getValue()); instance().console().initializeAudio(); // update 'Console' tab settings immediately @@ -782,19 +790,38 @@ void GameInfoDialog::eraseEEPROM() Controller& lport = instance().console().leftController(); Controller& rport = instance().console().rightController(); - if(lport.type() == Controller::Type::SaveKey || lport.type() == Controller::Type::AtariVox) + if(lport.type() == Controller::Type::SaveKey || + lport.type() == Controller::Type::AtariVox) { SaveKey& skey = static_cast(lport); skey.eraseCurrent(); } - if(rport.type() == Controller::Type::SaveKey || rport.type() == Controller::Type::AtariVox) + if(rport.type() == Controller::Type::SaveKey || + rport.type() == Controller::Type::AtariVox) { SaveKey& skey = static_cast(rport); skey.eraseCurrent(); } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void GameInfoDialog::saveCurrentPropertiesToDisk() +{ + saveProperties(); + + FilesystemNode propfile(instance().defaultSaveDir() + myGameFile.getNameWithExt(".pro")); + ofstream out(propfile.getPath()); + if(out) + { + out << myGameProperties; + instance().frameBuffer().showMessage("Properties saved to " + + propfile.getShortPath()); + } + else + instance().frameBuffer().showMessage("Error saving properties"); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) @@ -810,6 +837,10 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, setDefaults(); break; + case kSavePressed: + saveCurrentPropertiesToDisk(); + break; + case TabWidget::kTabChangedCmd: if(data == 2) // 'Controllers' tab selected updateControllerStates(); diff --git a/src/gui/GameInfoDialog.hxx b/src/gui/GameInfoDialog.hxx index 2e2dc4f8a..7e5febdde 100644 --- a/src/gui/GameInfoDialog.hxx +++ b/src/gui/GameInfoDialog.hxx @@ -53,9 +53,12 @@ class GameInfoDialog : public Dialog, public CommandSender void loadControllerProperties(const Properties& props); // load the properties for the 'Cartridge' tab void loadCartridgeProperties(const Properties& props); + // save properties from all tabs into the local properties object + void saveProperties(); void updateControllerStates(); void eraseEEPROM(); + void saveCurrentPropertiesToDisk(); private: TabWidget* myTab{nullptr}; @@ -115,10 +118,13 @@ class GameInfoDialog : public Dialog, public CommandSender kEEButtonPressed = 'EEgb', kPXCenterChanged = 'Pxch', kPYCenterChanged = 'Pych', + kSavePressed = 'GIsp' }; // Game properties for currently loaded ROM Properties myGameProperties; + // Filename of the currently loaded ROM + FilesystemNode myGameFile; private: // Following constructors and assignment operators not supported