nkeynes@31: /** nkeynes@561: * $Id$ nkeynes@31: * nkeynes@31: * Implements the standard dreamcast controller nkeynes@848: * Part No. HKT-7700 nkeynes@31: * nkeynes@31: * Copyright (c) 2005 Nathan Keynes. nkeynes@31: * nkeynes@31: * This program is free software; you can redistribute it and/or modify nkeynes@31: * it under the terms of the GNU General Public License as published by nkeynes@31: * the Free Software Foundation; either version 2 of the License, or nkeynes@31: * (at your option) any later version. nkeynes@31: * nkeynes@31: * This program is distributed in the hope that it will be useful, nkeynes@31: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@31: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@31: * GNU General Public License for more details. nkeynes@31: */ nkeynes@31: nkeynes@2: #include nkeynes@770: #include nkeynes@2: #include "dream.h" nkeynes@144: #include "dreamcast.h" nkeynes@429: #include "display.h" nkeynes@2: #include "maple.h" nkeynes@846: nkeynes@846: /* First word of controller condition */ nkeynes@846: #define BUTTON_C 0x00000001 /* not on standard controller */ nkeynes@846: #define BUTTON_B 0x00000002 nkeynes@846: #define BUTTON_A 0x00000004 nkeynes@846: #define BUTTON_START 0x00000008 nkeynes@846: #define BUTTON_DPAD_UP 0x00000010 nkeynes@846: #define BUTTON_DPAD_DOWN 0x00000020 nkeynes@846: #define BUTTON_DPAD_LEFT 0x00000040 nkeynes@846: #define BUTTON_DPAD_RIGHT 0x00000080 nkeynes@846: #define BUTTON_Z 0x00000100 /* not on standard controller */ nkeynes@846: #define BUTTON_Y 0x00000200 nkeynes@846: #define BUTTON_X 0x00000400 nkeynes@846: #define BUTTON_D 0x00000800 /* not on standard controller */ nkeynes@846: #define BUTTON_LEFT_TRIGGER 0xFF000000 /* Bitmask */ nkeynes@846: #define BUTTON_RIGHT_TRIGGER 0x00FF0000 /* Bitmask */ nkeynes@846: nkeynes@846: /* Second word of controller condition (bitmasks) */ nkeynes@846: #define JOY_X_AXIS 0x000000FF nkeynes@846: #define JOY_Y_AXIS 0x0000FF00 nkeynes@846: #define JOY_X_AXIS_CENTER 0x00000080 nkeynes@846: #define JOY_Y_AXIS_CENTER 0x00008000 nkeynes@846: #define JOY2_X_AXIS 0x00FF0000 /* not on standard controller */ nkeynes@846: #define JOY2_Y_AXIS 0xFF000000 /* not on standard controller */ nkeynes@846: nkeynes@846: /* The following bits are used by the emulator for flags but don't actually nkeynes@846: * appear in the hardware nkeynes@846: */ nkeynes@846: #define JOY_LEFT 0x80000001 nkeynes@846: #define JOY_RIGHT 0x80000002 nkeynes@846: #define JOY_UP 0x80000004 nkeynes@846: #define JOY_DOWN 0x80000008 nkeynes@846: nkeynes@846: /* Standard controller ID */ nkeynes@846: #define CONTROLLER_IDENT {0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, \ nkeynes@846: 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x63, 0x61, 0x73, 0x74, 0x20, \ nkeynes@846: 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \ nkeynes@846: 0x20, 0x20, 0x20, 0x20, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x42, 0x79, 0x20, \ nkeynes@846: 0x6f, 0x72, 0x20, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, \ nkeynes@846: 0x20, 0x46, 0x72, 0x6f, 0x6d, 0x20, 0x53, 0x45, 0x47, 0x41, 0x20, 0x45, 0x4e, 0x54, 0x45, 0x52, \ nkeynes@846: 0x50, 0x52, 0x49, 0x53, 0x45, 0x53, 0x2c, 0x4c, 0x54, 0x44, 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, \ nkeynes@846: 0xae, 0x01, 0xf4, 0x01} nkeynes@846: #define CONTROLLER_VERSION {0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x2e, 0x30, 0x31, \ nkeynes@846: 0x30, 0x2c, 0x31, 0x39, 0x39, 0x38, 0x2f, 0x30, 0x39, 0x2f, 0x32, 0x38, 0x2c, 0x33, 0x31, 0x35, \ nkeynes@846: 0x2d, 0x36, 0x32, 0x31, 0x31, 0x2d, 0x41, 0x42, 0x20, 0x20, 0x20, 0x2c, 0x41, 0x6e, 0x61, 0x6c, \ nkeynes@846: 0x6f, 0x67, 0x20, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x3a, 0x20, 0x54, 0x68, 0x65, 0x20, \ nkeynes@846: 0x34, 0x74, 0x68, 0x20, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x35, 0x2f, 0x38, 0x20, \ nkeynes@846: 0x20, 0x2b, 0x44, 0x46 } nkeynes@2: nkeynes@770: #define CONTROLLER_CONFIG_ENTRIES 15 nkeynes@144: nkeynes@770: static void controller_attach( maple_device_t dev ); nkeynes@770: static void controller_detach( maple_device_t dev ); nkeynes@770: static void controller_destroy( maple_device_t dev ); nkeynes@770: static maple_device_t controller_clone( maple_device_t dev ); nkeynes@770: static maple_device_t controller_new(); nkeynes@770: static lxdream_config_entry_t controller_get_config( maple_device_t dev ); nkeynes@770: static void controller_set_config_value( maple_device_t dev, unsigned int key, const gchar *value ); nkeynes@770: static int controller_get_cond( maple_device_t dev, int function, unsigned char *outbuf, nkeynes@502: unsigned int *outlen ); nkeynes@2: nkeynes@2: typedef struct controller_device { nkeynes@2: struct maple_device dev; nkeynes@2: uint32_t condition[2]; nkeynes@770: struct lxdream_config_entry config[CONTROLLER_CONFIG_ENTRIES+1]; nkeynes@2: } *controller_device_t; nkeynes@2: nkeynes@144: struct maple_device_class controller_class = { "Sega Controller", controller_new }; nkeynes@2: nkeynes@144: static struct controller_device base_controller = { nkeynes@838: { MAPLE_DEVICE_TAG, &controller_class, MAPLE_GRAB_DONTCARE, nkeynes@838: CONTROLLER_IDENT, CONTROLLER_VERSION, nkeynes@770: controller_get_config, controller_set_config_value, nkeynes@770: controller_attach, controller_detach, controller_destroy, nkeynes@850: controller_clone, NULL, NULL, controller_get_cond, NULL, NULL, NULL, NULL, NULL }, nkeynes@736: {0x0000FFFF, 0x80808080}, nkeynes@736: {{ "dpad left", N_("Dpad left"), CONFIG_TYPE_KEY }, nkeynes@736: { "dpad right", N_("Dpad right"), CONFIG_TYPE_KEY }, nkeynes@736: { "dpad up", N_("Dpad up"), CONFIG_TYPE_KEY }, nkeynes@736: { "dpad down", N_("Dpad down"), CONFIG_TYPE_KEY }, nkeynes@736: { "analog left", N_("Analog left"), CONFIG_TYPE_KEY }, nkeynes@736: { "analog right", N_("Analog right"), CONFIG_TYPE_KEY }, nkeynes@736: { "analog up", N_("Analog up"), CONFIG_TYPE_KEY }, nkeynes@736: { "analog down", N_("Analog down"), CONFIG_TYPE_KEY }, nkeynes@736: { "button X", N_("Button X"), CONFIG_TYPE_KEY }, nkeynes@736: { "button Y", N_("Button Y"), CONFIG_TYPE_KEY }, nkeynes@736: { "button A", N_("Button A"), CONFIG_TYPE_KEY }, nkeynes@736: { "button B", N_("Button B"), CONFIG_TYPE_KEY }, nkeynes@736: { "trigger left", N_("Trigger left"), CONFIG_TYPE_KEY }, nkeynes@736: { "trigger right", N_("Trigger right"), CONFIG_TYPE_KEY }, nkeynes@736: { "start", N_("Start button"), CONFIG_TYPE_KEY }, nkeynes@736: { NULL, CONFIG_TYPE_NONE }} }; nkeynes@144: nkeynes@770: static int config_button_map[] = { nkeynes@770: BUTTON_DPAD_LEFT, BUTTON_DPAD_RIGHT, BUTTON_DPAD_UP, BUTTON_DPAD_DOWN, nkeynes@770: JOY_LEFT, JOY_RIGHT, JOY_UP, JOY_DOWN, BUTTON_X, BUTTON_Y, BUTTON_A, nkeynes@770: BUTTON_B, BUTTON_LEFT_TRIGGER, BUTTON_RIGHT_TRIGGER, BUTTON_START }; nkeynes@770: nkeynes@144: #define CONTROLLER(x) ((controller_device_t)(x)) nkeynes@2: nkeynes@770: static maple_device_t controller_new( ) nkeynes@2: { nkeynes@2: controller_device_t dev = malloc( sizeof(struct controller_device) ); nkeynes@2: memcpy( dev, &base_controller, sizeof(base_controller) ); nkeynes@2: return MAPLE_DEVICE(dev); nkeynes@2: } nkeynes@2: nkeynes@770: static maple_device_t controller_clone( maple_device_t srcdevice ) nkeynes@460: { nkeynes@460: controller_device_t src = (controller_device_t)srcdevice; nkeynes@460: controller_device_t dev = (controller_device_t)controller_new(); nkeynes@460: lxdream_copy_config_list( dev->config, src->config ); nkeynes@460: memcpy( dev->condition, src->condition, sizeof(src->condition) ); nkeynes@460: return MAPLE_DEVICE(dev); nkeynes@460: } nkeynes@460: nkeynes@144: /** nkeynes@144: * Input callback nkeynes@144: */ nkeynes@770: static void controller_key_callback( void *mdev, uint32_t value, uint32_t pressure, gboolean isKeyDown ) nkeynes@144: { nkeynes@144: controller_device_t dev = (controller_device_t)mdev; nkeynes@144: if( isKeyDown ) { nkeynes@736: switch( value ) { nkeynes@736: case JOY_LEFT: nkeynes@736: dev->condition[1] &= ~JOY_X_AXIS; nkeynes@736: break; nkeynes@736: case JOY_RIGHT: nkeynes@736: dev->condition[1] |= JOY_X_AXIS; nkeynes@736: break; nkeynes@736: case JOY_UP: nkeynes@736: dev->condition[1] &= ~JOY_Y_AXIS; nkeynes@736: break; nkeynes@736: case JOY_DOWN: nkeynes@736: dev->condition[1] |= JOY_Y_AXIS; nkeynes@736: break; nkeynes@736: case BUTTON_LEFT_TRIGGER: nkeynes@736: case BUTTON_RIGHT_TRIGGER: nkeynes@736: dev->condition[0] |= value; nkeynes@736: break; nkeynes@736: default: nkeynes@736: dev->condition[0] &= ~value; nkeynes@736: } nkeynes@144: } else { nkeynes@736: switch(value ) { nkeynes@736: case JOY_LEFT: nkeynes@736: case JOY_RIGHT: nkeynes@736: dev->condition[1] = (dev->condition[1] & ~JOY_X_AXIS)| JOY_X_AXIS_CENTER; nkeynes@736: break; nkeynes@736: case JOY_UP: nkeynes@736: case JOY_DOWN: nkeynes@736: dev->condition[1] = (dev->condition[1] & ~JOY_Y_AXIS)| JOY_Y_AXIS_CENTER; nkeynes@736: break; nkeynes@736: case BUTTON_LEFT_TRIGGER: nkeynes@736: case BUTTON_RIGHT_TRIGGER: nkeynes@736: dev->condition[0] &= ~value; nkeynes@736: break; nkeynes@736: default: nkeynes@736: dev->condition[0] |= value; nkeynes@736: } nkeynes@144: } nkeynes@144: } nkeynes@2: nkeynes@770: static lxdream_config_entry_t controller_get_config( maple_device_t mdev ) nkeynes@2: { nkeynes@144: controller_device_t dev = (controller_device_t)mdev; nkeynes@144: return dev->config; nkeynes@144: } nkeynes@2: nkeynes@770: static void controller_set_config_value( maple_device_t mdev, unsigned int key, const gchar *value ) nkeynes@770: { nkeynes@770: controller_device_t dev = (controller_device_t)mdev; nkeynes@770: assert( key < CONTROLLER_CONFIG_ENTRIES ); nkeynes@770: nkeynes@770: input_unregister_key( dev->config[key].value, controller_key_callback, dev, config_button_map[key] ); nkeynes@770: lxdream_set_config_value( &dev->config[key], value ); nkeynes@770: input_register_key( dev->config[key].value, controller_key_callback, dev, config_button_map[key] ); nkeynes@770: } nkeynes@770: nkeynes@770: static void controller_destroy( maple_device_t mdev ) nkeynes@144: { nkeynes@144: free( mdev ); nkeynes@144: } nkeynes@144: nkeynes@144: /** nkeynes@144: * Device is being attached to the bus. Go through the config and reserve the nkeynes@144: * keys we need. nkeynes@144: */ nkeynes@770: static void controller_attach( maple_device_t mdev ) nkeynes@144: { nkeynes@144: controller_device_t dev = (controller_device_t)mdev; nkeynes@770: int i; nkeynes@770: for( i=0; iconfig[i].value, controller_key_callback, dev, config_button_map[i] ); nkeynes@770: } nkeynes@2: } nkeynes@2: nkeynes@770: static void controller_detach( maple_device_t mdev ) nkeynes@2: { nkeynes@451: controller_device_t dev = (controller_device_t)mdev; nkeynes@770: int i; nkeynes@770: for( i=0; iconfig[i].value, controller_key_callback, dev, config_button_map[i] ); nkeynes@770: } nkeynes@2: nkeynes@2: } nkeynes@2: nkeynes@2: nkeynes@770: static int controller_get_cond( maple_device_t mdev, int function, unsigned char *outbuf, nkeynes@502: unsigned int *outlen ) nkeynes@2: { nkeynes@2: controller_device_t dev = (controller_device_t)mdev; nkeynes@2: if( function == MAPLE_FUNC_CONTROLLER ) { nkeynes@2: *outlen = 2; nkeynes@2: memcpy( outbuf, dev->condition, 8 ); nkeynes@2: return 0; nkeynes@2: } else { nkeynes@2: return MAPLE_ERR_FUNC_UNSUP; nkeynes@2: } nkeynes@2: } nkeynes@2: