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 | |