@@ -83,35 +83,38 @@ int main(int argc, char** argv) {
83
83
game = argv [2 ];
84
84
options = argv [1 ];
85
85
} else if ((argc > 3 ) || (argc < 2 )) {
86
- printf ("usage: launchArcade [nomap] [/path/to/arcadegame.elf]\n" );
86
+ printf ("usage: launchArcade [nomap / keybswap ] [/path/to/arcadegame.elf]\n" );
87
87
return 1 ;
88
88
}
89
89
90
90
91
91
// Check for nomap option
92
92
if (!strcmp (options , "nomap" )) {
93
- printf ("%s argument detected,\nStarting %s with no automatic gamepad mappings...\n" , options , game );
93
+ printf ("%s argument detected,\nlaunCharc starting %s with no automatic gamepad mappings...\n" , options , game );
94
94
sleep (1 );
95
95
} else {
96
96
// Determine the number of connected gamepads
97
- printf ("Starting %s with automatic gamepad mappings...\n \n" , game );
97
+ printf ("launCharc starting %s with automatic gamepad mappings...\n" , game );
98
98
char eventPaths [100 ];
99
99
memset (eventPaths , 0 , sizeof (eventPaths ));
100
100
int numberOfPads = 0 ;
101
- int numberOfEvents = 1 + atoi (getSystemOutput ("ls /dev/input | sed 's/event//' | sort -n | tail -1" ));
102
- printf ("\nHighest found input event number: %d\n\n " , numberOfEvents );
101
+ int numberOfEvents = 1 + atoi (getSystemOutput ("ls /dev/input | sed 's/event//' | sort -n | tail -1 | tr -d [:cntrl:] " ));
102
+ printf ("\nHighest found input event number: %d\n" , numberOfEvents );
103
103
char padEvent [2 ][20 ];
104
+ memset (padEvent , 0 , sizeof (padEvent ));
104
105
for (int i = 0 ; i < numberOfEvents ; i ++ ) {
105
106
if (numberOfPads < 2 ) {
106
107
char padCommand [150 ];
107
- snprintf (padCommand , 150 , "/home/pi/McAirpos/McAirpos/uinput-mapper/input-read -vp /dev/input/event%d 2>&1 | grep -e BTN_SOUTH -e BTN_PINKIE" , i );
108
+ memset (padCommand , 0 , sizeof (padCommand ));
109
+ snprintf (padCommand , 150 , "/home/pi/McAirpos/McAirpos/uinput-mapper/input-read -vp /dev/input/event%d 2>&1 | grep -e BTN_START -e BTN_SOUTH -e BTN_PINKIE" , i );
108
110
char * event = getSystemOutput (padCommand );
109
111
if (strcmp (event , "" )) {
110
112
if (numberOfPads == 0 ) {
111
- printf ("\nGamepad search hits:\n" );
113
+ printf ("Gamepad search hits:\n" );
112
114
}
113
115
printf ("%s, Output:%s" , padCommand , getSystemOutput (padCommand ));
114
116
char iString [20 ];
117
+ memset (iString , 0 , sizeof (iString ));
115
118
sprintf (iString , "%d" , i );
116
119
strcat (strcat (strcat (eventPaths , "/dev/input/event" ), iString ), " " );
117
120
strcat (strcat (strcat (eventPaths , "/dev/input/event" ), iString ), " " );
@@ -123,17 +126,23 @@ int main(int argc, char** argv) {
123
126
}
124
127
125
128
// Determine if keyboard is connected
126
- char keybCommand [] = "cat /proc/bus/input/devices | grep -B 7 EV=12001 | tr ' ' '\\n' | grep event" ;
129
+ char keybCommand [300 ];
130
+ memset (keybCommand , 0 , sizeof (keybCommand ));
131
+ if (!strcmp (options , "keybswap" )) {
132
+ strcat (keybCommand , "cat /proc/bus/input/devices | grep -B 5 -A 5 Handlers=sysrq | grep -B 7 -A 3 -e EV=12001 -e EV=10001 | grep -B 2 -A 8 -E 'Phys=(usb\\S+\\/input0|[a-zA-Z0-9]{2}(:[a-zA-Z0-9]{2}){5}.*)' | tr ' ' '\\n' | grep event | tail -1 | tr -d [:cntrl:]" );
133
+ } else {
134
+ strcat (keybCommand , "cat /proc/bus/input/devices | grep -B 5 -A 5 Handlers=sysrq | grep -B 7 -A 3 -e EV=12001 -e EV=10001 | grep -B 2 -A 8 -E 'Phys=(usb\\S+\\/input0|[a-zA-Z0-9]{2}(:[a-zA-Z0-9]{2}){5}.*)' | tr ' ' '\\n' | grep event | head -1 | tr -d [:cntrl:]" );
135
+ }
127
136
char * keybEvent = getSystemOutput (keybCommand );
128
137
if (strcmp (keybEvent , "" )) {
129
- printf ("\nKeyboard search hit:\n" );
138
+ printf ("Keyboard search hit:\n" );
130
139
printf ("%s, Output:%s" , keybCommand , getSystemOutput (keybCommand ));
131
140
}
132
141
133
142
134
143
// Automatically set up uinput-mapper with keyboard, 1 or 2 gamepads
135
- // printf("\n%s\n", eventPaths);
136
144
char stringNumberOfPads [20 ];
145
+ memset (stringNumberOfPads , 0 , sizeof (stringNumberOfPads ));
137
146
char uiMapCommand [400 ];
138
147
memset (uiMapCommand , 0 , sizeof (uiMapCommand ));
139
148
char uinputMapperOrKeyboard [20 ];
@@ -156,14 +165,12 @@ int main(int argc, char** argv) {
156
165
printf ("\nFound %d gamepad to configure on:\n%s\n" , numberOfPads , padEvent [0 ]);
157
166
printf ("\nFound 1 keyboard to configure on:\n/dev/input/%s\n\n" , keybEvent );
158
167
strcat (strcat (eventPaths , "/dev/input/" ), keybEvent );
159
- eventPaths [strlen (eventPaths )- 1 ] = 0 ;
160
168
strcat (eventPaths , " " );
161
169
sprintf (stringNumberOfPads , "%d.py)&" ,numberOfPads );
162
170
}
163
171
else if (strcmp (keybEvent , "" )) {
164
172
printf ("\nFound 1 keyboard to configure on:\n/dev/input/%s\n\n" , keybEvent );
165
173
strcat (defaultEvent , keybEvent );
166
- defaultEvent [strlen (defaultEvent )- 1 ] = 0 ;
167
174
strcat (uinputMapperOrKeyboard , "keyboard" );
168
175
}
169
176
else if (numberOfPads == 1 ) {
@@ -182,7 +189,7 @@ int main(int argc, char** argv) {
182
189
if (numberOfPads > 0 ) {
183
190
strcat (strcat (strcat (strcat (uiMapCommand , "(/home/pi/McAirpos/McAirpos/uinput-mapper/input-read -C -D " ), eventPaths ), "| sudo /home/pi/McAirpos/McAirpos/uinput-mapper/input-create -C -S /home/pi/McAirpos/McAirpos/uinput-mapper/configs/arcade" ), stringNumberOfPads );
184
191
if (system (uiMapCommand ) == 0 ) {
185
- printf ("\nStarting UInput-Mapper with command:\n%s\n" , uiMapCommand );
192
+ printf ("Starting UInput-Mapper with command:\n%s\n" , uiMapCommand );
186
193
int whileCount = 0 ;
187
194
while (!strcmp ("" , getSystemOutput ("cat /proc/bus/input/devices | grep -A 8 \"UInputMapper: MakeCode_Arcade\" | tr ' ' '\n' | grep event" ))) {
188
195
if (whileCount > 500 ) {
@@ -192,9 +199,8 @@ int main(int argc, char** argv) {
192
199
}
193
200
whileCount ++ ;
194
201
}
195
- char * uinputEvent = getSystemOutput ("cat /proc/bus/input/devices | grep -A 8 \"UInputMapper: MakeCode_Arcade\" | tr ' ' '\n' | grep event" );
202
+ char * uinputEvent = getSystemOutput ("cat /proc/bus/input/devices | grep -A 8 \"UInputMapper: MakeCode_Arcade\" | tr ' ' '\n' | grep event | tr -d [:cntrl:] " );
196
203
strcat (defaultEvent , uinputEvent );
197
- defaultEvent [strlen (defaultEvent )- 1 ] = 0 ;
198
204
strcat (uinputMapperOrKeyboard , "UInputMapper" );
199
205
} else {
200
206
printf ("\nUInput-Mapper failed to start...\n" );
@@ -209,25 +215,39 @@ int main(int argc, char** argv) {
209
215
}
210
216
211
217
212
- // Set default default event for MakeCode Arcade elf game file
218
+ // Set default input event for MakeCode Arcade elf game file
213
219
char sedCommand [100 ];
220
+ memset (sedCommand , 0 , sizeof (sedCommand ));
214
221
snprintf (sedCommand , 100 , "sed -i \"1s&.*&\"%s\"&\" /sd/arcade.cfg" , defaultEvent );
215
222
if (system (sedCommand ) == 0 ) {
216
- printf ("\n\nSetting up %s in MakeCode Arcade game's /sd/arcade.cfg with:\n%s\n\n" , uinputMapperOrKeyboard , defaultEvent );
223
+ printf ("Setting up %s in MakeCode Arcade game's /sd/arcade.cfg with:\n%s\n\n" , uinputMapperOrKeyboard , defaultEvent );
217
224
} else {
218
- printf ("\n\nPlease check path or write permissions for /sd/arcade.cfg and try again.\n\n" );
225
+ printf ("Please check path or write permissions for /sd/arcade.cfg and try again.\n\n" );
219
226
goto cleanup ;
220
227
}
221
228
}
222
- system ("stty -ixon" ); //Disable pause in terminal with key combo CTRL+S
223
229
224
230
225
- // Fork game execution on launch, so that it is executed
226
- // the same way it's done in-game on reset and finish
231
+ // Ready terminal and game files
232
+ int foundPxtFile = 0 ;
233
+ system ("stty -ixon intr undef susp undef" ); //Disable pause(CTRL+S), suspend(CTRL+Z) and interrupt(CTRL+C) in terminal
234
+ if (0 == system ("head -1 /tmp/pxt-pid >>/dev/null 2>&1" )) {
235
+ system ("sed -i \"1s&.*&\"\"&\" /tmp/pxt-pid" ); //Clear old pid from /tmp/pxt if present
236
+ foundPxtFile = 1 ;
237
+ }
238
+ if (strcmp ("" , getSystemOutput ("ps -A | grep pulse" ))) {
239
+ system ("sudo killall pulseaudio" ); //Kill PulseAudio if running, can sometimes halt game looking for ALSA
240
+ }
227
241
char * path = "/dev/tty" ;
228
- int fd = open (path , O_RDWR , 0 );
242
+ int fd ;
243
+ fflush (stdout );
244
+
245
+ // Fork game execution on launch, so that it is executed
246
+ // the same way it's done in-game on reset
229
247
if (!fork ()) {
248
+
230
249
//Switch console to graphics mode to avoid disturbing text output in borders
250
+ fd = open (path , O_RDWR , 0 );
231
251
if (fd < 0 ) {
232
252
perror ("unable to open tty" );
233
253
return 1 ;
@@ -236,41 +256,95 @@ int main(int argc, char** argv) {
236
256
perror ("warn: ioctl KDSETMODE failed" );
237
257
}
238
258
close (fd );
239
- system ("sudo killall pulseaudio" );
259
+
260
+ // Launch the game
240
261
if (system (game ) == 36608 ) {
241
- printf ("\n\n %s was exited by the user\n \n\n" , game );
262
+ printf ("%s was exited by the user\n\n" , game );
242
263
} else {
243
- printf ("\n\nPlease check path to and executable permissions for game_file.elf and try again.\n \n\n" );
264
+ printf ("Please check path to and executable permissions for game_file.elf and try again.\n\n" );
244
265
}
245
- //Alternative way to launch game
266
+ //Alternative way to launch game, but I need to spawn new process in fork, not replace fork process
246
267
//execl(game, game, NULL);
268
+
269
+ // Main thread continues
247
270
}else {
248
- sleep (1 ); // Wait for fork/game to launch and get pid
249
271
250
- // Get running game's process name
251
- char * processID = getSystemOutput ("head -1 /tmp/pxt-pid" );
272
+ // Wait for fork/game to launch and get running game's process name
273
+ struct stat pxtFileBuffer ;
274
+ char processID [20 ];
275
+ memset (processID , 0 , sizeof (processID ));
252
276
char processCommand [100 ];
253
- snprintf (processCommand , 100 , "head -1 /proc/%s/comm" , processID );
254
- char * processName = getSystemOutput (processCommand );
255
- char processCheckCmd [100 ];
256
- snprintf (processCheckCmd , 100 , "pgrep %s" , processName );
277
+ memset (processCommand , 0 , sizeof (processCommand ));
278
+ int whileCount = 0 ;
279
+ int maxCount = 500 ;
280
+ do {
281
+ sleep (0.1 );
282
+ whileCount ++ ;
283
+ snprintf (processCommand , 100 , "head -1 /proc/%s/comm >>/dev/null 2>&1" , processID );
284
+ if (whileCount > maxCount ) {
285
+ printf ("\nTimed out trying to find game's process ID...\n" );
286
+ printf ("If stuck, please read or open a related issue at https://github.com/Vegz78/McAirpos.\n" );
287
+ goto cleanup ;
288
+ }
289
+ // Check until found if /tmp/pxt-pid file exists without opening it, time out otherwise
290
+ if (0 == foundPxtFile ) {
291
+ if (0 != stat ("/tmp/pxt-pid" , & pxtFileBuffer )) {
292
+ if (whileCount > maxCount - 1 ) {
293
+ printf ("\nDid not find the file /tmp/pxt-pid...\n" );
294
+ }
295
+ continue ;
296
+ } else {
297
+ foundPxtFile = 1 ;
298
+ whileCount = 0 ;
299
+ }
300
+ }
301
+ // Set new game's processID from file /tmp/pxt-pid
302
+ snprintf (processID , 20 , "%s" , getSystemOutput ("head -1 /tmp/pxt-pid | tr -d [:cntrl:]" ));
303
+ }
304
+ // Check whether processID from /tmp/pxt-pid is running/registered on system, time out otherwise
305
+ while (0 != system (processCommand ));
306
+
307
+ // Get name of game process
308
+ snprintf (processCommand , 100 , "head -1 /proc/%s/comm 2>&1 | tr -d [:cntrl:]" , processID );
309
+ char processName [50 ];
310
+ memset (processName , 0 , sizeof (processName ));
311
+ snprintf (processName , 50 , "%s" , getSystemOutput (processCommand ));
312
+ printf ("\nFound running game process \"%s\" on PID=%s\n\n" , processName , processID );
313
+
257
314
258
315
// Check every 2 secounds if a game process is still active
259
- // Busy waiting to continue and cleanup when game is exited
316
+ // Busy waiting to continue and clean up when game is exited
260
317
// Why does this not work without the printf?!?
318
+ char processCheckCmd [100 ];
319
+ memset (processCheckCmd , 0 , sizeof (processCheckCmd ));
320
+ snprintf (processCheckCmd , 100 , "pgrep -n %s 2>&1 | tr -d [:cntrl:]" , processName );
321
+ char newProcessID [20 ];
322
+ memset (newProcessID , 0 , sizeof (newProcessID ));
261
323
besure :
262
- while (0 == system ( processCheckCmd )) {
263
- printf ("%s\n" , getSystemOutput ( processCheckCmd ) );
324
+ while (strcmp ( processID , "" )) {
325
+ // printf("%s@PID=%s is keeping launCharc alive... \n", processName, processID );
264
326
sleep (2 );
327
+ snprintf (newProcessID , 20 , getSystemOutput (processCheckCmd ));
328
+ if (strcmp (processID , newProcessID )) {
329
+ if (strcmp (newProcessID , "" )) {
330
+ printf ("\"%s\" restarted on PID=%s\n" , processName , newProcessID );
331
+ } else {
332
+ printf ("PID not found for \"%s\", trying again...\n" , processName );
333
+ }
334
+ snprintf (processID , 20 , "%s" , newProcessID );
335
+ }
265
336
}
266
337
267
- // Double check that game really has exited
268
- sleep (1 );
269
- if (0 == system (processCheckCmd )) {goto besure ;}
338
+ // Doublecheck that the game really has exited
339
+ sleep (3 );
340
+ snprintf (processID , 20 , getSystemOutput (processCheckCmd ));
341
+ if (strcmp (processID , "" )) {goto besure ;}
342
+ else {printf ("PID still not found for \"%s\", game exited?\nTerminating launCharc...\n" , processName );}
270
343
271
344
272
345
// Kill any remaining/orphaned game processes before exit
273
346
char killAllCmd [100 ];
347
+ memset (killAllCmd , 0 , sizeof (killAllCmd ));
274
348
snprintf (killAllCmd , 100 , "killall %s 2>&1" , processName );
275
349
system (killAllCmd );
276
350
cleanup :
@@ -286,7 +360,7 @@ int main(int argc, char** argv) {
286
360
return 1 ;
287
361
}
288
362
289
- // This one fails without sudo, but doesn't seem needed for
363
+ // This one fails without sudo, but doesn't seem needed for
290
364
// MakeCode Arcade games(comment out or leave as and option?).
291
365
if (ioctl (fd , VT_UNLOCKSWITCH , 1 ) < 0 ) {
292
366
//perror("warn: ioctl VT_UNLOCKSWITCH failed");
@@ -300,7 +374,7 @@ int main(int argc, char** argv) {
300
374
perror ("warn: ioctl KBSKBMODE failed" );
301
375
}
302
376
303
- system ("stty ixon " );
377
+ system ("stty sane " );
304
378
//system("clear");
305
379
}
306
380
0 commit comments