| 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 | #ifndef CONTROLLER_HXX |
| 19 | #define CONTROLLER_HXX |
| 20 | |
| 21 | class Controller; |
| 22 | class ControllerLowLevel; |
| 23 | class Event; |
| 24 | class System; |
| 25 | |
| 26 | #include <functional> |
| 27 | |
| 28 | #include "Serializable.hxx" |
| 29 | #include "bspf.hxx" |
| 30 | |
| 31 | /** |
| 32 | A controller is a device that plugs into either the left or right |
| 33 | controller jack of the Video Computer System (VCS). The pins of |
| 34 | the controller jacks are mapped as follows: |
| 35 | |
| 36 | ------------- |
| 37 | \ 1 2 3 4 5 / |
| 38 | \ 6 7 8 9 / |
| 39 | --------- |
| 40 | |
| 41 | Left Controller Right Controller |
| 42 | |
| 43 | pin 1 D4 PIA SWCHA D0 PIA SWCHA |
| 44 | pin 2 D5 PIA SWCHA D1 PIA SWCHA |
| 45 | pin 3 D6 PIA SWCHA D2 PIA SWCHA |
| 46 | pin 4 D7 PIA SWCHA D3 PIA SWCHA |
| 47 | pin 5 D7 TIA INPT1 (Dumped) D7 TIA INPT3 (Dumped) |
| 48 | pin 6 D7 TIA INPT4 (Latched) D7 TIA INPT5 (Latched) |
| 49 | pin 7 +5 +5 |
| 50 | pin 8 GND GND |
| 51 | pin 9 D7 TIA INPT0 (Dumped) D7 TIA INPT2 (Dumped) |
| 52 | |
| 53 | Each of the pins connected to the PIA can be configured as an |
| 54 | input or output pin. The "dumped" TIA pins are used to charge |
| 55 | a capacitor. A potentiometer is sometimes connected to these |
| 56 | pins for analog input. |
| 57 | |
| 58 | This is a base class for all controllers. It provides a view |
| 59 | of the controller from the perspective of the controller's jack. |
| 60 | |
| 61 | @author Bradford W. Mott |
| 62 | */ |
| 63 | class Controller : public Serializable |
| 64 | { |
| 65 | /** |
| 66 | Various classes that need special access to the underlying controller state |
| 67 | */ |
| 68 | friend class M6532; // FIXME - only needs two methods from this class |
| 69 | friend class CompuMate; // FIXME - should go through CMControl instead |
| 70 | friend class ControllerLowLevel; |
| 71 | |
| 72 | public: |
| 73 | /** |
| 74 | Enumeration of the controller jacks |
| 75 | */ |
| 76 | enum class Jack { Left = 0, Right = 1 }; |
| 77 | |
| 78 | /** |
| 79 | Enumeration of the digital pins of a controller port |
| 80 | */ |
| 81 | enum class DigitalPin { One, Two, Three, Four, Six }; |
| 82 | |
| 83 | /** |
| 84 | Enumeration of the analog pins of a controller port |
| 85 | */ |
| 86 | enum class AnalogPin { Five, Nine }; |
| 87 | |
| 88 | /** |
| 89 | Enumeration of the controller types |
| 90 | */ |
| 91 | enum class Type |
| 92 | { |
| 93 | Unknown, |
| 94 | AmigaMouse, AtariMouse, AtariVox, BoosterGrip, CompuMate, |
| 95 | Driving, Genesis, Joystick, Keyboard, KidVid, MindLink, |
| 96 | Paddles, PaddlesIAxis, PaddlesIAxDr, SaveKey, TrakBall, |
| 97 | LastType |
| 98 | }; |
| 99 | |
| 100 | /** |
| 101 | Callback type for analog pin updates |
| 102 | */ |
| 103 | using onAnalogPinUpdateCallback = std::function<void(AnalogPin)>; |
| 104 | |
| 105 | /** |
| 106 | Callback type for general controller messages |
| 107 | */ |
| 108 | using onMessageCallback = std::function<void(const string&)>; |
| 109 | |
| 110 | public: |
| 111 | /** |
| 112 | Create a new controller plugged into the specified jack |
| 113 | |
| 114 | @param jack The jack the controller is plugged into |
| 115 | @param event The event object to use for events |
| 116 | @param system The system using this controller |
| 117 | @param type The type for this controller |
| 118 | */ |
| 119 | Controller(Jack jack, const Event& event, const System& system, |
| 120 | Type type); |
| 121 | virtual ~Controller() = default; |
| 122 | |
| 123 | /** |
| 124 | Returns the jack that this controller is plugged into. |
| 125 | */ |
| 126 | Jack jack() const { return myJack; } |
| 127 | |
| 128 | /** |
| 129 | Returns the type of this controller. |
| 130 | */ |
| 131 | Type type() const { return myType; } |
| 132 | |
| 133 | /** |
| 134 | Read the entire state of all digital pins for this controller. |
| 135 | Note that this method must use the lower 4 bits, and zero the upper bits. |
| 136 | |
| 137 | @return The state of all digital pins |
| 138 | */ |
| 139 | virtual uInt8 read(); |
| 140 | |
| 141 | /** |
| 142 | Read the value of the specified digital pin for this controller. |
| 143 | |
| 144 | @param pin The pin of the controller jack to read |
| 145 | @return The state of the pin |
| 146 | */ |
| 147 | virtual bool read(DigitalPin pin); |
| 148 | |
| 149 | /** |
| 150 | Read the resistance at the specified analog pin for this controller. |
| 151 | The returned value is the resistance measured in ohms. |
| 152 | |
| 153 | @param pin The pin of the controller jack to read |
| 154 | @return The resistance at the specified pin |
| 155 | */ |
| 156 | virtual Int32 read(AnalogPin pin); |
| 157 | |
| 158 | /** |
| 159 | Write the given value to the specified digital pin for this |
| 160 | controller. Writing is only allowed to the pins associated |
| 161 | with the PIA. Therefore you cannot write to pin six. |
| 162 | |
| 163 | @param pin The pin of the controller jack to write to |
| 164 | @param value The value to write to the pin |
| 165 | */ |
| 166 | virtual void write(DigitalPin pin, bool value) { } |
| 167 | |
| 168 | /** |
| 169 | Called after *all* digital pins have been written on Port A. |
| 170 | Most controllers don't do anything in this case. |
| 171 | |
| 172 | @param value The entire contents of the SWCHA register |
| 173 | */ |
| 174 | virtual void controlWrite(uInt8 value) { } |
| 175 | |
| 176 | /** |
| 177 | Update the entire digital and analog pin state according to the |
| 178 | events currently set. |
| 179 | */ |
| 180 | virtual void update() = 0; |
| 181 | |
| 182 | /** |
| 183 | Returns the name of this controller. |
| 184 | */ |
| 185 | virtual string name() const = 0; |
| 186 | |
| 187 | /** |
| 188 | Answers whether the controller is intrinsically an analog controller. |
| 189 | Specific controllers should override and implement this method. |
| 190 | */ |
| 191 | virtual bool isAnalog() const { return false; } |
| 192 | |
| 193 | /** |
| 194 | Notification method invoked by the system after its reset method has |
| 195 | been called. It may be necessary to override this method for |
| 196 | controllers that need to know a reset has occurred. |
| 197 | */ |
| 198 | virtual void reset() { } |
| 199 | |
| 200 | /** |
| 201 | Notification method invoked by the system indicating that the |
| 202 | console is about to be destroyed. It may be necessary to override |
| 203 | this method for controllers that need cleanup before exiting. |
| 204 | */ |
| 205 | virtual void close() { } |
| 206 | |
| 207 | /** |
| 208 | Determines how this controller will treat values received from the |
| 209 | X/Y axis and left/right buttons of the mouse. Since not all controllers |
| 210 | use the mouse the same way (or at all), it's up to the specific class to |
| 211 | decide how to use this data. |
| 212 | |
| 213 | In the current implementation, the left button is tied to the X axis, |
| 214 | and the right one tied to the Y axis. |
| 215 | |
| 216 | @param xtype The controller to use for x-axis data |
| 217 | @param xid The controller ID to use for x-axis data (-1 for no id) |
| 218 | @param ytype The controller to use for y-axis data |
| 219 | @param yid The controller ID to use for y-axis data (-1 for no id) |
| 220 | |
| 221 | @return Whether the controller supports using the mouse |
| 222 | */ |
| 223 | virtual bool setMouseControl( |
| 224 | Controller::Type xtype, int xid, Controller::Type ytype, int yid) |
| 225 | { return false; } |
| 226 | |
| 227 | /** |
| 228 | Returns more detailed information about this controller. |
| 229 | */ |
| 230 | virtual string about(bool swappedPorts) const |
| 231 | { |
| 232 | return name() + " in " + (((myJack == Jack::Left) ^ swappedPorts) ? |
| 233 | "left port" : "right port" ); |
| 234 | } |
| 235 | |
| 236 | /** |
| 237 | Saves the current state of this controller to the given Serializer. |
| 238 | |
| 239 | @param out The serializer device to save to. |
| 240 | @return The result of the save. True on success, false on failure. |
| 241 | */ |
| 242 | bool save(Serializer& out) const override; |
| 243 | |
| 244 | /** |
| 245 | Loads the current state of this controller from the given Serializer. |
| 246 | |
| 247 | @param in The serializer device to load from. |
| 248 | @return The result of the load. True on success, false on failure. |
| 249 | */ |
| 250 | bool load(Serializer& in) override; |
| 251 | |
| 252 | /** |
| 253 | Inject a callback to be notified on analog pin updates. |
| 254 | */ |
| 255 | void setOnAnalogPinUpdateCallback(onAnalogPinUpdateCallback callback) { |
| 256 | myOnAnalogPinUpdateCallback = callback; |
| 257 | } |
| 258 | |
| 259 | /** |
| 260 | Returns the display name of the given controller type |
| 261 | */ |
| 262 | static string getName(const Type type); |
| 263 | |
| 264 | /** |
| 265 | Returns the property name of the given controller type |
| 266 | */ |
| 267 | static string getPropName(const Type type); |
| 268 | |
| 269 | /** |
| 270 | Returns the controller type of the given property name |
| 271 | */ |
| 272 | static Type getType(const string& propName); |
| 273 | |
| 274 | public: |
| 275 | /// Constant which represents maximum resistance for analog pins |
| 276 | static constexpr Int32 MAX_RESISTANCE = 0x7FFFFFFF; |
| 277 | |
| 278 | /// Constant which represents minimum resistance for analog pins |
| 279 | static constexpr Int32 MIN_RESISTANCE = 0x00000000; |
| 280 | |
| 281 | protected: |
| 282 | /** |
| 283 | Derived classes *must* use these accessor/mutator methods. |
| 284 | The read/write methods above are meant to be used at a higher level. |
| 285 | */ |
| 286 | inline bool setPin(DigitalPin pin, bool value) { |
| 287 | return myDigitalPinState[static_cast<int>(pin)] = value; |
| 288 | } |
| 289 | inline bool getPin(DigitalPin pin) const { |
| 290 | return myDigitalPinState[static_cast<int>(pin)]; |
| 291 | } |
| 292 | inline void setPin(AnalogPin pin, Int32 value) { |
| 293 | myAnalogPinValue[static_cast<int>(pin)] = value; |
| 294 | if(myOnAnalogPinUpdateCallback) |
| 295 | myOnAnalogPinUpdateCallback(pin); |
| 296 | } |
| 297 | inline Int32 getPin(AnalogPin pin) const { |
| 298 | return myAnalogPinValue[static_cast<int>(pin)]; |
| 299 | } |
| 300 | inline void resetDigitalPins() { |
| 301 | setPin(DigitalPin::One, true); |
| 302 | setPin(DigitalPin::Two, true); |
| 303 | setPin(DigitalPin::Three, true); |
| 304 | setPin(DigitalPin::Four, true); |
| 305 | setPin(DigitalPin::Six, true); |
| 306 | } |
| 307 | inline void resetAnalogPins() { |
| 308 | setPin(AnalogPin::Five, MAX_RESISTANCE); |
| 309 | setPin(AnalogPin::Nine, MAX_RESISTANCE); |
| 310 | } |
| 311 | |
| 312 | protected: |
| 313 | /// Specifies which jack the controller is plugged in |
| 314 | const Jack myJack; |
| 315 | |
| 316 | /// Reference to the event object this controller uses |
| 317 | const Event& myEvent; |
| 318 | |
| 319 | /// Pointer to the System object (used for timing purposes) |
| 320 | const System& mySystem; |
| 321 | |
| 322 | /// Specifies which type of controller this is (defined by child classes) |
| 323 | const Type myType; |
| 324 | |
| 325 | /// The callback that is dispatched whenver an analog pin has changed |
| 326 | onAnalogPinUpdateCallback myOnAnalogPinUpdateCallback; |
| 327 | |
| 328 | private: |
| 329 | /// The boolean value on each digital pin |
| 330 | std::array<bool, 5> myDigitalPinState; |
| 331 | |
| 332 | /// The analog value on each analog pin |
| 333 | std::array<Int32, 2> myAnalogPinValue; |
| 334 | |
| 335 | private: |
| 336 | // Following constructors and assignment operators not supported |
| 337 | Controller() = delete; |
| 338 | Controller(const Controller&) = delete; |
| 339 | Controller(Controller&&) = delete; |
| 340 | Controller& operator=(const Controller&) = delete; |
| 341 | Controller& operator=(Controller&&) = delete; |
| 342 | }; |
| 343 | |
| 344 | #endif |
| 345 | |