]> Shamusworld >> Repos - virtualjaguar/blob - src/joystick.cpp
Fix for joysticks to behave more like real H/W.
[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 uint16_t JoystickReadWord(uint32_t offset)
81 {
82         // E, D, B, 7
83         uint8_t joypad0Offset[16] = {
84                 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0xFF, 0xFF, 0xFF, 0x08, 0xFF, 0x04, 0x00, 0xFF
85         };
86         uint8_t joypad1Offset[16] = {
87                 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x0C, 0xFF
88         };
89
90 #warning "No bounds checking done in JoystickReadByte!"
91         offset &= 0x03;
92
93         if (offset == 0)
94         {
95                 if (!joysticksEnabled)
96                         return 0xFFFF;
97
98                 // Joystick data returns active low for buttons pressed, high for non-
99                 // pressed.
100                 uint16_t data = 0xFFFF;
101                 uint8_t offset0 = joypad0Offset[joystick_ram[1] & 0x0F];
102                 uint8_t offset1 = joypad1Offset[(joystick_ram[1] >> 4) & 0x0F];
103
104                 if (offset0 != 0xFF)
105                 {
106                         uint16_t mask[4] = { 0xFEFF, 0xFDFF, 0xFBFF, 0xF7FF };
107                         uint16_t msk2[4] = { 0xFFFF, 0xFFFD, 0xFFFB, 0xFFF7 };
108
109                         for(uint8_t i=0; i<4; i++)
110                                 data &= (joypad0Buttons[offset0 + i] ? mask[i] : 0xFFFF);
111
112                         data &= msk2[offset0 / 4];
113                 }
114
115                 if (offset1 != 0xFF)
116                 {
117                         uint16_t mask[4] = { 0xEFFF, 0xDFFF, 0xBFFF, 0x7FFF };
118                         uint16_t msk2[4] = { 0xFF7F, 0xFFBF, 0xFFDF, 0xFFEF };
119
120                         for(uint8_t i=0; i<4; i++)
121                                 data &= (joypad1Buttons[offset1 + i] ? mask[i] : 0xFFFF);
122
123                         data &= msk2[offset1 / 4];
124                 }
125
126                 return data;
127         }
128         else if (offset == 2)
129         {
130                 // Hardware ID returns NTSC/PAL identification bit here
131                 // N.B.: On real H/W, bit 7 is *always* zero...!
132                 uint16_t data = 0xFF6F | (vjs.hardwareTypeNTSC ? 0x10 : 0x00);
133
134                 if (!joysticksEnabled)
135                         return data;
136
137                 // Joystick data returns active low for buttons pressed, high for non-
138                 // pressed.
139                 uint8_t offset0 = joypad0Offset[joystick_ram[1] & 0x0F];
140                 uint8_t offset1 = joypad1Offset[(joystick_ram[1] >> 4) & 0x0F];
141
142                 if (offset0 != 0xFF)
143                 {
144                         offset0 /= 4;   // Make index 0, 1, 2, 3 instead of 0, 4, 8, 12
145                         uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, 0xFF }, { BUTTON_C, 0xFF }, { BUTTON_OPTION, 0xFF } };
146                         data &= (joypad0Buttons[mask[offset0][0]] ? 0xFFFD : 0xFFFF);
147
148                         if (mask[offset0][1] != 0xFF)
149                                 data &= (joypad0Buttons[mask[offset0][1]] ? 0xFFFE : 0xFFFF);
150                 }
151
152                 if (offset1 != 0xFF)
153                 {
154                         offset1 /= 4;   // Make index 0, 1, 2, 3 instead of 0, 4, 8, 12
155                         uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, 0xFF }, { BUTTON_C, 0xFF }, { BUTTON_OPTION, 0xFF } };
156                         data &= (joypad1Buttons[mask[offset1][0]] ? 0xFFF7 : 0xFFFF);
157
158                         if (mask[offset1][1] != 0xFF)
159                                 data &= (joypad1Buttons[mask[offset1][1]] ? 0xFFFB : 0xFFFF);
160                 }
161
162                 return data;
163         }
164
165         return 0xFFFF;
166 }
167
168
169 void JoystickWriteWord(uint32_t offset, uint16_t data)
170 {
171 #warning "No bounds checking done for JoystickWriteWord!"
172         offset &= 0x03;
173         joystick_ram[offset + 0] = (data >> 8) & 0xFF;
174         joystick_ram[offset + 1] = data & 0xFF;
175
176         if (offset == 0)
177         {
178                 audioEnabled = (data & 0x0100 ? true : false);
179                 joysticksEnabled = (data & 0x8000 ? true : false);
180         }
181 }
182