nkeynes@31 | 1 | /**
|
nkeynes@561 | 2 | * $Id$
|
nkeynes@31 | 3 | *
|
nkeynes@31 | 4 | * Implements the standard dreamcast controller
|
nkeynes@848 | 5 | * Part No. HKT-7700
|
nkeynes@31 | 6 | *
|
nkeynes@31 | 7 | * Copyright (c) 2005 Nathan Keynes.
|
nkeynes@31 | 8 | *
|
nkeynes@31 | 9 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@31 | 10 | * it under the terms of the GNU General Public License as published by
|
nkeynes@31 | 11 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@31 | 12 | * (at your option) any later version.
|
nkeynes@31 | 13 | *
|
nkeynes@31 | 14 | * This program is distributed in the hope that it will be useful,
|
nkeynes@31 | 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@31 | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@31 | 17 | * GNU General Public License for more details.
|
nkeynes@31 | 18 | */
|
nkeynes@31 | 19 |
|
nkeynes@2 | 20 | #include <stdlib.h>
|
nkeynes@770 | 21 | #include <assert.h>
|
nkeynes@2 | 22 | #include "dream.h"
|
nkeynes@144 | 23 | #include "dreamcast.h"
|
nkeynes@429 | 24 | #include "display.h"
|
nkeynes@2 | 25 | #include "maple.h"
|
nkeynes@846 | 26 |
|
nkeynes@846 | 27 | /* First word of controller condition */
|
nkeynes@846 | 28 | #define BUTTON_C 0x00000001 /* not on standard controller */
|
nkeynes@846 | 29 | #define BUTTON_B 0x00000002
|
nkeynes@846 | 30 | #define BUTTON_A 0x00000004
|
nkeynes@846 | 31 | #define BUTTON_START 0x00000008
|
nkeynes@846 | 32 | #define BUTTON_DPAD_UP 0x00000010
|
nkeynes@846 | 33 | #define BUTTON_DPAD_DOWN 0x00000020
|
nkeynes@846 | 34 | #define BUTTON_DPAD_LEFT 0x00000040
|
nkeynes@846 | 35 | #define BUTTON_DPAD_RIGHT 0x00000080
|
nkeynes@846 | 36 | #define BUTTON_Z 0x00000100 /* not on standard controller */
|
nkeynes@846 | 37 | #define BUTTON_Y 0x00000200
|
nkeynes@846 | 38 | #define BUTTON_X 0x00000400
|
nkeynes@846 | 39 | #define BUTTON_D 0x00000800 /* not on standard controller */
|
nkeynes@846 | 40 | #define BUTTON_LEFT_TRIGGER 0xFF000000 /* Bitmask */
|
nkeynes@846 | 41 | #define BUTTON_RIGHT_TRIGGER 0x00FF0000 /* Bitmask */
|
nkeynes@846 | 42 |
|
nkeynes@846 | 43 | /* Second word of controller condition (bitmasks) */
|
nkeynes@1010 | 44 | #define JOY_X_AXIS_MASK 0x000000FF
|
nkeynes@1010 | 45 | #define JOY_Y_AXIS_MASK 0x0000FF00
|
nkeynes@846 | 46 | #define JOY_X_AXIS_CENTER 0x00000080
|
nkeynes@846 | 47 | #define JOY_Y_AXIS_CENTER 0x00008000
|
nkeynes@1010 | 48 | #define JOY2_X_AXIS_MASK 0x00FF0000 /* not on standard controller */
|
nkeynes@1010 | 49 | #define JOY2_Y_AXIS_MASK 0xFF000000 /* not on standard controller */
|
nkeynes@1010 | 50 |
|
nkeynes@1010 | 51 | #define JOY_X_AXIS(x) ((x)&0xFF)
|
nkeynes@1010 | 52 | #define JOY_Y_AXIS(y) (((y)&0xFF)<<8)
|
nkeynes@846 | 53 |
|
nkeynes@846 | 54 | /* The following bits are used by the emulator for flags but don't actually
|
nkeynes@846 | 55 | * appear in the hardware
|
nkeynes@846 | 56 | */
|
nkeynes@846 | 57 | #define JOY_LEFT 0x80000001
|
nkeynes@846 | 58 | #define JOY_RIGHT 0x80000002
|
nkeynes@846 | 59 | #define JOY_UP 0x80000004
|
nkeynes@846 | 60 | #define JOY_DOWN 0x80000008
|
nkeynes@846 | 61 |
|
nkeynes@846 | 62 | /* Standard controller ID */
|
nkeynes@846 | 63 | #define CONTROLLER_IDENT {0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, \
|
nkeynes@846 | 64 | 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x63, 0x61, 0x73, 0x74, 0x20, \
|
nkeynes@846 | 65 | 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \
|
nkeynes@846 | 66 | 0x20, 0x20, 0x20, 0x20, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x42, 0x79, 0x20, \
|
nkeynes@846 | 67 | 0x6f, 0x72, 0x20, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, \
|
nkeynes@846 | 68 | 0x20, 0x46, 0x72, 0x6f, 0x6d, 0x20, 0x53, 0x45, 0x47, 0x41, 0x20, 0x45, 0x4e, 0x54, 0x45, 0x52, \
|
nkeynes@846 | 69 | 0x50, 0x52, 0x49, 0x53, 0x45, 0x53, 0x2c, 0x4c, 0x54, 0x44, 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, \
|
nkeynes@846 | 70 | 0xae, 0x01, 0xf4, 0x01}
|
nkeynes@846 | 71 | #define CONTROLLER_VERSION {0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x2e, 0x30, 0x31, \
|
nkeynes@846 | 72 | 0x30, 0x2c, 0x31, 0x39, 0x39, 0x38, 0x2f, 0x30, 0x39, 0x2f, 0x32, 0x38, 0x2c, 0x33, 0x31, 0x35, \
|
nkeynes@846 | 73 | 0x2d, 0x36, 0x32, 0x31, 0x31, 0x2d, 0x41, 0x42, 0x20, 0x20, 0x20, 0x2c, 0x41, 0x6e, 0x61, 0x6c, \
|
nkeynes@846 | 74 | 0x6f, 0x67, 0x20, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x3a, 0x20, 0x54, 0x68, 0x65, 0x20, \
|
nkeynes@846 | 75 | 0x34, 0x74, 0x68, 0x20, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x35, 0x2f, 0x38, 0x20, \
|
nkeynes@846 | 76 | 0x20, 0x2b, 0x44, 0x46 }
|
nkeynes@2 | 77 |
|
nkeynes@770 | 78 | #define CONTROLLER_CONFIG_ENTRIES 15
|
nkeynes@144 | 79 |
|
nkeynes@770 | 80 | static void controller_attach( maple_device_t dev );
|
nkeynes@770 | 81 | static void controller_detach( maple_device_t dev );
|
nkeynes@1072 | 82 | static void controller_key_callback( void *mdev, uint32_t value, uint32_t pressure, gboolean isKeyDown );
|
nkeynes@770 | 83 | static maple_device_t controller_clone( maple_device_t dev );
|
nkeynes@770 | 84 | static maple_device_t controller_new();
|
nkeynes@1072 | 85 | static lxdream_config_group_t controller_get_config( maple_device_t dev );
|
nkeynes@770 | 86 | static int controller_get_cond( maple_device_t dev, int function, unsigned char *outbuf,
|
nkeynes@502 | 87 | unsigned int *outlen );
|
nkeynes@2 | 88 |
|
nkeynes@2 | 89 | typedef struct controller_device {
|
nkeynes@2 | 90 | struct maple_device dev;
|
nkeynes@2 | 91 | uint32_t condition[2];
|
nkeynes@1072 | 92 | struct lxdream_config_group config;
|
nkeynes@2 | 93 | } *controller_device_t;
|
nkeynes@2 | 94 |
|
nkeynes@1034 | 95 | struct maple_device_class controller_class = { "Sega Controller",
|
nkeynes@1034 | 96 | MAPLE_TYPE_PRIMARY|MAPLE_GRAB_DONTCARE|MAPLE_SLOTS_2, controller_new };
|
nkeynes@2 | 97 |
|
nkeynes@144 | 98 | static struct controller_device base_controller = {
|
nkeynes@1034 | 99 | { MAPLE_DEVICE_TAG, &controller_class,
|
nkeynes@838 | 100 | CONTROLLER_IDENT, CONTROLLER_VERSION,
|
nkeynes@1072 | 101 | controller_get_config,
|
nkeynes@1072 | 102 | controller_attach, controller_detach, maple_default_destroy,
|
nkeynes@1034 | 103 | controller_clone, NULL, NULL, controller_get_cond, NULL, NULL, NULL, NULL, NULL, NULL },
|
nkeynes@1072 | 104 | {0x0000FFFF, 0x80808080},
|
nkeynes@1072 | 105 | {"Sega Controller", NULL, controller_key_callback, NULL,
|
nkeynes@1072 | 106 | {{ "dpad left", N_("Dpad left"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_LEFT },
|
nkeynes@1072 | 107 | { "dpad right", N_("Dpad right"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_RIGHT },
|
nkeynes@1072 | 108 | { "dpad up", N_("Dpad up"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_UP },
|
nkeynes@1072 | 109 | { "dpad down", N_("Dpad down"), CONFIG_TYPE_KEY, NULL, BUTTON_DPAD_DOWN },
|
nkeynes@1072 | 110 | { "analog left", N_("Analog left"), CONFIG_TYPE_KEY, NULL, JOY_LEFT },
|
nkeynes@1072 | 111 | { "analog right", N_("Analog right"), CONFIG_TYPE_KEY, NULL, JOY_RIGHT },
|
nkeynes@1072 | 112 | { "analog up", N_("Analog up"), CONFIG_TYPE_KEY, NULL, JOY_UP },
|
nkeynes@1072 | 113 | { "analog down", N_("Analog down"), CONFIG_TYPE_KEY, NULL, JOY_DOWN },
|
nkeynes@1072 | 114 | { "button X", N_("Button X"), CONFIG_TYPE_KEY, NULL, BUTTON_X },
|
nkeynes@1072 | 115 | { "button Y", N_("Button Y"), CONFIG_TYPE_KEY, NULL, BUTTON_Y },
|
nkeynes@1072 | 116 | { "button A", N_("Button A"), CONFIG_TYPE_KEY, NULL, BUTTON_A },
|
nkeynes@1072 | 117 | { "button B", N_("Button B"), CONFIG_TYPE_KEY, NULL, BUTTON_B },
|
nkeynes@1072 | 118 | { "trigger left", N_("Trigger left"), CONFIG_TYPE_KEY, NULL, BUTTON_LEFT_TRIGGER },
|
nkeynes@1072 | 119 | { "trigger right", N_("Trigger right"), CONFIG_TYPE_KEY, NULL, BUTTON_RIGHT_TRIGGER },
|
nkeynes@1072 | 120 | { "start", N_("Start button"), CONFIG_TYPE_KEY, NULL, BUTTON_START },
|
nkeynes@1072 | 121 | { NULL, CONFIG_TYPE_NONE }}} };
|
nkeynes@1072 | 122 |
|
nkeynes@1072 | 123 | /* Get the controller_device * from a lxdream_config_group_t */
|
nkeynes@1072 | 124 | #define DEV_FROM_CONFIG_GROUP(grp) ((controller_device_t)(((char *)grp) - offsetof( struct controller_device, config )))
|
nkeynes@144 | 125 |
|
nkeynes@770 | 126 | static int config_button_map[] = {
|
nkeynes@770 | 127 | BUTTON_DPAD_LEFT, BUTTON_DPAD_RIGHT, BUTTON_DPAD_UP, BUTTON_DPAD_DOWN,
|
nkeynes@770 | 128 | JOY_LEFT, JOY_RIGHT, JOY_UP, JOY_DOWN, BUTTON_X, BUTTON_Y, BUTTON_A,
|
nkeynes@770 | 129 | BUTTON_B, BUTTON_LEFT_TRIGGER, BUTTON_RIGHT_TRIGGER, BUTTON_START };
|
nkeynes@770 | 130 |
|
nkeynes@144 | 131 | #define CONTROLLER(x) ((controller_device_t)(x))
|
nkeynes@2 | 132 |
|
nkeynes@770 | 133 | static maple_device_t controller_new( )
|
nkeynes@2 | 134 | {
|
nkeynes@1072 | 135 | controller_device_t dev = malloc( sizeof(base_controller) );
|
nkeynes@2 | 136 | memcpy( dev, &base_controller, sizeof(base_controller) );
|
nkeynes@1072 | 137 | dev->config.data = dev;
|
nkeynes@2 | 138 | return MAPLE_DEVICE(dev);
|
nkeynes@2 | 139 | }
|
nkeynes@2 | 140 |
|
nkeynes@770 | 141 | static maple_device_t controller_clone( maple_device_t srcdevice )
|
nkeynes@460 | 142 | {
|
nkeynes@460 | 143 | controller_device_t src = (controller_device_t)srcdevice;
|
nkeynes@460 | 144 | controller_device_t dev = (controller_device_t)controller_new();
|
nkeynes@1072 | 145 | lxdream_copy_config_group( &dev->config, &src->config );
|
nkeynes@460 | 146 | memcpy( dev->condition, src->condition, sizeof(src->condition) );
|
nkeynes@460 | 147 | return MAPLE_DEVICE(dev);
|
nkeynes@460 | 148 | }
|
nkeynes@460 | 149 |
|
nkeynes@144 | 150 | /**
|
nkeynes@144 | 151 | * Input callback
|
nkeynes@144 | 152 | */
|
nkeynes@770 | 153 | static void controller_key_callback( void *mdev, uint32_t value, uint32_t pressure, gboolean isKeyDown )
|
nkeynes@144 | 154 | {
|
nkeynes@144 | 155 | controller_device_t dev = (controller_device_t)mdev;
|
nkeynes@144 | 156 | if( isKeyDown ) {
|
nkeynes@736 | 157 | switch( value ) {
|
nkeynes@736 | 158 | case JOY_LEFT:
|
nkeynes@1010 | 159 | dev->condition[1] &= ~JOY_X_AXIS_MASK;
|
nkeynes@1010 | 160 | dev->condition[1] |= JOY_X_AXIS(0x7F - pressure);
|
nkeynes@736 | 161 | break;
|
nkeynes@736 | 162 | case JOY_RIGHT:
|
nkeynes@1010 | 163 | dev->condition[1] &= ~JOY_X_AXIS_MASK;
|
nkeynes@1010 | 164 | dev->condition[1] |= JOY_X_AXIS(0x80 + pressure);
|
nkeynes@736 | 165 | break;
|
nkeynes@736 | 166 | case JOY_UP:
|
nkeynes@1010 | 167 | dev->condition[1] &= ~JOY_Y_AXIS_MASK;
|
nkeynes@1010 | 168 | dev->condition[1] |= JOY_Y_AXIS(0x7F - pressure);
|
nkeynes@736 | 169 | break;
|
nkeynes@736 | 170 | case JOY_DOWN:
|
nkeynes@1010 | 171 | dev->condition[1] &= ~JOY_Y_AXIS_MASK;
|
nkeynes@1010 | 172 | dev->condition[1] |= JOY_Y_AXIS(0x80 + pressure);
|
nkeynes@736 | 173 | break;
|
nkeynes@736 | 174 | case BUTTON_LEFT_TRIGGER:
|
nkeynes@736 | 175 | case BUTTON_RIGHT_TRIGGER:
|
nkeynes@736 | 176 | dev->condition[0] |= value;
|
nkeynes@736 | 177 | break;
|
nkeynes@736 | 178 | default:
|
nkeynes@736 | 179 | dev->condition[0] &= ~value;
|
nkeynes@736 | 180 | }
|
nkeynes@144 | 181 | } else {
|
nkeynes@736 | 182 | switch(value ) {
|
nkeynes@736 | 183 | case JOY_LEFT:
|
nkeynes@736 | 184 | case JOY_RIGHT:
|
nkeynes@1010 | 185 | dev->condition[1] = (dev->condition[1] & ~JOY_X_AXIS_MASK)| JOY_X_AXIS_CENTER;
|
nkeynes@736 | 186 | break;
|
nkeynes@736 | 187 | case JOY_UP:
|
nkeynes@736 | 188 | case JOY_DOWN:
|
nkeynes@1010 | 189 | dev->condition[1] = (dev->condition[1] & ~JOY_Y_AXIS_MASK)| JOY_Y_AXIS_CENTER;
|
nkeynes@736 | 190 | break;
|
nkeynes@736 | 191 | case BUTTON_LEFT_TRIGGER:
|
nkeynes@736 | 192 | case BUTTON_RIGHT_TRIGGER:
|
nkeynes@736 | 193 | dev->condition[0] &= ~value;
|
nkeynes@736 | 194 | break;
|
nkeynes@736 | 195 | default:
|
nkeynes@736 | 196 | dev->condition[0] |= value;
|
nkeynes@736 | 197 | }
|
nkeynes@144 | 198 | }
|
nkeynes@144 | 199 | }
|
nkeynes@2 | 200 |
|
nkeynes@1072 | 201 | static lxdream_config_group_t controller_get_config( maple_device_t mdev )
|
nkeynes@2 | 202 | {
|
nkeynes@144 | 203 | controller_device_t dev = (controller_device_t)mdev;
|
nkeynes@1072 | 204 | return &dev->config;
|
nkeynes@144 | 205 | }
|
nkeynes@144 | 206 |
|
nkeynes@144 | 207 | /**
|
nkeynes@144 | 208 | * Device is being attached to the bus. Go through the config and reserve the
|
nkeynes@144 | 209 | * keys we need.
|
nkeynes@144 | 210 | */
|
nkeynes@770 | 211 | static void controller_attach( maple_device_t mdev )
|
nkeynes@144 | 212 | {
|
nkeynes@144 | 213 | controller_device_t dev = (controller_device_t)mdev;
|
nkeynes@1072 | 214 | dev->config.on_change = input_keygroup_changed;
|
nkeynes@1072 | 215 | input_register_keygroup( &dev->config );
|
nkeynes@2 | 216 | }
|
nkeynes@2 | 217 |
|
nkeynes@770 | 218 | static void controller_detach( maple_device_t mdev )
|
nkeynes@2 | 219 | {
|
nkeynes@451 | 220 | controller_device_t dev = (controller_device_t)mdev;
|
nkeynes@1072 | 221 | input_unregister_keygroup( &dev->config );
|
nkeynes@1072 | 222 | dev->config.on_change = NULL;
|
nkeynes@2 | 223 | }
|
nkeynes@2 | 224 |
|
nkeynes@2 | 225 |
|
nkeynes@770 | 226 | static int controller_get_cond( maple_device_t mdev, int function, unsigned char *outbuf,
|
nkeynes@502 | 227 | unsigned int *outlen )
|
nkeynes@2 | 228 | {
|
nkeynes@2 | 229 | controller_device_t dev = (controller_device_t)mdev;
|
nkeynes@2 | 230 | if( function == MAPLE_FUNC_CONTROLLER ) {
|
nkeynes@2 | 231 | *outlen = 2;
|
nkeynes@2 | 232 | memcpy( outbuf, dev->condition, 8 );
|
nkeynes@2 | 233 | return 0;
|
nkeynes@2 | 234 | } else {
|
nkeynes@2 | 235 | return MAPLE_ERR_FUNC_UNSUP;
|
nkeynes@2 | 236 | }
|
nkeynes@2 | 237 | }
|
nkeynes@2 | 238 |
|