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