source: ps2launchargs/source/uLaunchELF/pad.c@ 1109

Last change on this file since 1109 was 1101, checked in by iritscen, 7 years ago

Added following to ps2launchargs:\n-Source code.\n-DLL needed to run ps2client.\n-Instructions for building uLaunchELF.

  • Property svn:executable set to *
File size: 12.0 KB
Line 
1//---------------------------------------------------------------------------
2// File name: pad.c
3//---------------------------------------------------------------------------
4#include "launchelf.h"
5
6static char padBuf_t[2][256] __attribute__((aligned(64)));
7struct padButtonStatus buttons_t[2];
8u32 padtype_t[2];
9u32 paddata, paddata_t[2];
10u32 old_pad = 0, old_pad_t[2] = {0, 0};
11u32 new_pad, new_pad_t[2];
12u32 joy_value = 0;
13static int test_joy = 0;
14
15//---------------------------------------------------------------------------
16// read PAD, without KB, and allow no auto-repeat. This is needed in code
17// that is used regardless of VSync cycles, and where KB is not wanted.
18//---------------------------------------------------------------------------
19int readpad_noKBnoRepeat(void)
20{
21 int port, state, ret[2];
22
23 for(port=0; port<2; port++){
24 if((state=padGetState(port, 0))==PAD_STATE_STABLE
25 ||(state == PAD_STATE_FINDCTP1)){
26 //Deal with cases where pad state is valid for padRead
27 ret[port] = padRead(port, 0, &buttons_t[port]);
28 if (ret[port] != 0){
29 paddata_t[port] = 0xffff ^ buttons_t[port].btns;
30 new_pad_t[port] = paddata_t[port] & ~old_pad_t[port];
31 old_pad_t[port] = paddata_t[port];
32 }
33 }else{
34 //Deal with cases where pad state is not valid for padRead
35 new_pad_t[port]=0;
36 } //ends 'if' testing for state valid for padRead
37 } //ends for
38 new_pad = new_pad_t[0]|new_pad_t[1]; //This has only new button bits
39 paddata = paddata_t[0]|paddata_t[1]; //This has all pressed button bits
40 return (ret[0]|ret[1]);
41}
42//------------------------------
43//endfunc readpad_noKBnoRepeat
44//---------------------------------------------------------------------------
45// read PAD, but ignore KB. This is needed in code with own KB handlers,
46// such as the virtual keyboard input routines for 'Rename' and 'New Dir'
47//---------------------------------------------------------------------------
48int readpad_no_KB(void)
49{
50 static u64 rpt_time[2]={0,0};
51 static int rpt_count[2];
52 int port, state, ret[2];
53
54 for(port=0; port<2; port++){
55 if((state=padGetState(port, 0))==PAD_STATE_STABLE
56 ||(state == PAD_STATE_FINDCTP1)){
57 //Deal with cases where pad state is valid for padRead
58 ret[port] = padRead(port, 0, &buttons_t[port]);
59 if (ret[port] != 0){
60 paddata_t[port] = 0xffff ^ buttons_t[port].btns;
61 if((padtype_t[port] == 2) && (1 & (test_joy++))){//DualShock && time for joy scan
62 joy_value=0;
63 if(buttons_t[port].rjoy_h >= 0xbf){
64 paddata_t[port]=PAD_R3_H1;
65 joy_value=buttons_t[port].rjoy_h-0xbf;
66 }else if(buttons_t[port].rjoy_h <= 0x40){
67 paddata_t[port]=PAD_R3_H0;
68 joy_value=-(buttons_t[port].rjoy_h-0x40);
69 }else if(buttons_t[port].rjoy_v <= 0x40){
70 paddata_t[port]=PAD_R3_V0;
71 joy_value=-(buttons_t[port].rjoy_v-0x40);
72 }else if(buttons_t[port].rjoy_v >= 0xbf){
73 paddata_t[port]=PAD_R3_V1;
74 joy_value=buttons_t[port].rjoy_v-0xbf;
75 }else if(buttons_t[port].ljoy_h >= 0xbf){
76 paddata_t[port]=PAD_L3_H1;
77 joy_value=buttons_t[port].ljoy_h-0xbf;
78 }else if(buttons_t[port].ljoy_h <= 0x40){
79 paddata_t[port]=PAD_L3_H0;
80 joy_value=-(buttons_t[port].ljoy_h-0x40);
81 }else if(buttons_t[port].ljoy_v <= 0x40){
82 paddata_t[port]=PAD_L3_V0;
83 joy_value=-(buttons_t[port].ljoy_v-0x40);
84 }else if(buttons_t[port].ljoy_v >= 0xbf){
85 paddata_t[port]=PAD_L3_V1;
86 joy_value=buttons_t[port].ljoy_v-0xbf;
87 }
88 }
89 new_pad_t[port] = paddata_t[port] & ~old_pad_t[port];
90 if(old_pad_t[port] == paddata_t[port]){
91 //no change of pad data
92 if(Timer() > rpt_time[port]){
93 new_pad_t[port]=paddata_t[port]; //Accept repeated buttons as new
94 rpt_time[port] = Timer() + 40; //Min delay = 40ms => 25Hz repeat
95 if(rpt_count[port]++ < 20)
96 rpt_time[port] += 43; //Early delays = 83ms => 12Hz repeat
97 }
98 }else{
99 //pad data has changed !
100 rpt_count[port] = 0;
101 rpt_time[port] = Timer()+400; //Init delay = 400ms
102 old_pad_t[port] = paddata_t[port];
103 }
104 }
105 }else{
106 //Deal with cases where pad state is not valid for padRead
107 //NB: This should NOT clear KB repeat test variables
108 new_pad_t[port]=0;
109 //old_pad_t[port]=0; //Clearing this could cause hasty repeats
110 } //ends 'if' testing for state valid for padRead
111 } //ends for
112 new_pad = new_pad_t[0]|new_pad_t[1];
113 paddata = paddata_t[0]|paddata_t[1]; //This has all pressed button bits
114 return (ret[0]|ret[1]);
115}
116//------------------------------
117//endfunc readpad_no_KB
118//---------------------------------------------------------------------------
119// simPadKB attempts reading data from a USB keyboard, and map this as a
120// virtual gamepad. (Very improvised and sloppy, but it should work fine.)
121//---------------------------------------------------------------------------
122int simPadKB(void)
123{
124 int ret, command;
125 unsigned char KeyPress;
126
127 if((!setting->usbkbd_used)||(!PS2KbdRead(&KeyPress)))
128 return 0;
129 if(KeyPress != PS2KBD_ESCAPE_KEY)
130 command = KeyPress;
131 else {
132 PS2KbdRead(&KeyPress);
133 command = 0x100+KeyPress;
134 }
135 ret = 1; //Assume that the entered key is a valid command
136 switch(command) {
137 case 0x11B: //Escape == Triangle
138 new_pad = PAD_TRIANGLE;
139 break;
140 case 0x00A: //Enter == OK
141 if(!swapKeys)
142 new_pad = PAD_CIRCLE;
143 else
144 new_pad = PAD_CROSS;
145 break;
146 case 0x020: //Space == Cancel/Mark
147 if(!swapKeys)
148 new_pad = PAD_CROSS;
149 else
150 new_pad = PAD_CIRCLE;
151 break;
152 case 0x031: //'1' == L1
153 new_pad = PAD_L1;
154 break;
155 case 0x032: //'2' == L2
156 new_pad = PAD_L2;
157 break;
158 case 0x033: //'3' == L3
159 new_pad = PAD_L3;
160 break;
161 case 0x077: //'w' == Up
162 new_pad = PAD_UP;
163 break;
164 case 0x061: //'a' == Left
165 new_pad = PAD_LEFT;
166 break;
167 case 0x073: //'s' == Right
168 new_pad = PAD_RIGHT;
169 break;
170 case 0x07A: //'z' == Down
171 new_pad = PAD_DOWN;
172 break;
173 case 0x030: //'0' == R1
174 new_pad = PAD_R1;
175 break;
176 case 0x039: //'9' == R2
177 new_pad = PAD_R2;
178 break;
179 case 0x038: //'8' == R3
180 new_pad = PAD_R3;
181 break;
182 case 0x069: //'i' == Triangle
183 new_pad = PAD_TRIANGLE;
184 break;
185 case 0x06A: //'j' == Square
186 new_pad = PAD_SQUARE;
187 break;
188 case 0x06B: //'k' == Circle
189 new_pad = PAD_CIRCLE;
190 break;
191 case 0x06D: //'m' == Cross
192 new_pad = PAD_CROSS;
193 break;
194 case 0x101: //F1 == L1
195 new_pad = PAD_L1;
196 break;
197 case 0x102: //F2 == L2
198 new_pad = PAD_L2;
199 break;
200 case 0x103: //F3 == L3
201 new_pad = PAD_L3;
202 break;
203 case 0x12C: //Up == Up
204 new_pad = PAD_UP;
205 break;
206 case 0x12A: //Left == Left
207 new_pad = PAD_LEFT;
208 break;
209 case 0x129: //Right == Right
210 new_pad = PAD_RIGHT;
211 break;
212 case 0x12B: //Down == Down
213 new_pad = PAD_DOWN;
214 break;
215 case 0x123: //Insert == Select
216 new_pad = PAD_SELECT;
217 break;
218 case 0x10C: //F12 == R1
219 new_pad = PAD_R1;
220 break;
221 case 0x10B: //F11 == R2
222 new_pad = PAD_R2;
223 break;
224 case 0x10A: //F10 == R3
225 new_pad = PAD_R3;
226 break;
227 case 0x124: //Home == Triangle
228 new_pad = PAD_TRIANGLE;
229 break;
230 case 0x127: //End == Square
231 new_pad = PAD_SQUARE;
232 break;
233 case 0x125: //PgUp == Circle
234 new_pad = PAD_CIRCLE;
235 break;
236 case 0x128: //PgDn == Cross
237 new_pad = PAD_CROSS;
238 break;
239 case 0x126: //Delete == Start
240 new_pad = PAD_START;
241 break;
242 default: //Unrecognized key => no pad button
243 ret = 0;
244 break;
245 }
246 return ret;
247}
248//------------------------------
249//endfunc simPadKB
250//---------------------------------------------------------------------------
251// readpad will call readpad_no_KB, and if no new pad buttons are found, it
252// will also attempt reading data from a USB keyboard, and map this as a
253// virtual gamepad. (Very improvised and sloppy, but it should work fine.)
254//---------------------------------------------------------------------------
255int readpad(void)
256{
257 int ret;
258
259 if((ret=readpad_no_KB()) && new_pad)
260 return ret;
261
262 return simPadKB();
263}
264//------------------------------
265//endfunc readpad
266//---------------------------------------------------------------------------
267// readpad_noRepeat calls readpad_noKBnoRepeat, and if no new pad buttons are
268// found, it also attempts reading data from a USB keyboard, and map this as
269// a virtual gamepad. (Very improvised and sloppy, but it should work fine.)
270//---------------------------------------------------------------------------
271int readpad_noRepeat(void)
272{
273 int ret;
274
275 if((ret=readpad_noKBnoRepeat()) && new_pad)
276 return ret;
277
278 return simPadKB();
279}
280//------------------------------
281//endfunc readpad_noRepeat
282//---------------------------------------------------------------------------
283// Wait for specific PAD, but also accept disconnected state
284void waitPadReady(int port, int slot)
285{
286 int state, lastState;
287 char stateString[16];
288
289 state = padGetState(port, slot);
290 lastState = -1;
291 while((state != PAD_STATE_DISCONN)
292 && (state != PAD_STATE_STABLE)
293 && (state != PAD_STATE_FINDCTP1)){
294 if (state != lastState)
295 padStateInt2String(state, stateString);
296 lastState = state;
297 state=padGetState(port, slot);
298 }
299}
300//---------------------------------------------------------------------------
301// Wait for any PAD, but also accept disconnected states
302void waitAnyPadReady(void)
303{
304 int state_1, state_2;
305
306 state_1 = padGetState(0, 0);
307 state_2 = padGetState(1, 0);
308 while((state_1 != PAD_STATE_DISCONN) && (state_2 != PAD_STATE_DISCONN)
309 && (state_1 != PAD_STATE_STABLE) && (state_2 != PAD_STATE_STABLE)
310 && (state_1 != PAD_STATE_FINDCTP1) && (state_2 != PAD_STATE_FINDCTP1)){
311 state_1 = padGetState(0, 0);
312 state_2 = padGetState(1, 0);
313 }
314}
315//---------------------------------------------------------------------------
316// setup PAD
317int setupPad(void)
318{
319 int ret, i, port, state, modes;
320
321 padInit(0);
322
323 for(port=0; port<2; port++){
324 padtype_t[port] = 0; //Assume that we don't have a proper PS2 controller
325 if((ret = padPortOpen(port, 0, &padBuf_t[port][0])) == 0)
326 return 0;
327 waitPadReady(port, 0);
328 state = padGetState(port, 0);
329 if(state != PAD_STATE_DISCONN){ //if anything connected to this port
330 modes = padInfoMode(port, 0, PAD_MODETABLE, -1);
331 if (modes != 0){ //modes != 0, so it may be a dualshock type
332 for(i=0; i<modes; i++){
333 if (padInfoMode(port, 0, PAD_MODETABLE, i) == PAD_TYPE_DUALSHOCK){
334 padtype_t[port] = 2; //flag normal PS2 controller
335 break;
336 }
337 } //ends for (modes)
338 } else { //modes == 0, so this is a digital controller
339 padtype_t[port] = 1; //flag digital controller
340 }
341 if(padtype_t[port] == 2) //if DualShock
342 padSetMainMode(port, 0, PAD_MMODE_DUALSHOCK, PAD_MMODE_LOCK); //Set DualShock
343 else //else
344 padSetMainMode(port, 0, PAD_MMODE_DIGITAL, PAD_MMODE_UNLOCK); //Set Digital
345 waitPadReady(port, 0); //Await completion
346 } else { //Nothing is connected to this port
347 padSetMainMode(port, 0, PAD_MMODE_DUALSHOCK, PAD_MMODE_LOCK); //Fake DualShock
348 waitPadReady(port, 0); //Await completion
349 }
350 } //ends for (port)
351 return 1;
352}
353//---------------------------------------------------------------------------
354// End of file: pad.c
355//---------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.