File: wiimouse.c

package info (click to toggle)
fuse-emulator 1.1.1%2Bdfsg1-2
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 11,120 kB
  • ctags: 8,968
  • sloc: ansic: 78,960; sh: 11,228; perl: 3,742; makefile: 1,104; yacc: 236; lex: 140
file content (207 lines) | stat: -rw-r--r-- 5,847 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/* wiimouse.c: routines for dealing with the Wiimote as a mouse
   Copyright (c) 2008-2009 Bjoern Giesler, Marek Januszewski

   $Id: wiimouse.c 3995 2009-04-04 20:19:32Z specu $

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

   Author contact information:

   E-mail: bjoern@giesler.de

*/

#include <config.h>

#include <stdio.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define GEKKO

#include <wiiuse/wpad.h>

#include "fuse.h"
#include "keyboard.h"
#include "ui/ui.h"
#include "ui/wii/wiidisplay.h"

static WPADData paddata;
static WPADData oldpaddata;

/* The below is to remember last nunchuck position when navigating the menus.
   It is used so the user needs to release nunchuck stick and then press it
   again to go to the next menu item (holding the direction will to next menu
   item just once, no matter how long the direction is being held). */
#define LEFT  1
#define RIGHT 2
#define UP    3
#define DOWN  4
static u8 last_nunchuck[ 2 ]; /* for 2 controllers */

int
wiimouse_init( void )
{
  WPAD_Init();
  WPAD_SetDataFormat( WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR );
  WPAD_SetIdleTimeout( 60 );

  memset( &paddata, 0, sizeof(paddata) );
  memset( &oldpaddata, 0, sizeof(oldpaddata) );
  ui_mouse_present = 1;
  return 0;
}

int
wiimouse_end( void )
{
  return 0;
}

void
wiimouse_get_position( int *x, int *y )
{
  if( paddata.ir.state == 0 ) *x = *y = -1;

  *x = paddata.ir.x;
  *y = paddata.ir.y;
}

void
mouse_update( void )
{
  /* do this ONLY here. wiijoystick depends on it as well, but
     mouse_update is called regardless of whether the emulation is
     running or not, ui_joystick_poll only if running. So we do this
     here and risk lagging 1 frame behind on the joystick
     FIXME: A function that does this only once depending on the
     current frame counter would be better */

  int ctrlr; /* Which controller */
  u32 wm_down; /* Wii Remote buttons that are down */
  WPADData *wpad;
  joystick_t js;

  WPAD_ScanPads();

#define POST_KEYPRESS(pressed) do {		\
    input_event_t fuse_event; \
    fuse_event.type = INPUT_EVENT_KEYPRESS; \
    fuse_event.types.key.native_key = pressed; \
    fuse_event.types.key.spectrum_key = pressed; \
    input_event(&fuse_event); \
  } while(0)
  
#define POST_KEYRELEASE(pressed) do {	    \
    input_event_t fuse_event; \
    fuse_event.type = INPUT_EVENT_KEYRELEASE; \
    fuse_event.types.key.native_key = pressed; \
    fuse_event.types.key.spectrum_key = pressed; \
    input_event(&fuse_event); \
  } while(0)

  for( ctrlr = 0; ctrlr < 2; ctrlr++ ) {

    wpad = WPAD_Data( ctrlr );
    if( !wpad ) continue;

    wm_down = wpad->btns_d;

    /* we don't bother with key releases here; this is only for entering
       and/or using the menu, which seems to at best disregard
       keyreleases and at worst react badly to them. */
  
    if(fuse_emulation_paused) {
      if( wm_down & WPAD_BUTTON_DOWN )
        POST_KEYPRESS( INPUT_JOYSTICK_RIGHT );
      else if( wm_down & WPAD_BUTTON_UP )
        POST_KEYPRESS( INPUT_JOYSTICK_LEFT );
      else if( wm_down & WPAD_BUTTON_LEFT )
        POST_KEYPRESS( INPUT_JOYSTICK_DOWN );
      else if( wm_down & WPAD_BUTTON_RIGHT )
        POST_KEYPRESS( INPUT_JOYSTICK_UP );
      else if( ( wm_down & WPAD_BUTTON_A ) || ( wm_down & WPAD_BUTTON_2 ) )
        POST_KEYPRESS( INPUT_JOYSTICK_FIRE_1 );
      else if( ( wm_down & WPAD_BUTTON_B ) || ( wm_down & WPAD_BUTTON_1 )
           || ( wm_down & WPAD_BUTTON_HOME ) )
        POST_KEYPRESS( INPUT_JOYSTICK_FIRE_2 );
  
      if( wpad->exp.type == EXP_NUNCHUK ) {
  
        js = wpad->exp.nunchuk.js;

        if( js.mag >= 0.5 ) {
          /* left */
          if( js.ang >= 270-45 && js.ang <= 270+45 ) {
            if( last_nunchuck[ ctrlr ] != LEFT ) {
              POST_KEYPRESS( INPUT_JOYSTICK_LEFT );
              last_nunchuck[ ctrlr ] = LEFT;
            }
          }
          /* right */
          else if( js.ang >= 90-45 && js.ang <= 90+45 ) {
            if( last_nunchuck[ ctrlr ] != RIGHT ) {
              POST_KEYPRESS( INPUT_JOYSTICK_RIGHT );
              last_nunchuck[ ctrlr ] = RIGHT;
            }
          }
          /* up */
          else if( js.ang >= 360-45 || js.ang <= 45 ) {
            if( last_nunchuck[ ctrlr ] != UP ) {
              POST_KEYPRESS( INPUT_JOYSTICK_UP );
              last_nunchuck[ ctrlr ] = UP;
            }
          }
          /* down */
          else if( js.ang >= 180-45 && js.ang <= 180+45 ) {
            if( last_nunchuck[ ctrlr ] != DOWN ) {
              POST_KEYPRESS( INPUT_JOYSTICK_DOWN );
              last_nunchuck[ ctrlr ] = DOWN;
            }
          }
        }
        else
          last_nunchuck[ ctrlr ] = 0;
      }
    } else {
      if( wm_down & WPAD_BUTTON_HOME )
        POST_KEYPRESS( INPUT_KEY_F1 );
    }
  }

  WPAD_ReadEvent( 0, &paddata );

  if( paddata.ir.state == 0 )
    wiidisplay_showmouse( -1, -1 );
  else
    wiidisplay_showmouse( paddata.ir.x/560.0f, paddata.ir.y/420.0f );  
}

int
ui_mouse_grab( int startup GCC_UNUSED )
{
  return 1;
}

int
ui_mouse_release( int suspend )
{
  return !suspend;
}