filename | src/maple/lightgun.c |
changeset | 1072:d82e04e6d497 |
prev | 1034:7044e01148f0 |
next | 1298:d0eb2307b847 |
author | nkeynes |
date | Sun Feb 12 16:30:26 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Add -Werror for mregparm check, so it actually fails if mregparm isn't accepted |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * Implementation of the SEGA lightgun device
5 * Part No. HKT-7800
6 *
7 * Copyright (c) 2008 Nathan Keynes.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <assert.h>
24 #include "display.h"
25 #include "eventq.h"
26 #include "pvr2/pvr2.h"
27 #include "maple/maple.h"
29 #define BUTTON_B 0x00000002
30 #define BUTTON_A 0x00000004
31 #define BUTTON_START 0x00000008
32 #define BUTTON_DPAD_UP 0x00000010
33 #define BUTTON_DPAD_DOWN 0x00000020
34 #define BUTTON_DPAD_LEFT 0x00000040
35 #define BUTTON_DPAD_RIGHT 0x00000080
37 #define LIGHTGUN_IDENT { 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, \
38 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x44, 0x72, 0x65, 0x61, 0x6D, 0x63, 0x61, 0x73, 0x74, 0x20, \
39 0x47, 0x75, 0x6E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \
40 0x20, 0x20, 0x20, 0x20, 0x50, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x42, 0x79, 0x20, \
41 0x6F, 0x72, 0x20, 0x55, 0x6E, 0x64, 0x65, 0x72, 0x20, 0x4C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, \
42 0x20, 0x46, 0x72, 0x6F, 0x6D, 0x20, 0x53, 0x45, 0x47, 0x41, 0x20, 0x45, 0x4E, 0x54, 0x45, 0x52, \
43 0x50, 0x52, 0x49, 0x53, 0x45, 0x53, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, \
44 0xDC, 0x00, 0x2C, 0x01 }
45 #define LIGHTGUN_VERSION { 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x31, 0x2E, 0x30, 0x30, \
46 0x30, 0x2C, 0x31, 0x39, 0x39, 0x38, 0x2F, 0x30, 0x39, 0x2F, 0x31, 0x36, 0x2C, 0x33, 0x31, 0x35, \
47 0x2D, 0x36, 0x31, 0x32, 0x35, 0x2D, 0x41, 0x47, 0x20, 0x20, 0x20, 0x2C, 0x55, 0x2C, 0x44, 0x2C, \
48 0x4C, 0x2C, 0x52, 0x2C, 0x53, 0x2C, 0x41, 0x2C, 0x42, 0x20, 0x4B, 0x65, 0x79, 0x20, 0x26, 0x20, \
49 0x53, 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x4C, 0x69, 0x6E, 0x65, 0x20, 0x41, 0x6D, \
50 0x70, 0x2E, 0x20, 0x20 }
53 #define LIGHTGUN_CONFIG_ENTRIES 7
55 static void lightgun_attach( maple_device_t dev );
56 static void lightgun_detach( maple_device_t dev );
57 static void lightgun_destroy( maple_device_t dev );
58 static maple_device_t lightgun_clone( maple_device_t dev );
59 static maple_device_t lightgun_new();
60 static void lightgun_key_callback( void *mdev, uint32_t value, uint32_t pressure, gboolean isKeyDown );
61 static lxdream_config_group_t lightgun_get_config( maple_device_t dev );
62 static int lightgun_get_cond( maple_device_t dev, int function, unsigned char *outbuf,
63 unsigned int *outlen );
64 static void lightgun_start_gun( maple_device_t dev );
65 static void lightgun_stop_gun( maple_device_t dev );
67 static gboolean lightgun_set_config_value( lxdream_config_group_t group, unsigned int key,
68 const gchar *oldvalue, const gchar *value );
70 typedef struct lightgun_device {
71 struct maple_device dev;
72 uint32_t condition[2];
73 int gun_active;
74 int mouse_x, mouse_y;
75 struct lxdream_config_group config;
76 } *lightgun_device_t;
78 struct maple_device_class lightgun_class = { "Sega Lightgun",
79 MAPLE_TYPE_PRIMARY|MAPLE_GRAB_NO|MAPLE_SLOTS_2, lightgun_new };
81 static struct lightgun_device base_lightgun = {
82 { MAPLE_DEVICE_TAG, &lightgun_class,
83 LIGHTGUN_IDENT, LIGHTGUN_VERSION,
84 lightgun_get_config,
85 lightgun_attach, lightgun_detach, lightgun_destroy,
86 lightgun_clone, NULL, NULL, lightgun_get_cond, NULL, NULL, NULL, NULL,
87 lightgun_start_gun, lightgun_stop_gun},
88 {0x0000FFFF, 0x80808080}, 0, -1, -1,
89 {"Sega Lightgun", NULL, lightgun_key_callback, NULL,
90 {{ "dpad left", N_("Dpad left"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_LEFT },
91 { "dpad right", N_("Dpad right"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_RIGHT },
92 { "dpad up", N_("Dpad up"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_UP },
93 { "dpad down", N_("Dpad down"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_DOWN },
94 { "button A", N_("Button A"), CONFIG_TYPE_KEY, NULL, BUTTON_A },
95 { "button B", N_("Button B"), CONFIG_TYPE_KEY, NULL, BUTTON_B },
96 { "start", N_("Start button"), CONFIG_TYPE_KEY, NULL, BUTTON_START },
97 { NULL, CONFIG_TYPE_NONE }}} };
100 #define lightgun(x) ((lightgun_device_t)(x))
102 static maple_device_t lightgun_new( )
103 {
104 lightgun_device_t dev = malloc( sizeof(struct lightgun_device) );
105 memcpy( dev, &base_lightgun, sizeof(base_lightgun) );
106 dev->config.data = dev;
107 return MAPLE_DEVICE(dev);
108 }
110 static maple_device_t lightgun_clone( maple_device_t srcdevice )
111 {
112 lightgun_device_t src = (lightgun_device_t)srcdevice;
113 lightgun_device_t dev = (lightgun_device_t)lightgun_new();
114 lxdream_copy_config_group( &dev->config, &src->config );
115 memcpy( dev->condition, src->condition, sizeof(src->condition) );
116 return MAPLE_DEVICE(dev);
117 }
119 static lxdream_config_group_t lightgun_get_config( maple_device_t mdev )
120 {
121 lightgun_device_t dev = (lightgun_device_t)mdev;
122 return &dev->config;
123 }
125 static void lightgun_destroy( maple_device_t mdev )
126 {
127 free( mdev );
128 }
130 /**
131 * Input callback
132 */
133 static void lightgun_key_callback( void *mdev, uint32_t value, uint32_t pressure, gboolean isKeyDown )
134 {
135 lightgun_device_t dev = (lightgun_device_t)mdev;
136 if( isKeyDown ) {
137 dev->condition[0] &= ~value;
138 } else {
139 dev->condition[0] |= value;
140 }
141 }
143 static void lightgun_mouse_callback( void *mdev, uint32_t buttons, int32_t x, int32_t y, gboolean absolute )
144 {
145 lightgun_device_t dev = (lightgun_device_t)mdev;
146 if( absolute ) {
147 dev->mouse_x = x;
148 dev->mouse_y = y;
149 if( dev->gun_active ) {
150 pvr2_queue_gun_event( x, y );
151 dev->gun_active = FALSE;
152 }
153 }
154 }
156 /**
157 * Device is being attached to the bus. Go through the config and reserve the
158 * keys we need.
159 */
160 static void lightgun_attach( maple_device_t mdev )
161 {
162 lightgun_device_t dev = (lightgun_device_t)mdev;
163 dev->config.on_change = input_keygroup_changed;
164 input_register_keygroup( &dev->config );
165 input_register_mouse_hook( TRUE, lightgun_mouse_callback, dev );
166 }
168 static void lightgun_detach( maple_device_t mdev )
169 {
170 lightgun_device_t dev = (lightgun_device_t)mdev;
171 input_unregister_keygroup( &dev->config );
172 dev->config.on_change = NULL;
173 input_unregister_mouse_hook( lightgun_mouse_callback, dev );
175 }
178 static int lightgun_get_cond( maple_device_t mdev, int function, unsigned char *outbuf,
179 unsigned int *outlen )
180 {
181 lightgun_device_t dev = (lightgun_device_t)mdev;
182 if( function == MAPLE_FUNC_CONTROLLER ) {
183 *outlen = 2;
184 memcpy( outbuf, dev->condition, 8 );
185 return 0;
186 } else {
187 return MAPLE_ERR_FUNC_UNSUP;
188 }
189 }
191 static void lightgun_start_gun( maple_device_t mdev )
192 {
193 lightgun_device_t dev = (lightgun_device_t)mdev;
194 if( dev->mouse_x != -1 && dev->mouse_y != -1 ) {
195 pvr2_queue_gun_event( dev->mouse_x, dev->mouse_y );
196 } else {
197 // Wait for a mouse event
198 dev->gun_active = 1;
199 }
200 }
202 static void lightgun_stop_gun( maple_device_t mdev )
203 {
204 lightgun_device_t dev = (lightgun_device_t)mdev;
205 dev->gun_active = 0;
206 event_cancel( EVENT_GUNPOS );
207 }
.