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-2021 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 PADDLES_HXX 19 #define PADDLES_HXX 20 21 #include "bspf.hxx" 22 #include "Control.hxx" 23 #include "Event.hxx" 24 25 /** 26 The standard Atari 2600 pair of paddle controllers. 27 28 @author Bradford W. Mott 29 */ 30 class Paddles : public Controller 31 { 32 public: 33 /** 34 Create a new pair of paddle controllers plugged into the specified jack 35 36 @param jack The jack the controller is plugged into 37 @param event The event object to use for events 38 @param system The system using this controller 39 40 @param swappaddle Whether to swap the paddles plugged into this jack 41 @param swapaxis Whether to swap the axis on the paddle (x <-> y) 42 @param swapdir Whether to swap the direction for which an axis 43 causes movement (lesser axis values cause paddle 44 resistance to decrease instead of increase) 45 */ 46 Paddles(Jack jack, const Event& event, const System& system, 47 bool swappaddle, bool swapaxis, bool swapdir, bool altmap = false); 48 ~Paddles() override = default; 49 50 public: 51 static constexpr int ANALOG_MIN_VALUE = -32768; 52 static constexpr int ANALOG_MAX_VALUE = 32767; 53 static constexpr int ANALOG_RANGE = ANALOG_MAX_VALUE - ANALOG_MIN_VALUE + 1; 54 static constexpr float BASE_ANALOG_SENSE = 0.148643628F; 55 static constexpr int MIN_ANALOG_SENSE = 0; 56 static constexpr int MAX_ANALOG_SENSE = 30; 57 static constexpr int MIN_ANALOG_LINEARITY = 25; 58 static constexpr int MAX_ANALOG_LINEARITY = 100; 59 static constexpr int MIN_ANALOG_CENTER = -10; 60 static constexpr int MAX_ANALOG_CENTER = 30; 61 static constexpr int MIN_DIGITAL_SENSE = 1; 62 static constexpr int MAX_DIGITAL_SENSE = 20; 63 static constexpr int MIN_DEJITTER = 0; 64 static constexpr int MAX_DEJITTER = 10; 65 static constexpr int MIN_MOUSE_RANGE = 1; 66 static constexpr int MAX_MOUSE_RANGE = 100; 67 68 /** 69 Update the entire digital and analog pin state according to the 70 events currently set. 71 */ 72 void update() override; 73 74 /** 75 Returns the name of this controller. 76 */ name() const77 string name() const override { return "Paddles"; } 78 79 /** 80 Answers whether the controller is intrinsically an analog controller. 81 */ isAnalog() const82 bool isAnalog() const override { return true; } 83 84 /** 85 Determines how this controller will treat values received from the 86 X/Y axis and left/right buttons of the mouse. Since not all controllers 87 use the mouse the same way (or at all), it's up to the specific class to 88 decide how to use this data. 89 90 In the current implementation, the left button is tied to the X axis, 91 and the right one tied to the Y axis. 92 93 @param xtype The controller to use for x-axis data 94 @param xid The controller ID to use for x-axis data (-1 for no id) 95 @param ytype The controller to use for y-axis data 96 @param yid The controller ID to use for y-axis data (-1 for no id) 97 98 @return Whether the controller supports using the mouse 99 */ 100 bool setMouseControl(Controller::Type xtype, int xid, 101 Controller::Type ytype, int yid) override; 102 103 /** 104 Sets the x-center for analog paddles. 105 106 @param xcenter Value from -10 to 30, representing the center offset/860 107 */ 108 static void setAnalogXCenter(int xcenter); 109 110 /** 111 Sets the y-center for analog paddles. 112 113 @param ycenter Value from -10 to 30, representing the center offset/860 114 */ 115 static void setAnalogYCenter(int ycenter); 116 117 /** 118 Sets the linearity of analog paddles. 119 120 @param linearity Value from 25 to 100 121 */ 122 static void setAnalogLinearity(int linearity); 123 124 /** 125 Sets the sensitivity for analog paddles. 126 127 @param sensitivity Value from 0 to 30, where 20 equals 1 128 @return Resulting sensitivity 129 */ 130 static float setAnalogSensitivity(int sensitivity); 131 132 static float analogSensitivityValue(int sensitivity); 133 134 135 /** 136 @param strength Value from 0 to 10 137 */ 138 static void setDejitterBase(int strength); 139 140 /** 141 @param strength Value from 0 to 10 142 */ 143 static void setDejitterDiff(int strength); 144 145 /** 146 Sets the sensitivity for digital emulation of paddle movement. 147 This is only used for *digital* events (ie, buttons or keys, 148 or digital joystick axis events); Stelladaptors or the mouse are 149 not modified. 150 151 @param sensitivity Value from 1 to MAX_DIGITAL_SENSE, with larger 152 values causing more movement 153 */ 154 static void setDigitalSensitivity(int sensitivity); 155 156 /** 157 Sets the maximum upper range for digital/mouse emulation of paddle 158 movement (ie, a value of 50 means to only use 50% of the possible 159 range of movement). Note that this specfically does not apply to 160 Stelladaptor-like devices, which uses an absolute value range. 161 162 @param range Value from 1 to 100, representing the percentage 163 of the range to use 164 */ 165 static void setDigitalPaddleRange(int range); 166 167 // The maximum value of the paddle pot = 1MOhm 168 static constexpr uInt32 MAX_RESISTANCE = 1000000; 169 170 private: 171 // Range of values over which digital and mouse movement is scaled 172 // to paddle resistance 173 static constexpr int TRIGMIN = 1; 174 static constexpr int TRIGMAX = 4096; 175 static int TRIGRANGE; // This one is variable for the upper range 176 177 // Pre-compute the events we care about based on given port 178 // This will eliminate test for left or right port in update() 179 Event::Type myAAxisValue, myBAxisValue, 180 myLeftADecEvent, myLeftAIncEvent, 181 myLeftBDecEvent, myLeftBIncEvent, 182 myLeftAFireEvent, myLeftBFireEvent, 183 myAxisMouseMotion; 184 185 // The following are used for the various mouse-axis modes 186 int myMPaddleID{-1}; // paddle to emulate in 'automatic' mode 187 int myMPaddleIDX{-1}, myMPaddleIDY{-1}; // paddles to emulate in 'specific axis' mode 188 189 bool myKeyRepeatA{false}, myKeyRepeatB{false}; 190 int myPaddleRepeatA{0}, myPaddleRepeatB{0}; 191 std::array<int, 2> myCharge{TRIGRANGE/2, TRIGRANGE/2}, myLastCharge{0}; 192 int myLastAxisX{0}, myLastAxisY{0}; 193 int myAxisDigitalZero{0}, myAxisDigitalOne{0}; 194 195 static int XCENTER; 196 static int YCENTER; 197 static float SENSITIVITY, LINEARITY; 198 199 static int DIGITAL_SENSITIVITY, DIGITAL_DISTANCE; 200 static int DEJITTER_BASE, DEJITTER_DIFF; 201 202 /** 203 Swap two events. 204 */ 205 void swapEvents(Event::Type& event1, Event::Type& event2); 206 207 AnalogReadout::Connection getReadOut(int lastAxis, int& newAxis, int center); 208 209 /** 210 Update the axes pin state according to the events currently set. 211 */ 212 bool updateAnalogAxes(); 213 214 /** 215 Update the entire state according to mouse events currently set. 216 */ 217 void updateMouse(bool& firePressedA, bool& firePressedB); 218 219 /** 220 Update the axes pin state according to the keyboard events currently set. 221 */ 222 void updateDigitalAxes(); 223 224 private: 225 // Following constructors and assignment operators not supported 226 Paddles() = delete; 227 Paddles(const Paddles&) = delete; 228 Paddles(Paddles&&) = delete; 229 Paddles& operator=(const Paddles&) = delete; 230 Paddles& operator=(Paddles&&) = delete; 231 }; 232 233 #endif 234