Search
lxdream.org :: lxdream/src/maple/lightgun.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/maple/lightgun.c
changeset 850:28782ebbd01d
next1021:848db285a184
author nkeynes
date Mon Sep 08 07:56:33 2008 +0000 (14 years ago)
permissions -rw-r--r--
last change Add lightgun support
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/maple/lightgun.c Mon Sep 08 07:56:33 2008 +0000
1.3 @@ -0,0 +1,220 @@
1.4 +/**
1.5 + * $Id: lightgun.c 858 2008-09-02 03:34:00Z nkeynes $
1.6 + *
1.7 + * Implementation of the SEGA lightgun device
1.8 + * Part No. HKT-7800
1.9 + *
1.10 + * Copyright (c) 2008 Nathan Keynes.
1.11 + *
1.12 + * This program is free software; you can redistribute it and/or modify
1.13 + * it under the terms of the GNU General Public License as published by
1.14 + * the Free Software Foundation; either version 2 of the License, or
1.15 + * (at your option) any later version.
1.16 + *
1.17 + * This program is distributed in the hope that it will be useful,
1.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.20 + * GNU General Public License for more details.
1.21 + */
1.22 +
1.23 +#include <stdlib.h>
1.24 +#include <stdio.h>
1.25 +#include <string.h>
1.26 +#include <assert.h>
1.27 +#include "display.h"
1.28 +#include "eventq.h"
1.29 +#include "pvr2/pvr2.h"
1.30 +#include "maple/maple.h"
1.31 +
1.32 +#define BUTTON_B 0x00000002
1.33 +#define BUTTON_A 0x00000004
1.34 +#define BUTTON_START 0x00000008
1.35 +#define BUTTON_DPAD_UP 0x00000010
1.36 +#define BUTTON_DPAD_DOWN 0x00000020
1.37 +#define BUTTON_DPAD_LEFT 0x00000040
1.38 +#define BUTTON_DPAD_RIGHT 0x00000080
1.39 +
1.40 +#define LIGHTGUN_IDENT { 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, \
1.41 + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x44, 0x72, 0x65, 0x61, 0x6D, 0x63, 0x61, 0x73, 0x74, 0x20, \
1.42 + 0x47, 0x75, 0x6E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \
1.43 + 0x20, 0x20, 0x20, 0x20, 0x50, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x42, 0x79, 0x20, \
1.44 + 0x6F, 0x72, 0x20, 0x55, 0x6E, 0x64, 0x65, 0x72, 0x20, 0x4C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, \
1.45 + 0x20, 0x46, 0x72, 0x6F, 0x6D, 0x20, 0x53, 0x45, 0x47, 0x41, 0x20, 0x45, 0x4E, 0x54, 0x45, 0x52, \
1.46 + 0x50, 0x52, 0x49, 0x53, 0x45, 0x53, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, \
1.47 + 0xDC, 0x00, 0x2C, 0x01 }
1.48 +#define LIGHTGUN_VERSION { 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x31, 0x2E, 0x30, 0x30, \
1.49 + 0x30, 0x2C, 0x31, 0x39, 0x39, 0x38, 0x2F, 0x30, 0x39, 0x2F, 0x31, 0x36, 0x2C, 0x33, 0x31, 0x35, \
1.50 + 0x2D, 0x36, 0x31, 0x32, 0x35, 0x2D, 0x41, 0x47, 0x20, 0x20, 0x20, 0x2C, 0x55, 0x2C, 0x44, 0x2C, \
1.51 + 0x4C, 0x2C, 0x52, 0x2C, 0x53, 0x2C, 0x41, 0x2C, 0x42, 0x20, 0x4B, 0x65, 0x79, 0x20, 0x26, 0x20, \
1.52 + 0x53, 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x4C, 0x69, 0x6E, 0x65, 0x20, 0x41, 0x6D, \
1.53 + 0x70, 0x2E, 0x20, 0x20 }
1.54 +
1.55 +
1.56 +#define LIGHTGUN_CONFIG_ENTRIES 7
1.57 +
1.58 +static void lightgun_attach( maple_device_t dev );
1.59 +static void lightgun_detach( maple_device_t dev );
1.60 +static void lightgun_destroy( maple_device_t dev );
1.61 +static maple_device_t lightgun_clone( maple_device_t dev );
1.62 +static maple_device_t lightgun_new();
1.63 +static lxdream_config_entry_t lightgun_get_config( maple_device_t dev );
1.64 +static void lightgun_set_config_value( maple_device_t dev, unsigned int key, const gchar *value );
1.65 +static int lightgun_get_cond( maple_device_t dev, int function, unsigned char *outbuf,
1.66 + unsigned int *outlen );
1.67 +static void lightgun_start_gun( maple_device_t dev );
1.68 +static void lightgun_stop_gun( maple_device_t dev );
1.69 +
1.70 +typedef struct lightgun_device {
1.71 + struct maple_device dev;
1.72 + uint32_t condition[2];
1.73 + int gun_active;
1.74 + int mouse_x, mouse_y;
1.75 + struct lxdream_config_entry config[LIGHTGUN_CONFIG_ENTRIES+1];
1.76 +} *lightgun_device_t;
1.77 +
1.78 +struct maple_device_class lightgun_class = { "Sega Lightgun", lightgun_new };
1.79 +
1.80 +static struct lightgun_device base_lightgun = {
1.81 + { MAPLE_DEVICE_TAG, &lightgun_class, MAPLE_GRAB_NO,
1.82 + LIGHTGUN_IDENT, LIGHTGUN_VERSION,
1.83 + lightgun_get_config, lightgun_set_config_value,
1.84 + lightgun_attach, lightgun_detach, lightgun_destroy,
1.85 + lightgun_clone, NULL, NULL, lightgun_get_cond, NULL, NULL, NULL,
1.86 + lightgun_start_gun, lightgun_stop_gun},
1.87 + {0x0000FFFF, 0x80808080}, 0, -1, -1,
1.88 + {{ "dpad left", N_("Dpad left"), CONFIG_TYPE_KEY },
1.89 + { "dpad right", N_("Dpad right"), CONFIG_TYPE_KEY },
1.90 + { "dpad up", N_("Dpad up"), CONFIG_TYPE_KEY },
1.91 + { "dpad down", N_("Dpad down"), CONFIG_TYPE_KEY },
1.92 + { "button A", N_("Button A"), CONFIG_TYPE_KEY },
1.93 + { "button B", N_("Button B"), CONFIG_TYPE_KEY },
1.94 + { "start", N_("Start button"), CONFIG_TYPE_KEY },
1.95 + { NULL, CONFIG_TYPE_NONE }} };
1.96 +
1.97 +static int config_button_map[] = {
1.98 + BUTTON_DPAD_LEFT, BUTTON_DPAD_RIGHT, BUTTON_DPAD_UP, BUTTON_DPAD_DOWN,
1.99 + BUTTON_A, BUTTON_B, BUTTON_START };
1.100 +
1.101 +#define lightgun(x) ((lightgun_device_t)(x))
1.102 +
1.103 +static maple_device_t lightgun_new( )
1.104 +{
1.105 + lightgun_device_t dev = malloc( sizeof(struct lightgun_device) );
1.106 + memcpy( dev, &base_lightgun, sizeof(base_lightgun) );
1.107 + return MAPLE_DEVICE(dev);
1.108 +}
1.109 +
1.110 +static maple_device_t lightgun_clone( maple_device_t srcdevice )
1.111 +{
1.112 + lightgun_device_t src = (lightgun_device_t)srcdevice;
1.113 + lightgun_device_t dev = (lightgun_device_t)lightgun_new();
1.114 + lxdream_copy_config_list( dev->config, src->config );
1.115 + memcpy( dev->condition, src->condition, sizeof(src->condition) );
1.116 + return MAPLE_DEVICE(dev);
1.117 +}
1.118 +
1.119 +/**
1.120 + * Input callback
1.121 + */
1.122 +static void lightgun_key_callback( void *mdev, uint32_t value, uint32_t pressure, gboolean isKeyDown )
1.123 +{
1.124 + lightgun_device_t dev = (lightgun_device_t)mdev;
1.125 + if( isKeyDown ) {
1.126 + dev->condition[0] &= ~value;
1.127 + } else {
1.128 + dev->condition[0] |= value;
1.129 + }
1.130 +}
1.131 +
1.132 +static lxdream_config_entry_t lightgun_get_config( maple_device_t mdev )
1.133 +{
1.134 + lightgun_device_t dev = (lightgun_device_t)mdev;
1.135 + return dev->config;
1.136 +}
1.137 +
1.138 +static void lightgun_set_config_value( maple_device_t mdev, unsigned int key, const gchar *value )
1.139 +{
1.140 + lightgun_device_t dev = (lightgun_device_t)mdev;
1.141 + assert( key < LIGHTGUN_CONFIG_ENTRIES );
1.142 +
1.143 + input_unregister_key( dev->config[key].value, lightgun_key_callback, dev, config_button_map[key] );
1.144 + lxdream_set_config_value( &dev->config[key], value );
1.145 + input_register_key( dev->config[key].value, lightgun_key_callback, dev, config_button_map[key] );
1.146 +}
1.147 +
1.148 +static void lightgun_destroy( maple_device_t mdev )
1.149 +{
1.150 + free( mdev );
1.151 +}
1.152 +
1.153 +
1.154 +static void lightgun_mouse_callback( void *mdev, uint32_t buttons, int32_t x, int32_t y, gboolean absolute )
1.155 +{
1.156 + lightgun_device_t dev = (lightgun_device_t)mdev;
1.157 + if( absolute ) {
1.158 + dev->mouse_x = x;
1.159 + dev->mouse_y = y;
1.160 + if( dev->gun_active ) {
1.161 + pvr2_queue_gun_event( x, y );
1.162 + dev->gun_active = FALSE;
1.163 + }
1.164 + }
1.165 +}
1.166 +
1.167 +/**
1.168 + * Device is being attached to the bus. Go through the config and reserve the
1.169 + * keys we need.
1.170 + */
1.171 +static void lightgun_attach( maple_device_t mdev )
1.172 +{
1.173 + lightgun_device_t dev = (lightgun_device_t)mdev;
1.174 + int i;
1.175 + for( i=0; i<LIGHTGUN_CONFIG_ENTRIES; i++ ) {
1.176 + input_register_key( dev->config[i].value, lightgun_key_callback, dev, config_button_map[i] );
1.177 + }
1.178 + input_register_mouse_hook( TRUE, lightgun_mouse_callback, dev );
1.179 +
1.180 +}
1.181 +
1.182 +static void lightgun_detach( maple_device_t mdev )
1.183 +{
1.184 + lightgun_device_t dev = (lightgun_device_t)mdev;
1.185 + int i;
1.186 + for( i=0; i<LIGHTGUN_CONFIG_ENTRIES; i++ ) {
1.187 + input_unregister_key( dev->config[i].value, lightgun_key_callback, dev, config_button_map[i] );
1.188 + }
1.189 + input_unregister_mouse_hook( lightgun_mouse_callback, dev );
1.190 +
1.191 +}
1.192 +
1.193 +
1.194 +static int lightgun_get_cond( maple_device_t mdev, int function, unsigned char *outbuf,
1.195 + unsigned int *outlen )
1.196 +{
1.197 + lightgun_device_t dev = (lightgun_device_t)mdev;
1.198 + if( function == MAPLE_FUNC_CONTROLLER ) {
1.199 + *outlen = 2;
1.200 + memcpy( outbuf, dev->condition, 8 );
1.201 + return 0;
1.202 + } else {
1.203 + return MAPLE_ERR_FUNC_UNSUP;
1.204 + }
1.205 +}
1.206 +
1.207 +static void lightgun_start_gun( maple_device_t mdev )
1.208 +{
1.209 + lightgun_device_t dev = (lightgun_device_t)mdev;
1.210 + if( dev->mouse_x != -1 && dev->mouse_y != -1 ) {
1.211 + pvr2_queue_gun_event( dev->mouse_x, dev->mouse_y );
1.212 + } else {
1.213 + // Wait for a mouse event
1.214 + dev->gun_active = 1;
1.215 + }
1.216 +}
1.217 +
1.218 +static void lightgun_stop_gun( maple_device_t mdev )
1.219 +{
1.220 + lightgun_device_t dev = (lightgun_device_t)mdev;
1.221 + dev->gun_active = 0;
1.222 + event_cancel( EVENT_GUNPOS );
1.223 +}
.