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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
32GlobalPropsDialog::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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
134int 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
196void 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
218void 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
255void 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
271void 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
295const char* const GlobalPropsDialog::ourJoyState[10] = {
296 "U", "D", "L", "R", "F", "U", "D", "L", "R", "F"
297};
298