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-2014 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 // $Id: CompuMate.cxx 2838 2014-01-17 23:34:03Z stephena $
18 //============================================================================
19
20 #include "Control.hxx"
21 #include "System.hxx"
22 #include "StellaKeys.hxx"
23 #include "CompuMate.hxx"
24
25 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CompuMate(CartridgeCM & cart,const Event & event,const System & system)26 CompuMate::CompuMate(CartridgeCM& cart, const Event& event,
27 const System& system)
28 : myCart(cart),
29 myEvent(event),
30 mySystem(system),
31 myLeftController(0),
32 myRightController(0),
33 myCycleAtLastUpdate(0)
34 {
35 myLeftController = new CMControl(*this, Controller::Left, event, system);
36 myRightController = new CMControl(*this, Controller::Right, event, system);
37
38 myLeftController->myAnalogPinValue[Controller::Nine] = Controller::maximumResistance;
39 myLeftController->myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
40 myRightController->myAnalogPinValue[Controller::Nine] = Controller::minimumResistance;
41 myRightController->myAnalogPinValue[Controller::Five] = Controller::maximumResistance;
42 }
43
44 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
enableKeyHandling(bool enable)45 void CompuMate::enableKeyHandling(bool enable)
46 {
47 if(enable)
48 myKeyTable = myEvent.getKeys();
49 else
50 {
51 for(uInt32 i = 0; i < KBDK_LAST; ++i)
52 myInternalKeyTable[i] = false;
53
54 myKeyTable = myInternalKeyTable;
55 }
56 }
57
58 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
update()59 void CompuMate::update()
60 {
61 uInt32 cycle = mySystem.cycles();
62
63 // Only perform update once for both ports in the same cycle
64 if(myCycleAtLastUpdate != cycle)
65 {
66 myCycleAtLastUpdate = cycle;
67 return;
68 }
69 myCycleAtLastUpdate = cycle;
70
71 // Handle SWCHA changes - the following comes almost directly from z26
72 Controller& lp = *myLeftController;
73 Controller& rp = *myRightController;
74
75 lp.myAnalogPinValue[Controller::Nine] = Controller::maximumResistance;
76 lp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
77 lp.myDigitalPinState[Controller::Six] = true;
78 rp.myAnalogPinValue[Controller::Nine] = Controller::minimumResistance;
79 rp.myAnalogPinValue[Controller::Five] = Controller::maximumResistance;
80 rp.myDigitalPinState[Controller::Six] = true;
81
82 if (myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT])
83 rp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
84 if (myKeyTable[KBDK_LCTRL] || myKeyTable[KBDK_RCTRL])
85 lp.myAnalogPinValue[Controller::Nine] = Controller::minimumResistance;
86
87 rp.myDigitalPinState[Controller::Three] = true;
88 rp.myDigitalPinState[Controller::Four] = true;
89 switch(myCart.column())
90 {
91 case 0:
92 if (myKeyTable[KBDK_7]) lp.myDigitalPinState[Controller::Six] = false;
93 if (myKeyTable[KBDK_u]) rp.myDigitalPinState[Controller::Three] = false;
94 if (myKeyTable[KBDK_j]) rp.myDigitalPinState[Controller::Six] = false;
95 if (myKeyTable[KBDK_m]) rp.myDigitalPinState[Controller::Four] = false;
96 break;
97 case 1:
98 if (myKeyTable[KBDK_6]) lp.myDigitalPinState[Controller::Six] = false;
99 // Emulate the '?' character (Shift-6) with the actual question key
100 if (myKeyTable[KBDK_SLASH] && (myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
101 {
102 rp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
103 lp.myDigitalPinState[Controller::Six] = false;
104 }
105 if (myKeyTable[KBDK_y]) rp.myDigitalPinState[Controller::Three] = false;
106 if (myKeyTable[KBDK_h]) rp.myDigitalPinState[Controller::Six] = false;
107 if (myKeyTable[KBDK_n]) rp.myDigitalPinState[Controller::Four] = false;
108 break;
109 case 2:
110 if (myKeyTable[KBDK_8]) lp.myDigitalPinState[Controller::Six] = false;
111 // Emulate the '[' character (Shift-8) with the actual key
112 if (myKeyTable[KBDK_LEFTBRACKET] && !(myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
113 {
114 rp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
115 lp.myDigitalPinState[Controller::Six] = false;
116 }
117 if (myKeyTable[KBDK_i]) rp.myDigitalPinState[Controller::Three] = false;
118 if (myKeyTable[KBDK_k]) rp.myDigitalPinState[Controller::Six] = false;
119 if (myKeyTable[KBDK_COMMA]) rp.myDigitalPinState[Controller::Four] = false;
120 break;
121 case 3:
122 if (myKeyTable[KBDK_2]) lp.myDigitalPinState[Controller::Six] = false;
123 // Emulate the '-' character (Shift-2) with the actual minus key
124 if (myKeyTable[KBDK_MINUS] && !(myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
125 {
126 rp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
127 lp.myDigitalPinState[Controller::Six] = false;
128 }
129 if (myKeyTable[KBDK_w]) rp.myDigitalPinState[Controller::Three] = false;
130 if (myKeyTable[KBDK_s]) rp.myDigitalPinState[Controller::Six] = false;
131 if (myKeyTable[KBDK_x]) rp.myDigitalPinState[Controller::Four] = false;
132 break;
133 case 4:
134 if (myKeyTable[KBDK_3]) lp.myDigitalPinState[Controller::Six] = false;
135 if (myKeyTable[KBDK_e]) rp.myDigitalPinState[Controller::Three] = false;
136 if (myKeyTable[KBDK_d]) rp.myDigitalPinState[Controller::Six] = false;
137 if (myKeyTable[KBDK_c]) rp.myDigitalPinState[Controller::Four] = false;
138 break;
139 case 5:
140 if (myKeyTable[KBDK_0]) lp.myDigitalPinState[Controller::Six] = false;
141 // Emulate the quote character (Shift-0) with the actual quote key
142 if (myKeyTable[KBDK_QUOTE] && (myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
143 {
144 rp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
145 lp.myDigitalPinState[Controller::Six] = false;
146 }
147 if (myKeyTable[KBDK_p]) rp.myDigitalPinState[Controller::Three] = false;
148 if (myKeyTable[KBDK_RETURN] || myKeyTable[KBDK_KP_ENTER])
149 rp.myDigitalPinState[Controller::Six] = false;
150 if (myKeyTable[KBDK_SPACE]) rp.myDigitalPinState[Controller::Four] = false;
151 // Emulate Ctrl-space (aka backspace) with the actual Backspace key
152 if (myKeyTable[KBDK_BACKSPACE])
153 {
154 lp.myAnalogPinValue[Controller::Nine] = Controller::minimumResistance;
155 rp.myDigitalPinState[Controller::Four] = false;
156 }
157 break;
158 case 6:
159 if (myKeyTable[KBDK_9]) lp.myDigitalPinState[Controller::Six] = false;
160 // Emulate the ']' character (Shift-9) with the actual key
161 if (myKeyTable[KBDK_RIGHTBRACKET] && !(myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
162 {
163 rp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
164 lp.myDigitalPinState[Controller::Six] = false;
165 }
166 if (myKeyTable[KBDK_o]) rp.myDigitalPinState[Controller::Three] = false;
167 if (myKeyTable[KBDK_l]) rp.myDigitalPinState[Controller::Six] = false;
168 if (myKeyTable[KBDK_PERIOD]) rp.myDigitalPinState[Controller::Four] = false;
169 break;
170 case 7:
171 if (myKeyTable[KBDK_5]) lp.myDigitalPinState[Controller::Six] = false;
172 // Emulate the '=' character (Shift-5) with the actual equals key
173 if (myKeyTable[KBDK_EQUALS] && !(myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
174 {
175 rp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
176 lp.myDigitalPinState[Controller::Six] = false;
177 }
178 if (myKeyTable[KBDK_t]) rp.myDigitalPinState[Controller::Three] = false;
179 if (myKeyTable[KBDK_g]) rp.myDigitalPinState[Controller::Six] = false;
180 if (myKeyTable[KBDK_b]) rp.myDigitalPinState[Controller::Four] = false;
181 break;
182 case 8:
183 if (myKeyTable[KBDK_1]) lp.myDigitalPinState[Controller::Six] = false;
184 // Emulate the '+' character (Shift-1) with the actual plus key (Shift-=)
185 if (myKeyTable[KBDK_EQUALS] && (myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
186 {
187 rp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
188 lp.myDigitalPinState[Controller::Six] = false;
189 }
190 if (myKeyTable[KBDK_q]) rp.myDigitalPinState[Controller::Three] = false;
191 if (myKeyTable[KBDK_a]) rp.myDigitalPinState[Controller::Six] = false;
192 if (myKeyTable[KBDK_z]) rp.myDigitalPinState[Controller::Four] = false;
193 break;
194 case 9:
195 if (myKeyTable[KBDK_4]) lp.myDigitalPinState[Controller::Six] = false;
196 // Emulate the '/' character (Shift-4) with the actual slash key
197 if (myKeyTable[KBDK_SLASH] && !(myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
198 {
199 rp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
200 lp.myDigitalPinState[Controller::Six] = false;
201 }
202 if (myKeyTable[KBDK_r]) rp.myDigitalPinState[Controller::Three] = false;
203 if (myKeyTable[KBDK_f]) rp.myDigitalPinState[Controller::Six] = false;
204 if (myKeyTable[KBDK_v]) rp.myDigitalPinState[Controller::Four] = false;
205 break;
206 default:
207 break;
208 }
209 }
210