Search
lxdream.org :: lxdream/src/maple/lightgun.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/maple/lightgun.c
changeset 1034:7044e01148f0
prev1021:848db285a184
next1072:d82e04e6d497
author nkeynes
date Fri Jun 26 05:47:04 2009 +0000 (14 years ago)
permissions -rw-r--r--
last change Refactor path operations into lxpaths.[ch]
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 lxdream_config_entry_t lightgun_get_config( maple_device_t dev );
    61 static void lightgun_set_config_value( maple_device_t dev, unsigned int key, const gchar *value );
    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 typedef struct lightgun_device {
    68     struct maple_device dev;
    69     uint32_t condition[2];
    70     int gun_active;
    71     int mouse_x, mouse_y;
    72     struct lxdream_config_entry config[LIGHTGUN_CONFIG_ENTRIES+1];
    73 } *lightgun_device_t;
    75 struct maple_device_class lightgun_class = { "Sega Lightgun", 
    76         MAPLE_TYPE_PRIMARY|MAPLE_GRAB_NO|MAPLE_SLOTS_2, lightgun_new };
    78 static struct lightgun_device base_lightgun = {
    79         { MAPLE_DEVICE_TAG, &lightgun_class,
    80           LIGHTGUN_IDENT, LIGHTGUN_VERSION, 
    81           lightgun_get_config, lightgun_set_config_value, 
    82           lightgun_attach, lightgun_detach, lightgun_destroy,
    83           lightgun_clone, NULL, NULL, lightgun_get_cond, NULL, NULL, NULL, NULL,
    84           lightgun_start_gun, lightgun_stop_gun},
    85           {0x0000FFFF, 0x80808080}, 0, -1, -1, 
    86           {{ "dpad left", N_("Dpad left"), CONFIG_TYPE_KEY },
    87            { "dpad right", N_("Dpad right"), CONFIG_TYPE_KEY },
    88            { "dpad up", N_("Dpad up"), CONFIG_TYPE_KEY },
    89            { "dpad down", N_("Dpad down"), CONFIG_TYPE_KEY },
    90            { "button A", N_("Button A"), CONFIG_TYPE_KEY },
    91            { "button B", N_("Button B"), CONFIG_TYPE_KEY },
    92            { "start", N_("Start button"), CONFIG_TYPE_KEY },
    93            { NULL, CONFIG_TYPE_NONE }} };
    95 static int config_button_map[] = { 
    96         BUTTON_DPAD_LEFT, BUTTON_DPAD_RIGHT, BUTTON_DPAD_UP, BUTTON_DPAD_DOWN,
    97         BUTTON_A, BUTTON_B, BUTTON_START };
    99 #define lightgun(x) ((lightgun_device_t)(x))
   101 static maple_device_t lightgun_new( )
   102 {
   103     lightgun_device_t dev = malloc( sizeof(struct lightgun_device) );
   104     memcpy( dev, &base_lightgun, sizeof(base_lightgun) );
   105     return MAPLE_DEVICE(dev);
   106 }
   108 static maple_device_t lightgun_clone( maple_device_t srcdevice )
   109 {
   110     lightgun_device_t src = (lightgun_device_t)srcdevice;
   111     lightgun_device_t dev = (lightgun_device_t)lightgun_new();
   112     lxdream_copy_config_list( dev->config, src->config );
   113     memcpy( dev->condition, src->condition, sizeof(src->condition) );
   114     return MAPLE_DEVICE(dev);
   115 }
   117 /**
   118  * Input callback 
   119  */
   120 static void lightgun_key_callback( void *mdev, uint32_t value, uint32_t pressure, gboolean isKeyDown )
   121 {
   122     lightgun_device_t dev = (lightgun_device_t)mdev;
   123     if( isKeyDown ) {
   124         dev->condition[0] &= ~value;
   125     } else {
   126         dev->condition[0] |= value;
   127     }
   128 }
   130 static lxdream_config_entry_t lightgun_get_config( maple_device_t mdev )
   131 {
   132     lightgun_device_t dev = (lightgun_device_t)mdev;
   133     return dev->config;
   134 }
   136 static void lightgun_set_config_value( maple_device_t mdev, unsigned int key, const gchar *value )
   137 {
   138     lightgun_device_t dev = (lightgun_device_t)mdev;
   139     assert( key < LIGHTGUN_CONFIG_ENTRIES );
   141     input_unregister_key( dev->config[key].value, lightgun_key_callback, dev, config_button_map[key] );
   142     lxdream_set_config_value( &dev->config[key], value );
   143     input_register_key( dev->config[key].value, lightgun_key_callback, dev, config_button_map[key] );
   144 }
   146 static void lightgun_destroy( maple_device_t mdev )
   147 {
   148     free( mdev );
   149 }
   152 static void lightgun_mouse_callback( void *mdev, uint32_t buttons, int32_t x, int32_t y, gboolean absolute )
   153 {
   154     lightgun_device_t dev = (lightgun_device_t)mdev;
   155     if( absolute ) {
   156         dev->mouse_x = x;
   157         dev->mouse_y = y;
   158         if( dev->gun_active ) {
   159             pvr2_queue_gun_event( x, y );
   160             dev->gun_active = FALSE;
   161         }
   162     }
   163 }
   165 /**
   166  * Device is being attached to the bus. Go through the config and reserve the
   167  * keys we need.
   168  */
   169 static void lightgun_attach( maple_device_t mdev )
   170 {
   171     lightgun_device_t dev = (lightgun_device_t)mdev;
   172     int i;
   173     for( i=0; i<LIGHTGUN_CONFIG_ENTRIES; i++ ) {
   174         input_register_key( dev->config[i].value, lightgun_key_callback, dev, config_button_map[i] );
   175     }
   176     input_register_mouse_hook( TRUE, lightgun_mouse_callback, dev );
   178 }
   180 static void lightgun_detach( maple_device_t mdev )
   181 {
   182     lightgun_device_t dev = (lightgun_device_t)mdev;
   183     int i;
   184     for( i=0; i<LIGHTGUN_CONFIG_ENTRIES; i++ ) {
   185         input_unregister_key( dev->config[i].value, lightgun_key_callback, dev, config_button_map[i] );
   186     }
   187     input_unregister_mouse_hook( lightgun_mouse_callback, dev );
   189 }
   192 static int lightgun_get_cond( maple_device_t mdev, int function, unsigned char *outbuf,
   193                          unsigned int *outlen )
   194 {
   195     lightgun_device_t dev = (lightgun_device_t)mdev;
   196     if( function == MAPLE_FUNC_CONTROLLER ) {
   197         *outlen = 2;
   198         memcpy( outbuf, dev->condition, 8 );
   199         return 0;
   200     } else {
   201         return MAPLE_ERR_FUNC_UNSUP;
   202     }
   203 }
   205 static void lightgun_start_gun( maple_device_t mdev )
   206 {
   207     lightgun_device_t dev = (lightgun_device_t)mdev;
   208     if( dev->mouse_x != -1 && dev->mouse_y != -1 ) {
   209         pvr2_queue_gun_event( dev->mouse_x, dev->mouse_y );
   210     } else {
   211         // Wait for a mouse event
   212         dev->gun_active = 1;
   213     }
   214 }
   216 static void lightgun_stop_gun( maple_device_t mdev )
   217 {
   218     lightgun_device_t dev = (lightgun_device_t)mdev;
   219     dev->gun_active = 0;
   220     event_cancel( EVENT_GUNPOS );
   221 }
.