]> Shamusworld >> Repos - virtualjaguar/blob - src/joystick.cpp
91cfbbb0b661563c5c2caf3d77dbfd415ad9e4b1
[virtualjaguar] / src / joystick.cpp
1 //
2 // Joystick handler
3 //
4 // by cal2
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Extensive rewrite by James Hammons
7 // (C) 2013 Underground Software
8 //
9 // JLH = James Hammons <jlhamm@acm.org>
10 //
11 // Who  When        What
12 // ---  ----------  -------------------------------------------------------------
13 // JLH  01/16/2010  Created this log ;-)
14 //
15
16 #include "joystick.h"
17 #include <string.h>                     // For memset()
18 #include "gpu.h"
19 #include "jaguar.h"
20 #include "log.h"
21 #include "settings.h"
22
23 // Global vars
24
25 static uint8_t joystick_ram[4];
26 uint8_t joypad0Buttons[21];
27 uint8_t joypad1Buttons[21];
28 bool audioEnabled = false;
29 bool joysticksEnabled = false;
30
31
32 bool GUIKeyHeld = false;
33 extern int start_logging;
34 int gpu_start_log = 0;
35 int op_start_log = 0;
36 int blit_start_log = 0;
37 int effect_start = 0;
38 int effect_start2 = 0, effect_start3 = 0, effect_start4 = 0, effect_start5 = 0, effect_start6 = 0;
39 bool interactiveMode = false;
40 bool iLeft, iRight, iToggle = false;
41 bool keyHeld1 = false, keyHeld2 = false, keyHeld3 = false;
42 int objectPtr = 0;
43 bool startMemLog = false;
44 extern bool doDSPDis, doGPUDis;
45
46 bool blitterSingleStep = false;
47 bool bssGo = false;
48 bool bssHeld = false;
49
50
51 void JoystickInit(void)
52 {
53         JoystickReset();
54 }
55
56
57 void JoystickExec(void)
58 {
59         gpu_start_log = 0;                                                      // Only log while key down!
60         effect_start = 0;
61         effect_start2 = effect_start3 = effect_start4 = effect_start5 = effect_start6 = 0;
62         blit_start_log = 0;
63         iLeft = iRight = false;
64 }
65
66
67 void JoystickReset(void)
68 {
69         memset(joystick_ram, 0x00, 4);
70         memset(joypad0Buttons, 0, 21);
71         memset(joypad1Buttons, 0, 21);
72 }
73
74
75 void JoystickDone(void)
76 {
77 }
78
79
80 //uint8_t JoystickReadByte(uint32_t offset)
81 uint16_t JoystickReadWord(uint32_t offset)
82 {
83         // E, D, B, 7
84         uint8_t joypad0Offset[16] = {
85                 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0xFF, 0xFF, 0xFF, 0x08, 0xFF, 0x04, 0x00, 0xFF
86         };
87         uint8_t joypad1Offset[16] = {
88                 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x0C, 0xFF
89         };
90
91 #warning "No bounds checking done in JoystickReadByte!"
92         offset &= 0x03;
93
94         if (offset == 0)
95         {
96 #if 0
97                 uint8_t data = 0x00;
98                 int pad0Index = joystick_ram[1] & 0x0F;
99                 int pad1Index = (joystick_ram[1] >> 4) & 0x0F;
100
101 // This is bad--we're assuming that a bit is set in the last case. Might not be so!
102 // NOTE: values $7, B, D, & E are only legal ones for pad 0, (rows 3 to 0, in both cases)
103 //              $E, D, B, & 7 are only legal ones for pad 1
104 //       So the following code is WRONG! (now fixed! ;-)
105 // Also: we should explicitly check for those bit patterns, as other patterns
106 // are legal and yield other controllers... !!! FIX !!!
107 #warning "!!! Need to explicitly check for the proper bit combinations! !!!"
108
109                 if (!(pad0Index & 0x01))
110                         pad0Index = 0;
111                 else if (!(pad0Index & 0x02))
112                         pad0Index = 1;
113                 else if (!(pad0Index & 0x04))
114                         pad0Index = 2;
115                 else if (!(pad0Index & 0x08))
116                         pad0Index = 3;
117
118                 if (!(pad1Index & 0x01))
119                         pad1Index = 3;
120                 else if (!(pad1Index & 0x02))
121                         pad1Index = 2;
122                 else if (!(pad1Index & 0x04))
123                         pad1Index = 1;
124                 else if (!(pad1Index & 0x08))
125                         pad1Index = 0;
126
127                 if (joypad0Buttons[(pad0Index << 2) + 0]) data |= 0x01;
128                 if (joypad0Buttons[(pad0Index << 2) + 1]) data |= 0x02;
129                 if (joypad0Buttons[(pad0Index << 2) + 2]) data |= 0x04;
130                 if (joypad0Buttons[(pad0Index << 2) + 3]) data |= 0x08;
131                 if (joypad1Buttons[(pad1Index << 2) + 0]) data |= 0x10;
132                 if (joypad1Buttons[(pad1Index << 2) + 1]) data |= 0x20;
133                 if (joypad1Buttons[(pad1Index << 2) + 2]) data |= 0x40;
134                 if (joypad1Buttons[(pad1Index << 2) + 3]) data |= 0x80;
135
136                 return ~data;
137 #else
138                 if (!joysticksEnabled)
139                         return 0xFFFF;
140
141                 // Joystick data returns active low for buttons pressed, high for non-
142                 // pressed.
143                 uint16_t data = 0xFFFF;
144                 uint8_t offset0 = joypad0Offset[joystick_ram[1] & 0x0F];
145                 uint8_t offset1 = joypad1Offset[(joystick_ram[1] >> 4) & 0x0F];
146
147                 if (offset0 != 0xFF)
148                 {
149                         uint16_t mask[4] = { 0xFEFF, 0xFDFF, 0xFBFF, 0xF7FF };
150 //                      uint16_t mask[4] = { 0xFFFE, 0xFFFD, 0xFFFB, 0xFFF7 };
151
152                         for(uint8_t i=0; i<4; i++)
153                                 data &= (joypad0Buttons[offset0 + i] ? mask[i] : 0xFFFF);
154                 }
155
156                 if (offset1 != 0xFF)
157                 {
158                         uint16_t mask[4] = { 0xEFFF, 0xDFFF, 0xBFFF, 0x7FFF };
159 //                      uint16_t mask[4] = { 0xFFEF, 0xFFDF, 0xFFBF, 0xFF7F };
160
161                         for(uint8_t i=0; i<4; i++)
162                                 data &= (joypad1Buttons[offset1 + i] ? mask[i] : 0xFFFF);
163                 }
164
165                 return data;
166 #endif
167         }
168 //      else if (offset == 3)
169         else if (offset == 2)
170         {
171                 // Hardware ID returns NTSC/PAL identification bit here
172                 uint16_t data = 0xFFEF | (vjs.hardwareTypeNTSC ? 0x10 : 0x00);
173
174                 if (!joysticksEnabled)
175                         return data;
176 #if 0
177                 int pad0Index = joystick_ram[1] & 0x0F;
178                 int pad1Index = (joystick_ram[1] >> 4) & 0x0F;
179
180 //This is more stuff to add to the button reading, as the preceeding only
181 //yields 16 buttons...
182 #warning "!!! This reports TeamTap incorrectly when PAUSE pressed on controller #1 or #2 !!!"
183                 if (!(pad0Index & 0x01))
184                 {
185                         if (joypad0Buttons[BUTTON_PAUSE])
186                                 data ^= 0x01;
187                         if (joypad0Buttons[BUTTON_A])
188                                 data ^= 0x02;
189                 }
190                 else if (!(pad0Index & 0x02))
191                 {
192                         if (joypad0Buttons[BUTTON_B])
193                                 data ^= 0x02;
194                 }
195                 else if (!(pad0Index & 0x04))
196                 {
197                         if (joypad0Buttons[BUTTON_C])
198                                 data ^= 0x02;
199                 }
200                 else if (!(pad0Index & 0x08))
201                 {
202                         if (joypad0Buttons[BUTTON_OPTION])
203                                 data ^= 0x02;
204                 }
205
206                 if (!(pad1Index & 0x08))
207                 {
208                         if (joypad1Buttons[BUTTON_PAUSE])
209                                 data ^= 0x04;
210                         if (joypad1Buttons[BUTTON_A])
211                                 data ^= 0x08;
212                 }
213                 else if (!(pad1Index & 0x04))
214                 {
215                         if (joypad1Buttons[BUTTON_B])
216                                 data ^= 0x08;
217                 }
218                 else if (!(pad1Index & 0x02))
219                 {
220                         if (joypad1Buttons[BUTTON_C])
221                                 data ^= 0x08;
222                 }
223                 else if (!(pad1Index & 0x01))
224                 {
225                         if (joypad1Buttons[BUTTON_OPTION])
226                                 data ^= 0x08;
227                 }
228 #else
229                 // Joystick data returns active low for buttons pressed, high for non-
230                 // pressed.
231                 uint8_t offset0 = joypad0Offset[joystick_ram[1] & 0x0F] / 4;
232                 uint8_t offset1 = joypad1Offset[(joystick_ram[1] >> 4) & 0x0F] / 4;
233
234                 if (offset0 != 0xFF)
235                 {
236                         uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, -1 }, { BUTTON_C, -1 }, { BUTTON_OPTION, -1 } };
237                         data &= (joypad0Buttons[mask[offset0][0]] ? 0xFFFD : 0xFFFF);
238
239                         if (mask[offset0][1] != -1)
240                                 data &= (joypad0Buttons[mask[offset0][1]] ? 0xFFFE : 0xFFFF);
241                 }
242
243                 if (offset1 != 0xFF)
244                 {
245                         uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, -1 }, { BUTTON_C, -1 }, { BUTTON_OPTION, -1 } };
246                         data &= (joypad1Buttons[mask[offset1][0]] ? 0xFFF7 : 0xFFFF);
247
248                         if (mask[offset1][1] != -1)
249                                 data &= (joypad1Buttons[mask[offset1][1]] ? 0xFFFB : 0xFFFF);
250                 }
251 #endif
252
253                 return data;
254         }
255
256 //      return joystick_ram[offset];
257         return 0xFFFF;
258 }
259
260
261 #if 0
262 uint16_t JoystickReadWord(uint32_t offset)
263 {
264         return ((uint16_t)JoystickReadByte((offset + 0) & 0x03) << 8) | JoystickReadByte((offset + 1) & 0x03);
265 }
266 #endif
267
268
269 #if 0
270 void JoystickWriteByte(uint32_t offset, uint8_t data)
271 {
272         joystick_ram[offset & 0x03] = data;
273 }
274 #endif
275
276
277 void JoystickWriteWord(uint32_t offset, uint16_t data)
278 {
279 #warning "No bounds checking done for JoystickWriteWord!"
280         offset &= 0x03;
281         joystick_ram[offset + 0] = (data >> 8) & 0xFF;
282         joystick_ram[offset + 1] = data & 0xFF;
283
284         if (offset == 0)
285         {
286                 audioEnabled = (data & 0x0100 ? true : false);
287                 joysticksEnabled = (data & 0x8000 ? true : false);
288         }
289 }
290