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