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 "Event.hxx"
19#include "Booster.hxx"
20
21// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22BoosterGrip::BoosterGrip(Jack jack, const Event& event, const System& system)
23 : Controller(jack, event, system, Controller::Type::BoosterGrip),
24 myControlID(-1)
25{
26 if(myJack == Jack::Left)
27 {
28 myUpEvent = Event::JoystickZeroUp;
29 myDownEvent = Event::JoystickZeroDown;
30 myLeftEvent = Event::JoystickZeroLeft;
31 myRightEvent = Event::JoystickZeroRight;
32 myFireEvent = Event::JoystickZeroFire;
33 myTriggerEvent = Event::JoystickZeroFire5;
34 myBoosterEvent = Event::JoystickZeroFire9;
35 myXAxisValue = Event::PaddleZeroAnalog;
36 myYAxisValue = Event::PaddleOneAnalog;
37 }
38 else
39 {
40 myUpEvent = Event::JoystickOneUp;
41 myDownEvent = Event::JoystickOneDown;
42 myLeftEvent = Event::JoystickOneLeft;
43 myRightEvent = Event::JoystickOneRight;
44 myFireEvent = Event::JoystickOneFire;
45 myTriggerEvent = Event::JoystickOneFire5;
46 myBoosterEvent = Event::JoystickOneFire9;
47 myXAxisValue = Event::PaddleTwoAnalog;
48 myYAxisValue = Event::PaddleThreeAnalog;
49 }
50
51 setPin(AnalogPin::Five, MAX_RESISTANCE);
52 setPin(AnalogPin::Nine, MAX_RESISTANCE);
53}
54
55// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
56void BoosterGrip::update()
57{
58 // Digital events (from keyboard or joystick hats & buttons)
59 setPin(DigitalPin::One, myEvent.get(myUpEvent) == 0);
60 setPin(DigitalPin::Two, myEvent.get(myDownEvent) == 0);
61 setPin(DigitalPin::Three, myEvent.get(myLeftEvent) == 0);
62 setPin(DigitalPin::Four, myEvent.get(myRightEvent) == 0);
63 setPin(DigitalPin::Six, myEvent.get(myFireEvent) == 0);
64
65 // The CBS Booster-grip has two more buttons on it. These buttons are
66 // connected to the inputs usually used by paddles.
67 setPin(
68 AnalogPin::Five,
69 (myEvent.get(myTriggerEvent) != 0) ? MIN_RESISTANCE : MAX_RESISTANCE
70 );
71 setPin(
72 AnalogPin::Nine,
73 (myEvent.get(myBoosterEvent) != 0) ? MIN_RESISTANCE : MAX_RESISTANCE
74 );
75
76 // Axis events (usually generated by the Stelladaptor)
77 int xaxis = myEvent.get(myXAxisValue);
78 int yaxis = myEvent.get(myYAxisValue);
79 if(xaxis > 16384-4096)
80 {
81 setPin(DigitalPin::Four, false);
82 // Stelladaptor sends "half moved right" for L+R pushed together
83 if(xaxis < 16384+4096)
84 setPin(DigitalPin::Three, false);
85 }
86 else if(xaxis < -16384)
87 setPin(DigitalPin::Three, false);
88 if(yaxis > 16384-4096)
89 {
90 setPin(DigitalPin::Two, false);
91 // Stelladaptor sends "half moved down" for U+D pushed together
92 if(yaxis < 16384+4096)
93 setPin(DigitalPin::One, false);
94 }
95 else if(yaxis < -16384)
96 setPin(DigitalPin::One, false);
97
98 // Mouse motion and button events
99 if(myControlID > -1)
100 {
101 // The following code was taken from z26
102 #define MJ_Threshold 2
103 int mousex = myEvent.get(Event::MouseAxisXValue),
104 mousey = myEvent.get(Event::MouseAxisYValue);
105 if(mousex || mousey)
106 {
107 if((!(abs(mousey) > abs(mousex) << 1)) && (abs(mousex) >= MJ_Threshold))
108 {
109 if(mousex < 0)
110 setPin(DigitalPin::Three, false);
111 else if (mousex > 0)
112 setPin(DigitalPin::Four, false);
113 }
114
115 if((!(abs(mousex) > abs(mousey) << 1)) && (abs(mousey) >= MJ_Threshold))
116 {
117 if(mousey < 0)
118 setPin(DigitalPin::One, false);
119 else if(mousey > 0)
120 setPin(DigitalPin::Two, false);
121 }
122 }
123 // Get mouse button state
124 if(myEvent.get(Event::MouseButtonLeftValue))
125 setPin(DigitalPin::Six, false);
126 if(myEvent.get(Event::MouseButtonRightValue))
127 setPin(AnalogPin::Nine, MIN_RESISTANCE);
128 }
129}
130
131// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
132bool BoosterGrip::setMouseControl(
133 Controller::Type xtype, int xid, Controller::Type ytype, int yid)
134{
135 // Currently, the booster-grip takes full control of the mouse, using both
136 // axes for its two degrees of movement, and the left/right buttons for
137 // fire and booster, respectively
138 if(xtype == Controller::Type::BoosterGrip && ytype == Controller::Type::BoosterGrip &&
139 xid == yid)
140 {
141 myControlID = ((myJack == Jack::Left && xid == 0) ||
142 (myJack == Jack::Right && xid == 1)
143 ) ? xid : -1;
144 }
145 else
146 myControlID = -1;
147
148 return true;
149}
150