Search
lxdream.org :: lxdream/src/maple/lightgun.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/maple/lightgun.c
changeset 1298:d0eb2307b847
prev1072:d82e04e6d497
author nkeynes
date Wed Feb 04 08:38:23 2015 +1000 (5 years ago)
permissions -rw-r--r--
last change Fix assorted compile warnings reported by Clang
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@1072
    60
static void lightgun_key_callback( void *mdev, uint32_t value, uint32_t pressure, gboolean isKeyDown );
nkeynes@1072
    61
static lxdream_config_group_t lightgun_get_config( maple_device_t dev );
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@1072
    72
    struct lxdream_config_group config;
nkeynes@850
    73
} *lightgun_device_t;
nkeynes@850
    74
nkeynes@1034
    75
struct maple_device_class lightgun_class = { "Sega Lightgun", 
nkeynes@1034
    76
        MAPLE_TYPE_PRIMARY|MAPLE_GRAB_NO|MAPLE_SLOTS_2, lightgun_new };
nkeynes@850
    77
nkeynes@850
    78
static struct lightgun_device base_lightgun = {
nkeynes@1034
    79
        { MAPLE_DEVICE_TAG, &lightgun_class,
nkeynes@850
    80
          LIGHTGUN_IDENT, LIGHTGUN_VERSION, 
nkeynes@1072
    81
          lightgun_get_config,
nkeynes@850
    82
          lightgun_attach, lightgun_detach, lightgun_destroy,
nkeynes@1034
    83
          lightgun_clone, NULL, NULL, lightgun_get_cond, NULL, NULL, NULL, NULL,
nkeynes@850
    84
          lightgun_start_gun, lightgun_stop_gun},
nkeynes@1072
    85
          {0x0000FFFF, 0x80808080}, 0, -1, -1,
nkeynes@1072
    86
          {"Sega Lightgun", NULL, lightgun_key_callback, NULL,
nkeynes@1072
    87
           {{ "dpad left", N_("Dpad left"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_LEFT },
nkeynes@1072
    88
            { "dpad right", N_("Dpad right"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_RIGHT },
nkeynes@1072
    89
            { "dpad up", N_("Dpad up"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_UP },
nkeynes@1072
    90
            { "dpad down", N_("Dpad down"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_DOWN },
nkeynes@1072
    91
            { "button A", N_("Button A"), CONFIG_TYPE_KEY, NULL, BUTTON_A },
nkeynes@1072
    92
            { "button B", N_("Button B"), CONFIG_TYPE_KEY, NULL, BUTTON_B },
nkeynes@1072
    93
            { "start", N_("Start button"), CONFIG_TYPE_KEY, NULL, BUTTON_START },
nkeynes@1072
    94
            { NULL, CONFIG_TYPE_NONE }}}  };
nkeynes@850
    95
nkeynes@1072
    96
nkeynes@850
    97
#define lightgun(x) ((lightgun_device_t)(x))
nkeynes@850
    98
nkeynes@850
    99
static maple_device_t lightgun_new( )
nkeynes@850
   100
{
nkeynes@850
   101
    lightgun_device_t dev = malloc( sizeof(struct lightgun_device) );
nkeynes@850
   102
    memcpy( dev, &base_lightgun, sizeof(base_lightgun) );
nkeynes@1072
   103
    dev->config.data = dev;
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@1072
   111
    lxdream_copy_config_group( &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@1072
   116
static lxdream_config_group_t lightgun_get_config( maple_device_t mdev )
nkeynes@1072
   117
{
nkeynes@1072
   118
    lightgun_device_t dev = (lightgun_device_t)mdev;
nkeynes@1072
   119
    return &dev->config;
nkeynes@1072
   120
}
nkeynes@1072
   121
nkeynes@1072
   122
static void lightgun_destroy( maple_device_t mdev )
nkeynes@1072
   123
{
nkeynes@1072
   124
    free( mdev );
nkeynes@1072
   125
}
nkeynes@1072
   126
nkeynes@850
   127
/**
nkeynes@850
   128
 * Input callback 
nkeynes@850
   129
 */
nkeynes@850
   130
static void lightgun_key_callback( void *mdev, uint32_t value, uint32_t pressure, gboolean isKeyDown )
nkeynes@850
   131
{
nkeynes@850
   132
    lightgun_device_t dev = (lightgun_device_t)mdev;
nkeynes@850
   133
    if( isKeyDown ) {
nkeynes@850
   134
        dev->condition[0] &= ~value;
nkeynes@850
   135
    } else {
nkeynes@850
   136
        dev->condition[0] |= value;
nkeynes@850
   137
    }
nkeynes@850
   138
}
nkeynes@850
   139
nkeynes@850
   140
static void lightgun_mouse_callback( void *mdev, uint32_t buttons, int32_t x, int32_t y, gboolean absolute )
nkeynes@850
   141
{
nkeynes@850
   142
    lightgun_device_t dev = (lightgun_device_t)mdev;
nkeynes@850
   143
    if( absolute ) {
nkeynes@850
   144
        dev->mouse_x = x;
nkeynes@850
   145
        dev->mouse_y = y;
nkeynes@850
   146
        if( dev->gun_active ) {
nkeynes@850
   147
            pvr2_queue_gun_event( x, y );
nkeynes@850
   148
            dev->gun_active = FALSE;
nkeynes@850
   149
        }
nkeynes@850
   150
    }
nkeynes@850
   151
}
nkeynes@850
   152
nkeynes@850
   153
/**
nkeynes@850
   154
 * Device is being attached to the bus. Go through the config and reserve the
nkeynes@850
   155
 * keys we need.
nkeynes@850
   156
 */
nkeynes@850
   157
static void lightgun_attach( maple_device_t mdev )
nkeynes@850
   158
{
nkeynes@850
   159
    lightgun_device_t dev = (lightgun_device_t)mdev;
nkeynes@1072
   160
    dev->config.on_change = input_keygroup_changed;
nkeynes@1072
   161
    input_register_keygroup( &dev->config );
nkeynes@850
   162
    input_register_mouse_hook( TRUE, lightgun_mouse_callback, dev );
nkeynes@850
   163
}
nkeynes@850
   164
nkeynes@850
   165
static void lightgun_detach( maple_device_t mdev )
nkeynes@850
   166
{
nkeynes@850
   167
    lightgun_device_t dev = (lightgun_device_t)mdev;
nkeynes@1072
   168
    input_unregister_keygroup( &dev->config );
nkeynes@1072
   169
    dev->config.on_change = NULL;
nkeynes@850
   170
    input_unregister_mouse_hook( lightgun_mouse_callback, dev );
nkeynes@850
   171
nkeynes@850
   172
}
nkeynes@850
   173
nkeynes@850
   174
nkeynes@850
   175
static int lightgun_get_cond( maple_device_t mdev, int function, unsigned char *outbuf,
nkeynes@850
   176
                         unsigned int *outlen )
nkeynes@850
   177
{
nkeynes@850
   178
    lightgun_device_t dev = (lightgun_device_t)mdev;
nkeynes@850
   179
    if( function == MAPLE_FUNC_CONTROLLER ) {
nkeynes@850
   180
        *outlen = 2;
nkeynes@850
   181
        memcpy( outbuf, dev->condition, 8 );
nkeynes@850
   182
        return 0;
nkeynes@850
   183
    } else {
nkeynes@850
   184
        return MAPLE_ERR_FUNC_UNSUP;
nkeynes@850
   185
    }
nkeynes@850
   186
}
nkeynes@850
   187
nkeynes@850
   188
static void lightgun_start_gun( maple_device_t mdev )
nkeynes@850
   189
{
nkeynes@850
   190
    lightgun_device_t dev = (lightgun_device_t)mdev;
nkeynes@850
   191
    if( dev->mouse_x != -1 && dev->mouse_y != -1 ) {
nkeynes@850
   192
        pvr2_queue_gun_event( dev->mouse_x, dev->mouse_y );
nkeynes@850
   193
    } else {
nkeynes@850
   194
        // Wait for a mouse event
nkeynes@850
   195
        dev->gun_active = 1;
nkeynes@850
   196
    }
nkeynes@850
   197
}
nkeynes@850
   198
nkeynes@850
   199
static void lightgun_stop_gun( maple_device_t mdev )
nkeynes@850
   200
{
nkeynes@850
   201
    lightgun_device_t dev = (lightgun_device_t)mdev;
nkeynes@850
   202
    dev->gun_active = 0;
nkeynes@850
   203
    event_cancel( EVENT_GUNPOS );
nkeynes@850
   204
}
.