| 1 | //============================================================================ |
| 2 | // |
| 3 | // SSSS tt lll lll |
| 4 | // SS SS tt ll ll |
| 5 | // SS tttttt eeee ll ll aaaa |
| 6 | // SSSS tt ee ee ll ll aa |
| 7 | // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" |
| 8 | // SS SS tt ee ll ll aa aa |
| 9 | // SSSS ttt eeeee llll llll aaaaa |
| 10 | // |
| 11 | // Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony |
| 12 | // and the Stella Team |
| 13 | // |
| 14 | // See the file "License.txt" for information on usage and redistribution of |
| 15 | // this file, and for a DISCLAIMER OF ALL WARRANTIES. |
| 16 | //============================================================================ |
| 17 | |
| 18 | #include "bspf.hxx" |
| 19 | #include "Bankswitch.hxx" |
| 20 | #include "Control.hxx" |
| 21 | #include "Dialog.hxx" |
| 22 | #include "OSystem.hxx" |
| 23 | #include "FrameBuffer.hxx" |
| 24 | #include "PopUpWidget.hxx" |
| 25 | #include "Settings.hxx" |
| 26 | #include "Widget.hxx" |
| 27 | #include "Font.hxx" |
| 28 | #include "LauncherDialog.hxx" |
| 29 | #include "GlobalPropsDialog.hxx" |
| 30 | |
| 31 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| 32 | GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font) |
| 33 | : Dialog(boss->instance(), boss->parent(), font, "Power-on options" ), |
| 34 | CommandSender(boss) |
| 35 | { |
| 36 | const int lineHeight = font.getLineHeight(), |
| 37 | fontWidth = font.getMaxCharWidth(), |
| 38 | fontHeight = font.getFontHeight(), |
| 39 | buttonHeight = font.getLineHeight() + 4; |
| 40 | int xpos, ypos; |
| 41 | int lwidth = font.getStringWidth("Right difficulty " ), |
| 42 | pwidth = font.getStringWidth("CM (SpectraVideo CompuMate)" ); |
| 43 | const int VGAP = 4; |
| 44 | WidgetArray wid; |
| 45 | VariantList items; |
| 46 | const GUI::Font& infofont = instance().frameBuffer().infoFont(); |
| 47 | |
| 48 | // Set real dimensions |
| 49 | _w = lwidth + pwidth + fontWidth*3 + 15; |
| 50 | _h = 15 * (lineHeight + 4) + buttonHeight + 16 + _th; |
| 51 | |
| 52 | xpos = 10; ypos = 10 + _th; |
| 53 | |
| 54 | // Bankswitch type |
| 55 | new StaticTextWidget(this, font, xpos, ypos+1, "Bankswitch type" ); |
| 56 | for(uInt32 i = 0; i < uInt32(Bankswitch::Type::NumSchemes); ++i) |
| 57 | VarList::push_back(items, Bankswitch::BSList[i].desc, Bankswitch::BSList[i].name); |
| 58 | myBSType = new PopUpWidget(this, font, xpos+lwidth, ypos, |
| 59 | pwidth, lineHeight, items, "" ); |
| 60 | wid.push_back(myBSType); |
| 61 | ypos += lineHeight + VGAP * 3; |
| 62 | |
| 63 | pwidth = font.getStringWidth("A (Expert)" ); |
| 64 | |
| 65 | // TV type |
| 66 | new StaticTextWidget(this, font, xpos, ypos + 1, "TV type" ); |
| 67 | items.clear(); |
| 68 | VarList::push_back(items, "Default" , "DEFAULT" ); |
| 69 | VarList::push_back(items, "Color" , "COLOR" ); |
| 70 | VarList::push_back(items, "B/W" , "BW" ); |
| 71 | myTVType = new PopUpWidget(this, font, xpos + lwidth, ypos, |
| 72 | pwidth, lineHeight, items, "" ); |
| 73 | wid.push_back(myTVType); |
| 74 | ypos += lineHeight + VGAP; |
| 75 | |
| 76 | // Left difficulty |
| 77 | new StaticTextWidget(this, font, xpos, ypos+1, GUI::LEFT_DIFFICULTY); |
| 78 | items.clear(); |
| 79 | VarList::push_back(items, "Default" , "DEFAULT" ); |
| 80 | VarList::push_back(items, "A (Expert)" , "A" ); |
| 81 | VarList::push_back(items, "B (Novice)" , "B" ); |
| 82 | myLeftDiff = new PopUpWidget(this, font, xpos+lwidth, ypos, |
| 83 | pwidth, lineHeight, items, "" ); |
| 84 | wid.push_back(myLeftDiff); |
| 85 | ypos += lineHeight + VGAP; |
| 86 | |
| 87 | // Right difficulty |
| 88 | new StaticTextWidget(this, font, xpos, ypos+1, GUI::RIGHT_DIFFICULTY); |
| 89 | // ... use same items as above |
| 90 | myRightDiff = new PopUpWidget(this, font, xpos+lwidth, ypos, |
| 91 | pwidth, lineHeight, items, "" ); |
| 92 | wid.push_back(myRightDiff); |
| 93 | ypos += lineHeight + VGAP * 3; |
| 94 | |
| 95 | // Start in debugger mode |
| 96 | new StaticTextWidget(this, font, xpos, ypos+1, "Startup mode" ); |
| 97 | items.clear(); |
| 98 | VarList::push_back(items, "Console" , "false" ); |
| 99 | #ifdef DEBUGGER_SUPPORT |
| 100 | VarList::push_back(items, "Debugger" , "true" ); |
| 101 | #endif |
| 102 | myDebug = new PopUpWidget(this, font, xpos+lwidth, ypos, |
| 103 | pwidth, lineHeight, items, "" ); |
| 104 | wid.push_back(myDebug); |
| 105 | ypos += lineHeight + VGAP * 3; |
| 106 | |
| 107 | // Start console with buttons held down |
| 108 | new StaticTextWidget(this, font, xpos, ypos+1, |
| 109 | "Start with the following held down:" ); |
| 110 | ypos += lineHeight; |
| 111 | new StaticTextWidget(this, infofont, xpos, ypos+1, |
| 112 | "(automatically released shortly after start)" ); |
| 113 | |
| 114 | // Start with console joystick direction/buttons held down |
| 115 | xpos = 32; ypos += infofont.getLineHeight() + VGAP * 2; |
| 116 | ypos = addHoldWidgets(font, xpos, ypos, wid); |
| 117 | |
| 118 | // Add message concerning usage |
| 119 | xpos = 10; ypos += 2 * fontHeight; |
| 120 | ypos = _h - fontHeight * 2 - infofont.getLineHeight() - 24; |
| 121 | new StaticTextWidget(this, infofont, xpos, ypos, |
| 122 | "(*) These options are not saved, but apply to all" ); |
| 123 | ypos += infofont.getLineHeight(); |
| 124 | new StaticTextWidget(this, infofont, xpos, ypos, |
| 125 | " further ROMs until selecting 'Defaults'." ); |
| 126 | |
| 127 | // Add Defaults, OK and Cancel buttons |
| 128 | addDefaultsOKCancelBGroup(wid, font, "Load ROM" , "Cancel" ); |
| 129 | |
| 130 | addToFocusList(wid); |
| 131 | } |
| 132 | |
| 133 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| 134 | int GlobalPropsDialog::addHoldWidgets(const GUI::Font& font, int x, int y, |
| 135 | WidgetArray& wid) |
| 136 | { |
| 137 | int xpos = x, ypos = y; |
| 138 | const int VGAP = 4; |
| 139 | |
| 140 | // Left joystick |
| 141 | StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos+2, "Left joy" ); |
| 142 | xpos += t->getWidth()/2 - 7; ypos += t->getHeight() + VGAP; |
| 143 | myJoy[kJ0Up] = new CheckboxWidget(this, font, xpos, ypos, "" , kJ0Up); |
| 144 | ypos += myJoy[kJ0Up]->getHeight() * 2 + VGAP * 2; |
| 145 | myJoy[kJ0Down] = new CheckboxWidget(this, font, xpos, ypos, "" , kJ0Down); |
| 146 | xpos -= myJoy[kJ0Up]->getWidth() + 5; |
| 147 | ypos -= myJoy[kJ0Up]->getHeight() + VGAP; |
| 148 | myJoy[kJ0Left] = new CheckboxWidget(this, font, xpos, ypos, "" , kJ0Left); |
| 149 | xpos += (myJoy[kJ0Up]->getWidth() + 5) * 2; |
| 150 | myJoy[kJ0Right] = new CheckboxWidget(this, font, xpos, ypos, "" , kJ0Right); |
| 151 | xpos -= (myJoy[kJ0Up]->getWidth() + 5) * 2; |
| 152 | ypos += myJoy[kJ0Down]->getHeight() * 2 + VGAP * 2; |
| 153 | myJoy[kJ0Fire] = new CheckboxWidget(this, font, xpos, ypos, "Fire" , kJ0Fire); |
| 154 | |
| 155 | int final_y = ypos; |
| 156 | xpos = _w / 3; ypos = y; |
| 157 | |
| 158 | // Right joystick |
| 159 | t = new StaticTextWidget(this, font, xpos, ypos + 2, "Right joy" ); |
| 160 | xpos += t->getWidth()/2 - 7; ypos += t->getHeight() + VGAP; |
| 161 | myJoy[kJ1Up] = new CheckboxWidget(this, font, xpos, ypos, "" , kJ1Up); |
| 162 | ypos += myJoy[kJ1Up]->getHeight() * 2 + VGAP * 2; |
| 163 | myJoy[kJ1Down] = new CheckboxWidget(this, font, xpos, ypos, "" , kJ1Down); |
| 164 | xpos -= myJoy[kJ1Up]->getWidth() + 5; |
| 165 | ypos -= myJoy[kJ1Up]->getHeight() + VGAP; |
| 166 | myJoy[kJ1Left] = new CheckboxWidget(this, font, xpos, ypos, "" , kJ1Left); |
| 167 | xpos += (myJoy[kJ1Up]->getWidth() + 5) * 2; |
| 168 | myJoy[kJ1Right] = new CheckboxWidget(this, font, xpos, ypos, "" , kJ1Right); |
| 169 | xpos -= (myJoy[kJ1Up]->getWidth() + 5) * 2; |
| 170 | ypos += myJoy[kJ1Down]->getHeight() * 2 + VGAP * 2; |
| 171 | myJoy[kJ1Fire] = new CheckboxWidget(this, font, xpos, ypos, "Fire" , kJ1Fire); |
| 172 | |
| 173 | xpos = 2 * _w / 3 + 8; ypos = y; |
| 174 | |
| 175 | // Console Select/Reset |
| 176 | t = new StaticTextWidget(this, font, xpos, ypos+2, "Console" ); |
| 177 | ypos += t->getHeight() + VGAP; |
| 178 | myHoldSelect = new CheckboxWidget(this, font, xpos, ypos, GUI::SELECT); |
| 179 | ypos += myHoldSelect->getHeight() + VGAP; |
| 180 | myHoldReset = new CheckboxWidget(this, font, xpos, ypos, "Reset" ); |
| 181 | |
| 182 | const int TAB_ORDER[10] = { |
| 183 | kJ0Up, kJ0Left, kJ0Right, kJ0Down, kJ0Fire, |
| 184 | kJ1Up, kJ1Left, kJ1Right, kJ1Down, kJ1Fire |
| 185 | }; |
| 186 | for(int i = kJ0Up; i <= kJ1Fire; ++i) |
| 187 | wid.push_back(myJoy[TAB_ORDER[i]]); |
| 188 | |
| 189 | wid.push_back(myHoldSelect); |
| 190 | wid.push_back(myHoldReset); |
| 191 | |
| 192 | return final_y; |
| 193 | } |
| 194 | |
| 195 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| 196 | void GlobalPropsDialog::loadConfig() |
| 197 | { |
| 198 | Settings& settings = instance().settings(); |
| 199 | |
| 200 | myBSType->setSelected(settings.getString("bs" ), "AUTO" ); |
| 201 | myLeftDiff->setSelected(settings.getString("ld" ), "DEFAULT" ); |
| 202 | myRightDiff->setSelected(settings.getString("rd" ), "DEFAULT" ); |
| 203 | myTVType->setSelected(settings.getString("tv" ), "DEFAULT" ); |
| 204 | myDebug->setSelected(settings.getBool("debug" ) ? "true" : "false" ); |
| 205 | |
| 206 | const string& holdjoy0 = settings.getString("holdjoy0" ); |
| 207 | for(int i = kJ0Up; i <= kJ0Fire; ++i) |
| 208 | myJoy[i]->setState(BSPF::containsIgnoreCase(holdjoy0, ourJoyState[i])); |
| 209 | const string& holdjoy1 = settings.getString("holdjoy1" ); |
| 210 | for(int i = kJ1Up; i <= kJ1Fire; ++i) |
| 211 | myJoy[i]->setState(BSPF::containsIgnoreCase(holdjoy1, ourJoyState[i])); |
| 212 | |
| 213 | myHoldSelect->setState(settings.getBool("holdselect" )); |
| 214 | myHoldReset->setState(settings.getBool("holdreset" )); |
| 215 | } |
| 216 | |
| 217 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| 218 | void GlobalPropsDialog::saveConfig() |
| 219 | { |
| 220 | Settings& settings = instance().settings(); |
| 221 | string s; |
| 222 | |
| 223 | s = myBSType->getSelectedTag().toString(); |
| 224 | if(s == "AUTO" ) s = "" ; |
| 225 | settings.setValue("bs" , s); |
| 226 | |
| 227 | s = myLeftDiff->getSelectedTag().toString(); |
| 228 | if(s == "DEFAULT" ) s = "" ; |
| 229 | settings.setValue("ld" , s); |
| 230 | |
| 231 | s = myRightDiff->getSelectedTag().toString(); |
| 232 | if(s == "DEFAULT" ) s = "" ; |
| 233 | settings.setValue("rd" , s); |
| 234 | |
| 235 | s = myTVType->getSelectedTag().toString(); |
| 236 | if(s == "DEFAULT" ) s = "" ; |
| 237 | settings.setValue("tv" , s); |
| 238 | |
| 239 | settings.setValue("debug" , myDebug->getSelectedTag().toBool()); |
| 240 | |
| 241 | s = "" ; |
| 242 | for(int i = kJ0Up; i <= kJ0Fire; ++i) |
| 243 | if(myJoy[i]->getState()) s += ourJoyState[i]; |
| 244 | settings.setValue("holdjoy0" , s); |
| 245 | s = "" ; |
| 246 | for(int i = kJ1Up; i <= kJ1Fire; ++i) |
| 247 | if(myJoy[i]->getState()) s += ourJoyState[i]; |
| 248 | settings.setValue("holdjoy1" , s); |
| 249 | |
| 250 | settings.setValue("holdselect" , myHoldSelect->getState()); |
| 251 | settings.setValue("holdreset" , myHoldReset->getState()); |
| 252 | } |
| 253 | |
| 254 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| 255 | void GlobalPropsDialog::setDefaults() |
| 256 | { |
| 257 | myBSType->setSelected("AUTO" ); |
| 258 | myLeftDiff->setSelected("DEFAULT" ); |
| 259 | myRightDiff->setSelected("DEFAULT" ); |
| 260 | myTVType->setSelected("DEFAULT" ); |
| 261 | myDebug->setSelected("false" ); |
| 262 | |
| 263 | for(int i = kJ0Up; i <= kJ1Fire; ++i) |
| 264 | myJoy[i]->setState(false); |
| 265 | |
| 266 | myHoldSelect->setState(false); |
| 267 | myHoldReset->setState(false); |
| 268 | } |
| 269 | |
| 270 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| 271 | void GlobalPropsDialog::handleCommand(CommandSender* sender, int cmd, |
| 272 | int data, int id) |
| 273 | { |
| 274 | switch(cmd) |
| 275 | { |
| 276 | case GuiObject::kOKCmd: |
| 277 | saveConfig(); |
| 278 | close(); |
| 279 | // Inform parent to load the ROM |
| 280 | sendCommand(LauncherDialog::kLoadROMCmd, 0, 0); |
| 281 | break; |
| 282 | |
| 283 | case GuiObject::kDefaultsCmd: |
| 284 | setDefaults(); |
| 285 | saveConfig(); |
| 286 | break; |
| 287 | |
| 288 | default: |
| 289 | Dialog::handleCommand(sender, cmd, data, 0); |
| 290 | break; |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| 295 | const char* const GlobalPropsDialog::ourJoyState[10] = { |
| 296 | "U" , "D" , "L" , "R" , "F" , "U" , "D" , "L" , "R" , "F" |
| 297 | }; |
| 298 | |