1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
* Mupen64plus - plugin.c *
3
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4
* Copyright (C) 2008 Richard42 Tillin9 *
5
* Copyright (C) 2002 Blight *
7
* This program is free software; you can redistribute it and/or modify *
8
* it under the terms of the GNU General Public License as published by *
9
* the Free Software Foundation; either version 2 of the License, or *
10
* (at your option) any later version. *
12
* This program is distributed in the hope that it will be useful, *
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
* GNU General Public License for more details. *
17
* You should have received a copy of the GNU General Public License *
18
* along with this program; if not, write to the *
19
* Free Software Foundation, Inc., *
20
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
21
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
30
#include <sys/types.h>
35
#include "../main/winlnxdefs.h"
39
# include "configdialog_sdl.h"
40
#elif defined(GUI_GTK)
41
# include "configdialog_gtk.h"
49
#include <linux/input.h>
50
#endif /* __linux__ */
54
/* defines for the force feedback rumble support */
56
#define BITS_PER_LONG (sizeof(long) * 8)
57
#define OFF(x) ((x)%BITS_PER_LONG)
58
#define BIT(x) (1UL<<OFF(x))
59
#define LONG(x) ((x)/BITS_PER_LONG)
60
#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
65
static unsigned short button_bits[] = {
70
0x0010, // START_BUTTON
80
0x4000, // Mempak switch
81
0x8000 // Rumblepak switch
84
static SController controller[4]; // 4 controllers
85
static int romopen = 0; // is a rom opened
86
static char configdir[PATH_MAX] = {0}; // holds config dir path
88
Uint8 myKeyState[SDLK_LAST];
90
static const char *button_names[] = {
95
"Start", // START_BUTTON
97
"B Button", // B_BUTTON
98
"A Button", // A_BUTTON
99
"C Button R", // R_CBUTTON
100
"C Button L", // L_CBUTTON
101
"C Button D", // D_CBUTTON
102
"C Button U", // U_CBUTTON
112
get_button_num_by_name( const char *name )
116
for( i = 0; i < NUM_BUTTONS; i++ )
117
if( !strncasecmp( name, button_names[i], strlen( button_names[i] ) ) )
120
printf( "%s, %d: name = %s, button = %d\n", __FILE__, __LINE__, name, i );
126
printf( "%s, %d: button '%s' unknown\n", __FILE__, __LINE__, name );
132
get_key_by_name( const char *name )
136
for( i = 0; i < SDLK_LAST; i++ )
137
if( !strncasecmp( name, SDL_GetKeyName( i ), strlen( SDL_GetKeyName( i ) ) ) )
140
printf( "%s, %d: name = %s, key = %d\n", __FILE__, __LINE__, name, i );
146
printf( "%s, %d: key '%s' unknown\n", __FILE__, __LINE__, name );
152
get_hat_pos_by_name( const char *name )
154
if( !strcasecmp( name, "up" ) )
156
if( !strcasecmp( name, "down" ) )
158
if( !strcasecmp( name, "left" ) )
160
if( !strcasecmp( name, "right" ) )
161
return SDL_HAT_RIGHT;
165
void read_configuration( void )
168
int cont, plugged, plugin, mouse, i, b, dev;
169
char line[200], device[200], key_a[200], key_b[200], button_a[200], button_b[200],
170
axis[200], axis_a[200], axis_b[200], button[200], hat[200], hat_pos_a[200], hat_pos_b[200], mbutton[200];
175
for( i = 0; i < 4; i++ )
177
controller[i].device = DEVICE_NONE;
178
controller[i].control.Present = FALSE;
179
controller[i].control.RawData = FALSE;
180
controller[i].control.Plugin = PLUGIN_NONE;
181
for( b = 0; b < 16; b++ )
183
controller[i].button[b].button = -1;
184
controller[i].button[b].key = SDLK_UNKNOWN;
185
controller[i].button[b].axis = -1;
186
controller[i].button[b].hat = -1;
187
controller[i].button[b].hat_pos = -1;
188
controller[i].button[b].mouse = -1;
190
for( b = 0; b < 2; b++ )
192
controller[i].axis[b].button_a = controller[i].axis[b].button_b = -1;
193
controller[i].axis[b].key_a = controller[i].axis[b].key_a = SDLK_UNKNOWN;
194
controller[i].axis[b].axis_a = -1;
195
controller[i].axis[b].axis_dir_a = 1;
196
controller[i].axis[b].axis_b = -1;
197
controller[i].axis[b].axis_dir_b = 1;
198
controller[i].axis[b].hat = -1;
199
controller[i].axis[b].hat_pos_a = -1;
200
controller[i].axis[b].hat_pos_b = -1;
205
if(strlen(configdir) > 0)
206
strncpy(path, configdir, PATH_MAX);
207
strncat(path, "blight_input.conf", PATH_MAX - strlen(path));
208
f = fopen( path, "r" );
211
fprintf( stderr, "["PLUGIN_NAME"]: Couldn't open blight_input.conf for reading: %s\n", strerror( errno ) );
216
if( fgets( line, 200, f ) == NULL )
218
if( line[0] == '\n' || line[0] == '\0' )
220
if( sscanf( line, "[controller %d]", &cont ) == 1 )
222
if( sscanf( line, "plugged=%d", &plugged ) == 1 )
224
controller[cont].control.Present = plugged;
227
if( sscanf( line, "plugin=%d", &plugin ) == 1 )
229
controller[cont].control.Plugin = plugin;
232
if( sscanf( line, "mouse=%d", &mouse ) == 1 )
234
controller[cont].mouse = mouse;
237
if( sscanf( line, "device=%200s", device ) == 1 )
240
if( !strcasecmp( device, "keyboard" ) )
241
dev = DEVICE_KEYBOARD;
242
else if( sscanf( device, "%d", &i ) == 1 )
244
controller[cont].device = dev;
247
p = strchr( line, '=' );
253
strncpy( button, line, len );
257
b = get_button_num_by_name( button );
258
if( (b == X_AXIS) || (b == Y_AXIS) )
260
num = sscanf( p, "key( %s , %s ); button( %s , %s ); axis( %s , %s ); hat( %s , %s , %s )",
261
key_a, key_b, button_a, button_b, axis_a, axis_b, hat, hat_pos_a, hat_pos_b );
264
printf( "%s, %d: num = %d, key_a = %s, key_b = %s, button_a = %s, button_b = %s, axis_a = %s, axis_b = %s, hat = %s, hat_pos_a = %s, hat_pos_b = %s\n", __FILE__, __LINE__, num,
265
key_a, key_b, button_a, button_b, axis_a, axis_b, hat, hat_pos_a, hat_pos_b );
267
if( sscanf( key_a, "%d", (int *)&controller[cont].axis[b - Y_AXIS].key_a ) != 1 )
268
controller[cont].axis[b - Y_AXIS].key_a = -1;
269
if( sscanf( key_b, "%d", (int *)&controller[cont].axis[b - Y_AXIS].key_b ) != 1 )
270
controller[cont].axis[b - Y_AXIS].key_b = -1;
271
if( sscanf( button_a, "%d", &controller[cont].axis[b - Y_AXIS].button_a ) != 1 )
272
controller[cont].axis[b - Y_AXIS].button_a = -1;
273
if( sscanf( button_b, "%d", &controller[cont].axis[b - Y_AXIS].button_b ) != 1 )
274
controller[cont].axis[b - Y_AXIS].button_b = -1;
275
num = sscanf( axis_a, "%d%c", &controller[cont].axis[b - Y_AXIS].axis_a, &chAxisDir );
278
controller[cont].axis[b - Y_AXIS].axis_a = -1;
279
controller[cont].axis[b - Y_AXIS].axis_dir_a = 0;
283
if( chAxisDir == '+' )
284
controller[cont].axis[b - Y_AXIS].axis_dir_a = 1;
285
else if( chAxisDir == '-' )
286
controller[cont].axis[b - Y_AXIS].axis_dir_a = -1;
288
controller[cont].axis[b - Y_AXIS].axis_dir_a = 0;
291
num = sscanf( axis_b, "%d%c", &controller[cont].axis[b - Y_AXIS].axis_b, &chAxisDir);
294
controller[cont].axis[b - Y_AXIS].axis_b = -1;
295
controller[cont].axis[b - Y_AXIS].axis_dir_b = 0;
299
if( chAxisDir == '+' )
300
controller[cont].axis[b - Y_AXIS].axis_dir_b = 1;
301
else if( chAxisDir == '-' )
302
controller[cont].axis[b - Y_AXIS].axis_dir_b = -1;
304
controller[cont].axis[b - Y_AXIS].axis_dir_b = 0;
306
if( sscanf( hat, "%d", &controller[cont].axis[b - Y_AXIS].hat ) != 1 )
307
controller[cont].axis[b - Y_AXIS].hat = -1;
308
controller[cont].axis[b - Y_AXIS].hat_pos_a = get_hat_pos_by_name( hat_pos_a );
309
controller[cont].axis[b - Y_AXIS].hat_pos_b = get_hat_pos_by_name( hat_pos_b );
313
num = sscanf( p, "key( %s ); button( %s ); axis( %s ); hat( %s , %s ); mouse( %s )",
321
printf( "%s, %d: num = %d, key = %s, button = %s, axis = %s, hat = %s, hat_pos = %s, mbutton = %s\n", __FILE__, __LINE__, num, key_a, button_a, axis, hat, hat_pos_a, mbutton );
323
num = sscanf( axis, "%d%c", &controller[cont].button[b].axis, &chAxisDir );
326
controller[cont].button[b].axis = -1;
327
controller[cont].button[b].axis_dir = 0;
331
if( chAxisDir == '+' )
332
controller[cont].button[b].axis_dir = 1;
333
else if( chAxisDir == '-' )
334
controller[cont].button[b].axis_dir = -1;
336
controller[cont].button[b].axis_dir = 0;
338
if( sscanf( key_a, "%d", (int *)&controller[cont].button[b].key ) != 1 )
339
controller[cont].button[b].key = -1;
340
if( sscanf( button_a, "%d", &controller[cont].button[b].button ) != 1 )
341
controller[cont].button[b].button = -1;
342
if( sscanf( hat, "%d", &controller[cont].button[b].hat ) != 1 )
343
controller[cont].button[b].hat = -1;
344
controller[cont].button[b].hat_pos = get_hat_pos_by_name( hat_pos_a );
345
if( sscanf( mbutton, "%d", &controller[cont].button[b].mouse ) != 1 )
346
controller[cont].button[b].mouse = -1;
350
fprintf( stderr, "["PLUGIN_NAME"]: Unknown config line: %s\n", line );
355
#define HAT_POS_NAME( hat ) \
356
((hat == SDL_HAT_UP) ? "Up" : \
357
((hat == SDL_HAT_DOWN) ? "Down" : \
358
((hat == SDL_HAT_LEFT) ? "Left" : \
359
((hat == SDL_HAT_RIGHT) ? "Right" : \
363
write_configuration( void )
367
char cKey_a[100], cKey_b[100];
368
char cButton_a[100], cButton_b[100], cAxis[100], cAxis_a[100], cAxis_b[100];
374
if(strlen(configdir) > 0)
375
strncpy(path, configdir, PATH_MAX);
376
strncat(path, "blight_input.conf", PATH_MAX - strlen(path));
377
f = fopen( path, "w" );
380
fprintf( stderr, "["PLUGIN_NAME"]: Couldn't open blight_input.conf for writing: %s\n", strerror( errno ) );
384
for( i = 0; i < 4; i++ )
386
fprintf( f, "[controller %d]\n", i );
387
fprintf( f, "plugged=%d\n", controller[i].control.Present );
388
fprintf( f, "plugin=%d\n", controller[i].control.Plugin );
389
fprintf( f, "mouse=%d\n", controller[i].mouse );
390
if( controller[i].device == DEVICE_KEYBOARD )
391
fprintf( f, "device=Keyboard\n" );
392
else if( controller[i].device >= 0 )
393
fprintf( f, "device=%d\n", controller[i].device );
395
fprintf( f, "device=None\n" );
397
for( b = 0; b < 16; b++ )
399
// cKey_a = (controller[i].button[b].key == SDLK_UNKNOWN) ? "None" : SDL_GetKeyName( controller[i].button[b].key );
400
if( controller[i].button[b].key >= 0 )
401
sprintf( cKey_a, "%d", controller[i].button[b].key );
403
strcpy( cButton_a, "None" );
405
if( controller[i].button[b].button >= 0 )
406
sprintf( cButton_a, "%d", controller[i].button[b].button );
408
strcpy( cButton_a, "None" );
410
if( controller[i].button[b].axis >= 0 )
411
sprintf( cAxis, "%d%c", controller[i].button[b].axis, (controller[i].button[b].axis_dir == -1) ? '-' : '+' );
413
strcpy( cAxis, "None" );
415
if( controller[i].button[b].hat >= 0 )
416
sprintf( cHat, "%d", controller[i].button[b].hat );
418
strcpy( cHat, "None" );
420
if( controller[i].button[b].mouse >= 0 )
421
sprintf( cMouse, "%d", controller[i].button[b].mouse );
423
strcpy( cMouse, "None" );
425
fprintf( f, "%s=key( %s ); button( %s ); axis( %s ); hat( %s , %s ); mouse( %s )\n", button_names[b],
426
cKey_a, cButton_a, cAxis, cHat, HAT_POS_NAME(controller[i].button[b].hat_pos), cMouse );
428
for( b = 0; b < 2; b++ )
430
// cKey_a = (controller[i].axis[b].key_a == SDLK_UNKNOWN) ? "None" : SDL_GetKeyName( controller[i].axis[b].key_a );
431
// cKey_b = (controller[i].axis[b].key_b == SDLK_UNKNOWN) ? "None" : SDL_GetKeyName( controller[i].axis[b].key_b );
432
if( controller[i].axis[b].key_a >= 0 )
433
sprintf( cKey_a, "%d", controller[i].axis[b].key_a );
435
strcpy( cKey_a, "None" );
436
if( controller[i].axis[b].key_b >= 0 )
437
sprintf( cKey_b, "%d", controller[i].axis[b].key_b );
439
strcpy( cKey_b, "None" );
441
if( controller[i].axis[b].button_a >= 0 )
442
sprintf( cButton_a, "%d", controller[i].axis[b].button_a );
444
strcpy( cButton_a, "None" );
446
if( controller[i].axis[b].button_b >= 0 )
447
sprintf( cButton_b, "%d", controller[i].axis[b].button_b );
449
strcpy( cButton_b, "None" );
451
if( controller[i].axis[b].axis_a >= 0 )
452
sprintf( cAxis_a, "%d%c", controller[i].axis[b].axis_a, (controller[i].axis[b].axis_dir_a <= 0) ? '-' : '+' );
454
strcpy( cAxis_a, "None" );
456
if( controller[i].axis[b].axis_b >= 0 )
457
sprintf( cAxis_b, "%d%c", controller[i].axis[b].axis_b, (controller[i].axis[b].axis_dir_b <= 0) ? '-' : '+' );
459
strcpy( cAxis_b, "None" );
461
if( controller[i].axis[b].hat >= 0 )
462
sprintf( cHat, "%d", controller[i].axis[b].hat );
464
strcpy( cHat, "None" );
466
fprintf( f, "%s=key( %s , %s ); button( %s , %s ); axis( %s , %s ); hat( %s , %s , %s )\n", button_names[b+16],
467
cKey_a, cKey_b, cButton_a, cButton_b, cAxis_a, cAxis_b, cHat, HAT_POS_NAME(controller[i].axis[b].hat_pos_a), HAT_POS_NAME(controller[i].axis[b].hat_pos_b) );
480
struct ff_effect ffeffect[3];
481
struct ff_effect ffstrong[3];
482
struct ff_effect ffweak[3];
485
BYTE DataCRC( BYTE *Data, int iLenght )
487
register BYTE Remainder = Data[0];
492
while( iByte <= iLenght )
494
BOOL HighBit = ((Remainder & 0x80) != 0);
495
Remainder = Remainder << 1;
497
Remainder += ( iByte < iLenght && Data[iByte] & (0x80 >> bBit )) ? 1 : 0;
499
Remainder ^= (HighBit) ? 0x85 : 0;
509
/******************************************************************
511
Purpose: This function is called when the emulator is closing
512
down allowing the dll to de-initialise.
515
*******************************************************************/
519
printf( "["PLUGIN_NAME"]: Closing...\n" );
522
/******************************************************************
523
Function: ControllerCommand
524
Purpose: To process the raw data that has just been sent to a
526
input: - Controller Number (0 to 3) and -1 signalling end of
527
processing the pif ram.
528
- Pointer of data to be processed.
531
note: This function is only needed if the DLL is allowing raw
532
data, or the plugin is set to raw
534
the data that is being processed looks like this:
535
initilize controller: 01 03 00 FF FF FF
536
read controller: 01 04 01 FF FF FF FF
537
*******************************************************************/
538
void ControllerCommand(int Control, BYTE *Command)
540
BYTE *Data = &Command[5];
548
/*printf( "Get status\n" );*/
551
/*printf( "Read keys\n" );*/
554
/*printf( "Read pak\n" );*/
555
if (controller[Control].control.Plugin == PLUGIN_RAW)
557
DWORD dwAddress = (Command[3] << 8) + (Command[4] & 0xE0);
559
if(( dwAddress >= 0x8000 ) && ( dwAddress < 0x9000 ) )
560
memset( Data, 0x80, 32 );
562
memset( Data, 0x00, 32 );
564
Data[32] = DataCRC( Data, 32 );
568
/*printf( "Write pak\n" );*/
569
if (controller[Control].control.Plugin == PLUGIN_RAW)
571
DWORD dwAddress = (Command[3] << 8) + (Command[4] & 0xE0);
572
/*Uncomment to test rumble on systems without necessary hardware.
573
if(dwAddress==PAK_IO_RUMBLE&&*Data)
574
printf("Triggering rumble pack.\n");*/
577
struct input_event play;
578
if( dwAddress == PAK_IO_RUMBLE && controller[Control].event_joystick != 0)
583
play.code = ffeffect[Control].id;
586
if (write(controller[Control].event_joystick, (const void*) &play, sizeof(play)) == -1)
587
perror("Error starting rumble effect");
593
play.code = ffeffect[Control].id;
596
if (write(controller[Control].event_joystick, (const void*) &play, sizeof(play)) == -1)
597
perror("Error stopping rumble effect");
601
Data[32] = DataCRC( Data, 32 );
604
case RD_RESETCONTROLLER:
605
/*printf( "Reset controller\n" );*/
608
/*printf( "Read eeprom\n" );*/
611
/*printf( "Write eeprom\n" );*/
616
/******************************************************************
618
Purpose: This function is optional function that is provided
619
to give further information about the DLL.
620
input: a handle to the window that calls this function
622
*******************************************************************/
624
# include "SDL_ttf.h"
625
# include "arial.ttf.h" // arial font
628
# define FONT_SIZEPT 15
629
# define ABOUT_DIALOG_WIDTH 300
630
# define ABOUT_DIALOG_HEIGHT 145
633
static inline SDL_Surface *
634
render_text( TTF_Font *font, SDL_Color fg, SDL_Color bg, const char *fmt, ... )
640
vsnprintf( buf, 2048, fmt, ap );
646
return( TTF_RenderText_Shaded( font, buf, fg, bg ) );
651
write_text( SDL_Surface *dst, TTF_Font *font, int x, int y, SDL_Color fg, SDL_Color bg, const char *fmt, ... )
659
vsnprintf( buf, 2048, fmt, ap );
665
text = render_text( font, fg, bg, buf );
668
fprintf( stderr, "["PLUGIN_NAME"]: Couldn't render text: %s\n", SDL_GetError() );
676
SDL_BlitSurface( text, NULL, dst, &dstrect );
677
SDL_FreeSurface( text );
681
DllAbout( HWND hParent )
688
Uint32 u32black, u32gray, u32dark_gray;
689
SDL_Color black = { 0x00, 0x00, 0x00, 0 };
690
SDL_Color gray = { 0xAA, 0xAA, 0xAA, 0 };
691
SDL_Color dark_gray = { 0x66, 0x66, 0x66, 0 };
694
if( !SDL_WasInit( SDL_INIT_VIDEO ) )
695
if( SDL_InitSubSystem( SDL_INIT_VIDEO ) < 0 )
697
fprintf( stderr, "["PLUGIN_NAME"]: Couldn't init SDL video subsystem: %s\n", SDL_GetError() );
705
fprintf( stderr, "["PLUGIN_NAME"]: Couldn't init TTF library: %s\n", SDL_GetError() );
706
SDL_QuitSubSystem( SDL_INIT_VIDEO );
711
rw = SDL_RWFromMem( (char *)arial.data, arial.size );
712
font = TTF_OpenFontRW( rw, 0, FONT_SIZEPT );
715
fprintf( stderr, "["PLUGIN_NAME"]: Couldn't load %d pt font: %s\n", FONT_SIZEPT, SDL_GetError() );
717
SDL_QuitSubSystem( SDL_INIT_VIDEO );
720
TTF_SetFontStyle( font, TTF_STYLE_NORMAL );
722
// display dialog (set video mode)
723
screen = SDL_SetVideoMode( ABOUT_DIALOG_WIDTH, ABOUT_DIALOG_HEIGHT, 0, SDL_SWSURFACE );
726
fprintf( stderr, "["PLUGIN_NAME"]: Couldn't set video mode %dx%d: %s\n", ABOUT_DIALOG_WIDTH, ABOUT_DIALOG_HEIGHT, SDL_GetError() );
728
SDL_QuitSubSystem( SDL_INIT_VIDEO );
731
SDL_WM_SetCaption( PLUGIN_NAME" "PLUGIN_VERSION, NULL );
734
u32black = SDL_MapRGBA( screen->format, black.r, black.g, black.b, 0 );
735
u32gray = SDL_MapRGBA( screen->format, gray.r, gray.g, gray.b, 0 );
736
u32dark_gray = SDL_MapRGBA( screen->format, dark_gray.r, dark_gray.g, dark_gray.b, 0 );
739
SDL_FillRect( screen, NULL, u32dark_gray );
741
rect.x = rect.y = 5; rect.w = ABOUT_DIALOG_WIDTH - 10; rect.h = ABOUT_DIALOG_HEIGHT - 40;
742
SDL_FillRect( screen, &rect, u32black );
743
rect.x += 1; rect.y += 1; rect.w -= 2; rect.h -= 2;
744
SDL_FillRect( screen, &rect, u32gray );
746
write_text( screen, font, 15, 15, black, gray, PLUGIN_NAME" v"PLUGIN_VERSION":" );
747
write_text( screen, font, 15, 35, black, gray, "coded by blight" );
748
write_text( screen, font, 15, 55, black, gray, "This plugin uses the SDL library for input." );
749
write_text( screen, font, 15, 75, black, gray, "Go to www.libsdl.org for more information." );
751
rect.x = (ABOUT_DIALOG_WIDTH - 90) / 2; rect.y = ABOUT_DIALOG_HEIGHT - 30; rect.w = 90; rect.h = 25;
752
SDL_FillRect( screen, &rect, u32black );
753
rect.x += 1; rect.y += 1; rect.w -= 2; rect.h -= 2;
754
SDL_FillRect( screen, &rect, u32gray );
756
write_text( screen, font, rect.x + 33, rect.y + 2, black, gray, "Ok" );
762
if( SDL_PollEvent( &event ) )
764
if( event.type == SDL_KEYDOWN )
766
if( event.key.keysym.sym == SDLK_ESCAPE )
769
else if( event.type == SDL_MOUSEBUTTONDOWN )
771
if( event.button.button == SDL_BUTTON_LEFT )
773
if( event.button.x >= rect.x && event.button.x <= rect.x + rect.w &&
774
event.button.y >= rect.y && event.button.y <= rect.y + rect.h )
781
SDL_FreeSurface( screen );
782
SDL_QuitSubSystem( SDL_INIT_VIDEO );
785
#elif defined( GUI_GTK )
786
static int about_shown = 0;
789
about_ok_clicked( GtkWidget *widget,
792
gtk_widget_hide_all( GTK_WIDGET(data) );
793
gtk_widget_destroy( GTK_WIDGET(data) );
798
DllAbout( HWND hParent )
808
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
809
gtk_window_set_title( GTK_WINDOW(window), PLUGIN_NAME );
810
gtk_container_set_border_width( GTK_CONTAINER(window), 10 );
811
gtk_window_set_policy( GTK_WINDOW(window), FALSE, FALSE, TRUE );
813
vbox = gtk_vbox_new( FALSE, 10 );
814
label = gtk_label_new( PLUGIN_NAME" version "PLUGIN_VERSION"\n\n"
815
"This is a N64 input plugin using SDL.\n"
816
"(c) 2002 by blight" );
817
button = gtk_button_new_with_label( "Ok" );
819
gtk_container_add( GTK_CONTAINER(window), GTK_WIDGET(vbox) );
820
gtk_box_pack_start( GTK_BOX(vbox), GTK_WIDGET(label), TRUE, FALSE, 0 );
821
gtk_box_pack_start( GTK_BOX(vbox), GTK_WIDGET(button), TRUE, FALSE, 0 );
823
gtk_signal_connect( GTK_OBJECT(button), "clicked",
824
GTK_SIGNAL_FUNC(about_ok_clicked), (gpointer) window);
828
gtk_widget_show_all( GTK_WIDGET(window) );
832
/******************************************************************
834
Purpose: This function is optional function that is provided
835
to allow the user to configure the dll
836
input: a handle to the window that calls this function
838
*******************************************************************/
840
DllConfig( HWND hParent )
844
read_configuration();
846
configure_sdl( controller );
847
#elif defined( GUI_GTK )
848
configure_gtk( controller );
850
/* write_configuration() should be called in the configure_ function above */
854
/******************************************************************
856
Purpose: This function is optional function that is provided
857
to allow the user to test the dll
858
input: a handle to the window that calls this function
860
*******************************************************************/
862
DllTest( HWND hParent )
866
/******************************************************************
868
Purpose: This function allows the emulator to gather information
869
about the dll by filling in the PluginInfo structure.
870
input: a pointer to a PLUGIN_INFO stucture that needs to be
871
filled by the function. (see def above)
873
*******************************************************************/
875
GetDllInfo( PLUGIN_INFO *PluginInfo )
877
strncpy( PluginInfo->Name, PLUGIN_NAME" "PLUGIN_VERSION, 100 );
878
PluginInfo->Name[99] = '\0';
879
PluginInfo->Version = 0x0101;
880
PluginInfo->Type = PLUGIN_TYPE_CONTROLLER;
883
/* Helper function to handle the SDL keys */
885
doSdlKeys(Uint8* keystate)
887
int c, b, axis_val, axis_max_val, axis_val_tmp;
891
if (keystate[SDLK_LCTRL])
893
if (keystate[SDLK_LSHIFT])
896
for( c = 0; c < 4; c++ )
898
for( b = 0; b < 16; b++ )
900
if( controller[c].button[b].key == SDLK_UNKNOWN || ((int) controller[c].button[b].key) < 0)
902
if( keystate[controller[c].button[b].key] )
903
controller[c].buttons.Value |= button_bits[b];
905
for( b = 0; b < 2; b++ )
907
// from the N64 func ref: The 3D Stick data is of type signed char and in
908
// the range between 80 and -80. (32768 / 409 = ~80.1)
910
axis_val = controller[c].buttons.X_AXIS;
912
axis_val = -controller[c].buttons.Y_AXIS;
914
if( controller[c].axis[b].key_a != SDLK_UNKNOWN && ((int) controller[c].axis[b].key_a) > 0)
915
if( keystate[controller[c].axis[b].key_a] )
916
axis_val = axis_max_val;
917
if( controller[c].axis[b].key_b != SDLK_UNKNOWN && ((int) controller[c].axis[b].key_b) > 0)
918
if( keystate[controller[c].axis[b].key_b] )
919
axis_val = -axis_max_val;
922
controller[c].buttons.X_AXIS = axis_val;
924
controller[c].buttons.Y_AXIS = -axis_val;
926
if (controller[c].mouse)
928
if (keystate[SDLK_LCTRL] && keystate[SDLK_LALT])
935
SDL_WM_GrabInput( grabmouse ? SDL_GRAB_ON : SDL_GRAB_OFF );
936
SDL_ShowCursor( grabmouse ? 0 : 1 );
942
/******************************************************************
944
Purpose: To get the current state of the controllers buttons.
945
input: - Controller Number (0 to 3)
946
- A pointer to a BUTTONS structure to be filled with
947
the controller state.
949
*******************************************************************/
951
GetKeys( int Control, BUTTONS *Keys )
953
int b, axis_val, axis_max_val, axis_val_tmp;
956
// Handle keyboard input first
957
doSdlKeys( SDL_GetKeyState( NULL ) );
958
doSdlKeys( myKeyState );
960
// read joystick state
961
SDL_JoystickUpdate();
963
if( controller[Control].device >= 0 )
965
for( b = 0; b < 16; b++ )
967
if( controller[Control].button[b].button >= 0 )
968
if( SDL_JoystickGetButton( controller[Control].joystick, controller[Control].button[b].button ) )
969
controller[Control].buttons.Value |= button_bits[b];
971
if( controller[Control].button[b].axis >= 0 )
973
axis_val = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].button[b].axis );
974
if( (controller[Control].button[b].axis_dir < 0) && (axis_val <= -6000) )
975
controller[Control].buttons.Value |= button_bits[b];
976
else if( (controller[Control].button[b].axis_dir > 0) && (axis_val >= 6000) )
977
controller[Control].buttons.Value |= button_bits[b];
980
if( controller[Control].button[b].hat >= 0 )
982
if( controller[Control].button[b].hat_pos > 0 )
983
if( SDL_JoystickGetHat( controller[Control].joystick, controller[Control].button[b].hat ) & controller[Control].button[b].hat_pos )
984
controller[Control].buttons.Value |= button_bits[b];
987
for( b = 0; b < 2; b++ )
989
// from the N64 func ref: The 3D Stick data is of type signed char and in
990
// the range between 80 and -80. (32768 / 409 = ~80.1)
995
if( controller[Control].axis[b].axis_a >= 0 )
997
axis_val_tmp = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].axis[b].axis_a );
998
// if you push a positive axis... and your directions are flipped...
999
if( (controller[Control].axis[b].axis_dir_a < 0) && (axis_val_tmp <= -6000) )
1003
axis_val = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].axis[b].axis_a ) / -409;
1007
axis_val = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].axis[b].axis_a ) / 409;
1010
else if( (controller[Control].axis[b].axis_dir_a > 0) && (axis_val_tmp >= 6000) )
1014
axis_val = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].axis[b].axis_a ) / -409;
1018
axis_val = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].axis[b].axis_a ) / 409;
1023
if( controller[Control].axis[b].axis_b >= 0 )
1025
axis_val_tmp = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].axis[b].axis_b );
1026
// if you push a positive axis... and your directions are flipped...
1027
if( (controller[Control].axis[b].axis_dir_b < 0) && (axis_val_tmp <= -6000) )
1031
axis_val = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].axis[b].axis_b ) / -409;
1035
axis_val = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].axis[b].axis_b ) / 409;
1038
else if( (controller[Control].axis[b].axis_dir_b > 0) && (axis_val_tmp >= 6000) )
1042
axis_val = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].axis[b].axis_b ) / -409;
1046
axis_val = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].axis[b].axis_b ) / 409;
1050
if( controller[Control].axis[b].hat >= 0 )
1052
if( controller[Control].axis[b].hat_pos_a >= 0 )
1053
if( SDL_JoystickGetHat( controller[Control].joystick, controller[Control].axis[b].hat ) & controller[Control].axis[b].hat_pos_a )
1055
if( controller[Control].axis[b].hat_pos_b >= 0 )
1056
if( SDL_JoystickGetHat( controller[Control].joystick, controller[Control].axis[b].hat ) & controller[Control].axis[b].hat_pos_b )
1060
if( controller[Control].axis[b].button_a >= 0 )
1061
if( SDL_JoystickGetButton( controller[Control].joystick, controller[Control].axis[b].button_a ) )
1063
if( controller[Control].axis[b].button_b >= 0 )
1064
if( SDL_JoystickGetButton( controller[Control].joystick, controller[Control].axis[b].button_b ) )
1068
controller[Control].buttons.X_AXIS = axis_val;
1070
controller[Control].buttons.Y_AXIS = axis_val;
1074
// process mouse events
1076
Uint8 mstate = SDL_GetMouseState( NULL, NULL );
1078
for( b = 0; b < 16; b++ )
1080
if( controller[Control].button[b].mouse < 1 )
1082
if( mstate & SDL_BUTTON(controller[Control].button[b].mouse) )
1083
controller[Control].buttons.Value |= button_bits[b];
1087
if (controller[Control].mouse)
1090
while (SDL_PollEvent(&event))
1092
if (event.type == SDL_MOUSEMOTION && SDL_WM_GrabInput( SDL_GRAB_QUERY ) == SDL_GRAB_ON)
1094
if (event.motion.xrel)
1096
axis_val = (event.motion.xrel * 10);
1099
else if (axis_val > 80)
1101
controller[Control].buttons.Y_AXIS = axis_val;
1103
if (event.motion.yrel)
1105
axis_val = (event.motion.yrel * 10);
1108
else if (axis_val > 80)
1110
controller[Control].buttons.X_AXIS = -axis_val;
1113
else if (event.type == SDL_MOUSEBUTTONUP)
1115
if (event.button.button == SDL_BUTTON_LEFT)
1124
printf( "Controller #%d value: 0x%8.8X\n", Control, *(int *)&controller[Control].buttons );
1126
*Keys = controller[Control].buttons;
1128
/* handle mempack / rumblepak switching (only if rumble is active on joystick) */
1130
if (controller[Control].event_joystick != 0)
1132
struct input_event play;
1133
if (controller[Control].buttons.Value & button_bits[14])
1135
controller[Control].control.Plugin = PLUGIN_MEMPAK;
1137
play.code = ffweak[Control].id;
1139
if (write(controller[Control].event_joystick, (const void*) &play, sizeof(play)) == -1)
1140
perror("Error starting rumble effect");
1142
if (controller[Control].buttons.Value & button_bits[15])
1144
controller[Control].control.Plugin = PLUGIN_RAW;
1146
play.code = ffstrong[Control].id;
1148
if (write(controller[Control].event_joystick, (const void*) &play, sizeof(play)) == -1)
1149
perror("Error starting rumble effect");
1152
#endif /* __linux__ */
1154
controller[Control].buttons.Value = 0;
1155
//controller[Control].buttons.stick_x = 0;
1156
//controller[Control].buttons.stick_y = 0;
1159
static void InitiateRumble(int cntrl)
1164
unsigned long features[4];
1169
controller[cntrl].event_joystick = 0;
1171
sprintf(temp,"/sys/class/input/js%d/device", controller[cntrl].device);
1177
while ((ep=readdir(dp)))
1179
if (strncmp(ep->d_name, "event",5)==0)
1181
sprintf(temp, "/dev/input/%s", ep->d_name);
1185
else if(strncmp(ep->d_name,"input:event", 11)==0)
1187
sscanf(ep->d_name, "input:%s", temp2);
1188
sprintf(temp, "/dev/input/%s", temp2);
1192
else if(strncmp(ep->d_name,"input:input", 11)==0)
1195
strcat(temp, ep->d_name);
1207
printf("["PLUGIN_NAME"]: Couldn't find input event for rumble support.\n");
1211
controller[cntrl].event_joystick = open(temp, O_RDWR);
1212
if(controller[cntrl].event_joystick==-1)
1214
printf("["PLUGIN_NAME"]: Couldn't open device file '%s' for rumble support.\n", temp);
1215
controller[cntrl].event_joystick = 0;
1219
if(ioctl(controller[cntrl].event_joystick, EVIOCGBIT(EV_FF, sizeof(unsigned long) * 4), features)==-1)
1221
printf("["PLUGIN_NAME"]: Linux kernel communication failed for force feedback (rumble).\n");
1222
controller[cntrl].event_joystick = 0;
1226
if(!test_bit(FF_RUMBLE, features))
1228
printf("["PLUGIN_NAME"]: No rumble supported on N64 joystick #%i\n", cntrl + 1);
1229
controller[cntrl].event_joystick = 0;
1233
ffeffect[cntrl].type = FF_RUMBLE;
1234
ffeffect[cntrl].id = -1;
1235
ffeffect[cntrl].u.rumble.strong_magnitude = 0xFFFF;
1236
ffeffect[cntrl].u.rumble.weak_magnitude = 0xFFFF;
1238
ioctl(controller[cntrl].event_joystick, EVIOCSFF, &ffeffect[cntrl]);
1240
ffstrong[cntrl].type = FF_RUMBLE;
1241
ffstrong[cntrl].id = -1;
1242
ffstrong[cntrl].u.rumble.strong_magnitude = 0xFFFF;
1243
ffstrong[cntrl].u.rumble.weak_magnitude = 0x0000;
1244
ffstrong[cntrl].replay.length = 500;
1245
ffstrong[cntrl].replay.delay = 0;
1247
ioctl(controller[cntrl].event_joystick, EVIOCSFF, &ffstrong[cntrl]);
1249
ffweak[cntrl].type = FF_RUMBLE;
1250
ffweak[cntrl].id = -1;
1251
ffweak[cntrl].u.rumble.strong_magnitude = 0x0000;
1252
ffweak[cntrl].u.rumble.weak_magnitude = 0xFFFF;
1253
ffweak[cntrl].replay.length = 500;
1254
ffweak[cntrl].replay.delay = 0;
1256
ioctl(controller[cntrl].event_joystick, EVIOCSFF, &ffweak[cntrl]);
1258
printf("["PLUGIN_NAME"]: Rumble activated on N64 joystick #%i\n", cntrl + 1);
1259
#endif /* __linux__ */
1262
/******************************************************************
1263
Function: InitiateControllers
1264
Purpose: This function initialises how each of the controllers
1266
input: - The handle to the main window.
1267
- A controller structure that needs to be filled for
1268
the emulator to know how to handle each controller.
1270
*******************************************************************/
1271
void InitiateControllers( CONTROL_INFO ControlInfo )
1275
// reset controllers
1276
memset( controller, 0, sizeof( SController ) * 4 );
1278
for ( i = 0; i < SDLK_LAST; i++)
1283
// read configuration
1284
read_configuration();
1286
for( i = 0; i < 4; i++ )
1288
// test for rumble support for this joystick
1290
// if rumble not supported, switch to mempack
1291
// Comment out if statement to test rumble on systems without necessary hardware.
1292
if (controller[i].control.Plugin == PLUGIN_RAW && controller[i].event_joystick == 0)
1293
controller[i].control.Plugin = PLUGIN_MEMPAK;
1294
// copy control data struct to the core
1295
memcpy( ControlInfo.Controls + i, &controller[i].control, sizeof( CONTROL ) );
1298
printf( "["PLUGIN_NAME"]: version "PLUGIN_VERSION" initialized.\n" );
1301
/******************************************************************
1302
Function: ReadController
1303
Purpose: To process the raw data in the pif ram that is about to
1305
input: - Controller Number (0 to 3) and -1 signalling end of
1306
processing the pif ram.
1307
- Pointer of data to be processed.
1309
note: This function is only needed if the DLL is allowing raw
1311
*******************************************************************/
1313
ReadController( int Control, BYTE *Command )
1316
printf( "\nRaw Read (cont=%d):\n", Control );
1317
printf( "\t%02X %02X %02X %02X %02X %02X\n", Command[0], Command[1],
1318
Command[2], Command[3], Command[4], Command[5]);//, Command[6], Command[7] );
1322
/******************************************************************
1324
Purpose: This function is called when a rom is closed.
1327
*******************************************************************/
1334
for( i = 0; i < 4; i++ )
1335
if( controller[i].joystick )
1337
SDL_JoystickClose( controller[i].joystick );
1338
controller[i].joystick = NULL;
1341
// quit SDL joystick subsystem
1342
SDL_QuitSubSystem( SDL_INIT_JOYSTICK );
1344
// release/ungrab mouse
1345
SDL_WM_GrabInput( SDL_GRAB_OFF );
1346
SDL_ShowCursor( 1 );
1351
/******************************************************************
1353
Purpose: This function is called when a rom is open. (from the
1357
*******************************************************************/
1363
// init SDL joystick subsystem
1364
if( !SDL_WasInit( SDL_INIT_JOYSTICK ) )
1365
if( SDL_InitSubSystem( SDL_INIT_JOYSTICK ) == -1 )
1367
fprintf( stderr, "["PLUGIN_NAME"]: Couldn't init SDL joystick subsystem: %s\n", SDL_GetError() );
1372
for( i = 0; i < 4; i++ )
1373
if( controller[i].device >= 0 )
1375
controller[i].joystick = SDL_JoystickOpen( controller[i].device );
1376
if( controller[i].joystick == NULL )
1377
fprintf( stderr, "["PLUGIN_NAME"]: Couldn't open joystick for controller #%d: %s\n", i, SDL_GetError() );
1380
controller[i].joystick = NULL;
1383
if (controller[0].mouse || controller[1].mouse || controller[2].mouse || controller[3].mouse)
1385
SDL_ShowCursor( 0 );
1386
if (SDL_WM_GrabInput( SDL_GRAB_ON ) != SDL_GRAB_ON)
1388
fprintf( stderr, "["PLUGIN_NAME"]: Couldn't grab input! Mouse support won't work!\n" );
1389
fprintf( stderr, "["PLUGIN_NAME"]: Note: You have to set your graphics window fullscreen in order for this to work!\n" );
1397
translateKey( WPARAM wParam )
1401
// for a-z and 0-9 keys windows provides no defines
1402
if (wParam >= 0x41 && wParam <= 0x5a) {
1403
key = wParam - 0x41 + SDLK_a;
1404
} else if (wParam >= 0x30 && wParam <= 0x39) {
1405
key = wParam - 0x30 + SDLK_0;
1406
} else if (wParam == VK_RETURN) {
1408
} else if (wParam == VK_SPACE) {
1410
} else if (wParam == VK_LEFT) {
1412
} else if (wParam == VK_RIGHT) {
1414
} else if (wParam == VK_UP) {
1416
} else if (wParam == VK_DOWN) {
1423
/******************************************************************
1424
Function: WM_KeyDown
1425
Purpose: To pass the WM_KeyDown message from the emulator to the
1427
input: wParam and lParam of the WM_KEYDOWN message.
1429
*******************************************************************/
1431
WM_KeyDown( WPARAM wParam, LPARAM lParam )
1433
myKeyState[translateKey(wParam)] = 1;
1436
/******************************************************************
1438
Purpose: To pass the WM_KEYUP message from the emulator to the
1440
input: wParam and lParam of the WM_KEYDOWN message.
1442
*******************************************************************/
1444
WM_KeyUp( WPARAM wParam, LPARAM lParam )
1446
myKeyState[translateKey(wParam)] = 0;
1449
/******************************************************************
1450
NOTE: THIS HAS BEEN ADDED FOR MUPEN64PLUS AND IS NOT PART OF THE
1452
Function: SetConfigDir
1453
Purpose: To pass the location where config files should be read/
1455
input: path to config directory
1457
*******************************************************************/
1459
SetConfigDir( char *configDir )
1461
strncpy(configdir, configDir, PATH_MAX);