1 /*---------------------------------------------------------------------------*
2 Project: Game controller utilities
3 File: cont.c
4
5 Copyright 2000-2001 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Log: cont.c,v $
14 Revision 1.2 02/20/2006 04:13:08 mitu
15 changed include path from dolphin/ to revolution/.
16
17 Revision 1.1 01/31/2006 10:48:30 mitu
18 (none)
19
20
21 8 8/06/01 18:29 Shiki
22 Revised ReadCont().
23
24 7 01/03/27 13:16 Shiki
25 Fixed ReadCont().
26
27 6 01/03/23 15:06 Shiki
28 Fixed resetBits handling.
29
30 5 01/03/22 21:07:00 Shiki
31 Revised.
32
33 4 01/03/06 17:18 Shiki
34 Modified InitCont() to support controller recalibration.
35
36 3 01/03/06 15:51:00 Shiki
37 Fixed ReadCont() so it can work even if no controller is connected
38 initially.
39
40 2 11/14/00 3:02p Shiki
41 Fixed MAC build error.
42
43 1 11/13/00 6:02p Shiki
44 Initial check-in.
45 $NoKeywords: $
46 *---------------------------------------------------------------------------*/
47
48 #include <stdlib.h>
49 #include <revolution.h>
50 #include "cont.h"
51
52 Cont Conts[PAD_MAX_CONTROLLERS+1];
53 static int RepeatDelay;
54 static int RepeatRate;
55 static u32 ConnectedBits;
56
57 /*---------------------------------------------------------------------------*
58 Name: InitCont
59
60 Description: Reinitializes controllers
61
62 Arguments: connectBits Set PAD_CHANn_BIT(s) to try to connect to the
63 specified controller ports at every frame no
64 matter what.
65 Set zero to use controllers that initially
66 connected to the controller ports to minimize
67 extra processor overhead.
68 recalibrate Set TRUE to recalibrate controllers. (Should
69 be set TRUE only when the reset button on the
70 console is pushed.)
71
72 Returns: None.
73 *---------------------------------------------------------------------------*/
InitCont(u32 connectBits,BOOL recalibrate)74 void InitCont(u32 connectBits, BOOL recalibrate)
75 {
76 u32 resetBits;
77
78 if (VIGetTvFormat() == VI_PAL)
79 {
80 // 50Hz
81 RepeatDelay = 25;
82 RepeatRate = 5;
83 }
84 else // VI_NTSC, VI_MPAL
85 {
86 // 60Hz
87 RepeatDelay = 30;
88 RepeatRate = 6;
89 }
90
91 ConnectedBits = connectBits;
92 resetBits = PAD_CHAN0_BIT | PAD_CHAN1_BIT |
93 PAD_CHAN2_BIT | PAD_CHAN3_BIT;
94 if (ConnectedBits)
95 {
96 resetBits &= ConnectedBits;
97 }
98 if (recalibrate)
99 {
100 PADRecalibrate(resetBits);
101 }
102 else
103 {
104 PADReset(resetBits);
105 }
106 }
107
108 /*---------------------------------------------------------------------------*
109 Name: ReadCont
110
111 Description: Read controllers
112
113 Arguments: None.
114
115 Returns: None.
116 *---------------------------------------------------------------------------*/
ReadCont(void)117 void ReadCont(void)
118 {
119 PADStatus pads[PAD_MAX_CONTROLLERS];
120 PADStatus* pad;
121 u32 padBit;
122 int chan;
123 Cont* cont;
124 Cont* contAll;
125 u32 resetBits;
126
127 PADRead(pads);
128 PADClamp(pads);
129
130 contAll = &Conts[PAD_MAX_CONTROLLERS];
131 contAll->err = PAD_ERR_NO_CONTROLLER;
132
133 resetBits = 0;
134 for (chan = 0; chan < PAD_MAX_CONTROLLERS; ++chan)
135 {
136 padBit = PAD_CHAN0_BIT >> chan;
137 switch (pads[chan].err)
138 {
139 case PAD_ERR_NONE:
140 ConnectedBits |= padBit;
141 contAll->err = PAD_ERR_NONE;
142 break;
143 case PAD_ERR_TRANSFER:
144 ConnectedBits |= padBit;
145 if (contAll->err == PAD_ERR_NO_CONTROLLER)
146 {
147 contAll->err = PAD_ERR_TRANSFER;
148 }
149 break;
150 case PAD_ERR_NO_CONTROLLER:
151 resetBits |= padBit;
152 break;
153 case PAD_ERR_NOT_READY:
154 if (contAll->err == PAD_ERR_NO_CONTROLLER)
155 {
156 contAll->err = PAD_ERR_NOT_READY;
157 }
158 default:
159 break;
160 }
161 }
162 if (ConnectedBits)
163 {
164 resetBits &= ConnectedBits;
165 }
166 if (resetBits)
167 {
168 PADReset(resetBits);
169 }
170
171 contAll->buttonLast = contAll->button;
172 contAll->button = contAll->down = contAll->up = contAll->repeat = 0;
173 contAll->stickX = contAll->stickY = contAll->substickX = contAll->substickY = 0;
174 contAll->triggerLeft = contAll->triggerRight = 0;
175 contAll->analogA = contAll->analogB = 0;
176
177 for (chan = 0; chan < PAD_MAX_CONTROLLERS; ++chan)
178 {
179 cont = &Conts[chan];
180 pad = &pads[chan];
181 cont->err = pad->err;
182
183 cont->buttonLast = cont->button; // not to generate up/down twice
184 if (cont->err != PAD_ERR_TRANSFER)
185 {
186 cont->button = pad->button;
187 cont->stickX = pad->stickX;
188 cont->stickY = pad->stickY;
189 cont->substickX = pad->substickX;
190 cont->substickY = pad->substickY;
191 cont->triggerLeft = pad->triggerLeft;
192 cont->triggerRight = pad->triggerRight;
193 cont->analogA = pad->analogA;
194 cont->analogB = pad->analogB;
195 }
196
197 if (cont->stickX < 0)
198 {
199 cont->button |= PAD_BUTTON_LEFT;
200 }
201 else if (0 < cont->stickX)
202 {
203 cont->button |= PAD_BUTTON_RIGHT;
204 }
205 if (cont->stickY < 0)
206 {
207 cont->button |= PAD_BUTTON_DOWN;
208 }
209 else if (0 < cont->stickY)
210 {
211 cont->button |= PAD_BUTTON_UP;
212 }
213
214 cont->down = PADButtonDown(cont->buttonLast, cont->button);
215 cont->up = PADButtonUp(cont->buttonLast, cont->button);
216
217 cont->repeat = (u16) ((cont->button & cont->buttonLast) &
218 (PAD_BUTTON_A | PAD_BUTTON_B | PAD_BUTTON_X | PAD_BUTTON_Y |
219 PAD_TRIGGER_Z | PAD_TRIGGER_R | PAD_TRIGGER_L |
220 PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT |
221 PAD_BUTTON_DOWN | PAD_BUTTON_UP |
222 PAD_BUTTON_START));
223 if (cont->repeat)
224 {
225 ++cont->count;
226 if (cont->count < RepeatDelay)
227 {
228 cont->repeat = 0;
229 }
230 else if (cont->count % RepeatRate)
231 {
232 cont->repeat = 0;
233 }
234 }
235 else
236 {
237 cont->count = 0;
238 }
239 cont->repeat |= cont->down;
240
241 contAll->down |= cont->down;
242 contAll->up |= cont->up;
243 contAll->button |= cont->button;
244 contAll->repeat |= cont->repeat;
245
246 if (abs(contAll->stickX) < abs(cont->stickX))
247 {
248 contAll->stickX = cont->stickX;
249 }
250 if (abs(contAll->stickY) < abs(cont->stickY))
251 {
252 contAll->stickY = cont->stickY;
253 }
254 if (abs(contAll->substickX) < abs(cont->substickX))
255 {
256 contAll->substickX = cont->substickX;
257 }
258 if (abs(contAll->substickY) < abs(cont->substickY))
259 {
260 contAll->substickY = cont->substickY;
261 }
262 if (contAll->triggerLeft < cont->triggerLeft)
263 {
264 contAll->triggerLeft = cont->triggerLeft;
265 }
266 if (contAll->triggerRight < cont->triggerRight)
267 {
268 contAll->triggerRight = cont->triggerRight;
269 }
270 if (contAll->analogA < cont->analogA)
271 {
272 contAll->analogA = cont->analogA;
273 }
274 if (contAll->analogB < cont->analogB)
275 {
276 contAll->analogB = cont->analogB;
277 }
278 }
279 }
280