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