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 "Console.hxx"
19#include "Control.hxx"
20#include "Paddles.hxx"
21#include "Props.hxx"
22
23#include "MouseControl.hxx"
24
25// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
26MouseControl::MouseControl(Console& console, const string& mode)
27 : myProps(console.properties()),
28 myLeftController(console.leftController()),
29 myRightController(console.rightController()),
30 myCurrentModeNum(0)
31{
32 istringstream m_axis(mode);
33 string m_mode;
34 m_axis >> m_mode;
35
36 if(BSPF::equalsIgnoreCase(m_mode, "none"))
37 {
38 myModeList.push_back(MouseMode("Mouse input is disabled"));
39 return;
40 }
41 else if(!BSPF::equalsIgnoreCase(m_mode, "auto") && m_mode.length() == 2 &&
42 m_mode[0] >= '0' && m_mode[0] <= '8' &&
43 m_mode[1] >= '0' && m_mode[1] <= '8')
44 {
45 MouseControl::Type xaxis = MouseControl::Type(int(m_mode[0]) - '0');
46 MouseControl::Type yaxis = MouseControl::Type(int(m_mode[1]) - '0');
47 ostringstream msg;
48 Controller::Type xtype = Controller::Type::Joystick, ytype = Controller::Type::Joystick;
49 int xid = -1, yid = -1;
50
51 auto MControlToController = [&msg](MouseControl::Type axis,
52 Controller::Type& type, int& id) {
53 switch(axis)
54 {
55 case MouseControl::Type::NoControl:
56 msg << "not used";
57 break;
58 case MouseControl::Type::Paddle0:
59 type = Controller::Type::Paddles;
60 id = 0;
61 msg << "Paddle 0";
62 break;
63 case MouseControl::Type::Paddle1:
64 type = Controller::Type::Paddles;
65 id = 1;
66 msg << "Paddle 1";
67 break;
68 case MouseControl::Type::Paddle2:
69 type = Controller::Type::Paddles;
70 id = 2;
71 msg << "Paddle 2";
72 break;
73 case MouseControl::Type::Paddle3:
74 type = Controller::Type::Paddles;
75 id = 3;
76 msg << "Paddle 3";
77 break;
78 case MouseControl::Type::Driving0:
79 type = Controller::Type::Driving;
80 id = 0;
81 msg << "Driving 0";
82 break;
83 case MouseControl::Type::Driving1:
84 type = Controller::Type::Driving;
85 id = 1;
86 msg << "Driving 1";
87 break;
88 case MouseControl::Type::MindLink0:
89 type = Controller::Type::MindLink;
90 id = 0;
91 msg << "MindLink 0";
92 break;
93 case MouseControl::Type::MindLink1:
94 type = Controller::Type::MindLink;
95 id = 1;
96 msg << "MindLink 1";
97 break;
98 }
99 };
100
101 msg << "Mouse X-axis is ";
102 MControlToController(xaxis, xtype, xid);
103 msg << ", Y-axis is ";
104 MControlToController(yaxis, ytype, yid);
105
106 myModeList.push_back(MouseMode(xtype, xid, ytype, yid, msg.str()));
107 }
108
109 // Now consider the possible modes for the mouse based on the left
110 // and right controllers
111 bool noswap = BSPF::equalsIgnoreCase(myProps.get(PropType::Console_SwapPorts), "NO");
112 if(noswap)
113 {
114 addLeftControllerModes(noswap);
115 addRightControllerModes(noswap);
116 }
117 else
118 {
119 addRightControllerModes(noswap);
120 addLeftControllerModes(noswap);
121 }
122
123 // Set range information (currently only for paddles, but may be used
124 // for other controllers in the future)
125 int m_range = 100;
126 if(!(m_axis >> m_range))
127 m_range = 100;
128 Paddles::setPaddleRange(m_range);
129
130 // If the mouse isn't used at all, we still need one item in the list
131 if(myModeList.size() == 0)
132 myModeList.push_back(MouseMode("Mouse not used for current controllers"));
133
134#if 0
135 for(const auto& m: myModeList)
136 cerr << m << endl;
137#endif
138}
139
140// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
141const string& MouseControl::next()
142{
143 const MouseMode& mode = myModeList[myCurrentModeNum];
144 myCurrentModeNum = (myCurrentModeNum + 1) % myModeList.size();
145
146 myLeftController.setMouseControl(mode.xtype, mode.xid, mode.ytype, mode.yid);
147 myRightController.setMouseControl(mode.xtype, mode.xid, mode.ytype, mode.yid);
148
149 return mode.message;
150}
151
152// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
153void MouseControl::addLeftControllerModes(bool noswap)
154{
155 if(controllerSupportsMouse(myLeftController))
156 {
157 if(myLeftController.type() == Controller::Type::Paddles)
158 {
159 if(noswap) addPaddleModes(0, 1, 0, 1);
160 else addPaddleModes(2, 3, 0, 1);
161 }
162 else
163 {
164 ostringstream msg;
165 msg << "Mouse is left " << myLeftController.name() << " controller";
166 Controller::Type type = myLeftController.type();
167 int id = noswap ? 0 : 1;
168 myModeList.push_back(MouseMode(type, id, type, id, msg.str()));
169 }
170 }
171}
172
173// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
174void MouseControl::addRightControllerModes(bool noswap)
175{
176 if(controllerSupportsMouse(myRightController))
177 {
178 if(myRightController.type() == Controller::Type::Paddles)
179 {
180 if(noswap) addPaddleModes(2, 3, 2, 3);
181 else addPaddleModes(0, 1, 2, 3);
182 }
183 else
184 {
185 ostringstream msg;
186 msg << "Mouse is right " << myRightController.name() << " controller";
187 Controller::Type type = myRightController.type();
188 int id = noswap ? 1 : 0;
189 myModeList.push_back(MouseMode(type, id, type, id, msg.str()));
190 }
191 }
192}
193
194// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
195void MouseControl::addPaddleModes(int lport, int rport, int lname, int rname)
196{
197 Controller::Type type = Controller::Type::Paddles;
198 ostringstream msg;
199 msg << "Mouse is Paddle " << lname << " controller";
200 MouseMode mode0(type, lport, type, lport, msg.str());
201
202 msg.str("");
203 msg << "Mouse is Paddle " << rname << " controller";
204 MouseMode mode1(type, rport, type, rport, msg.str());
205
206 if(BSPF::equalsIgnoreCase(myProps.get(PropType::Controller_SwapPaddles), "NO"))
207 {
208 myModeList.push_back(mode0);
209 myModeList.push_back(mode1);
210 }
211 else
212 {
213 myModeList.push_back(mode1);
214 myModeList.push_back(mode0);
215 }
216}
217
218// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
219bool MouseControl::controllerSupportsMouse(Controller& controller)
220{
221 // Test whether the controller uses the mouse at all
222 // We can pass in dummy values here, since the controllers will be
223 // initialized by a call to next() once the system is up and running
224 return controller.setMouseControl(
225 Controller::Type::Joystick, -1, Controller::Type::Joystick, -1);
226}
227