1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2012 Sam Lantinga
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19    Sam Lantinga
20    slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_JOYSTICK_DC
25
26#include "SDL_events.h"
27#include "SDL_joystick.h"
28#include "../SDL_sysjoystick.h"
29#include "../SDL_joystick_c.h"
30
31#include <dc/maple.h>
32#include <dc/maple/controller.h>
33
34#define MAX_JOYSTICKS	8	/* only 2 are supported in the multimedia API */
35#define MAX_AXES	6	/* each joystick can have up to 6 axes */
36#define MAX_BUTTONS	8	/* and 8 buttons                      */
37#define	MAX_HATS	2
38
39#define	JOYNAMELEN	8
40
41/* array to hold joystick ID values */
42static uint8	SYS_Joystick_addr[MAX_JOYSTICKS];
43
44/* The private structure used to keep track of a joystick */
45struct joystick_hwdata
46{
47	cont_cond_t prev_cond;
48	int prev_buttons;
49};
50
51/* Function to scan the system for joysticks.
52 * This function should set SDL_numjoysticks to the number of available
53 * joysticks.  Joystick 0 should be the system default joystick.
54 * It should return 0, or -1 on an unrecoverable fatal error.
55 */
56int SDL_SYS_JoystickInit(void)
57{
58	int numdevs;
59
60	int p,u;
61
62	numdevs = 0;
63	for(p=0;p<MAPLE_PORT_COUNT;p++) {
64		for(u=0;u<MAPLE_UNIT_COUNT;u++) {
65			if (maple_device_func(p,u)&MAPLE_FUNC_CONTROLLER) {
66				SYS_Joystick_addr[numdevs] = maple_addr(p,u);
67				numdevs++;
68			}
69		}
70	}
71
72	return(numdevs);
73}
74
75/* Function to get the device-dependent name of a joystick */
76const char *SDL_SYS_JoystickName(int index)
77{
78	maple_device_t *dev;
79	if (maple_compat_resolve(SYS_Joystick_addr[index],&dev,MAPLE_FUNC_CONTROLLER)!=0) return NULL;
80	return dev->info.product_name;
81}
82
83/* Function to open a joystick for use.
84   The joystick to open is specified by the index field of the joystick.
85   This should fill the nbuttons and naxes fields of the joystick structure.
86   It returns 0, or -1 if there is an error.
87 */
88int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
89{
90	/* allocate memory for system specific hardware data */
91	joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata));
92	if (joystick->hwdata == NULL)
93	{
94		SDL_OutOfMemory();
95		return(-1);
96	}
97	SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
98
99	/* fill nbuttons, naxes, and nhats fields */
100	joystick->nbuttons = MAX_BUTTONS;
101	joystick->naxes = MAX_AXES;
102	joystick->nhats = MAX_HATS;
103	return(0);
104}
105
106
107/* Function to update the state of a joystick - called as a device poll.
108 * This function shouldn't update the joystick structure directly,
109 * but instead should call SDL_PrivateJoystick*() to deliver events
110 * and update joystick device state.
111 */
112
113void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
114{
115const	int sdl_buttons[] = {
116	CONT_C,
117	CONT_B,
118	CONT_A,
119	CONT_START,
120	CONT_Z,
121	CONT_Y,
122	CONT_X,
123	CONT_D
124};
125
126	uint8 addr;
127	cont_cond_t cond,*prev_cond;
128	int buttons,prev_buttons,i,changed;
129
130	addr = SYS_Joystick_addr[joystick->index];
131	if (cont_get_cond(addr,&cond)<0) return;
132
133	buttons = cond.buttons;
134	prev_buttons = joystick->hwdata->prev_buttons;
135	changed = buttons^prev_buttons;
136
137	if ((changed)&(CONT_DPAD_UP|CONT_DPAD_DOWN|CONT_DPAD_LEFT|CONT_DPAD_RIGHT)) {
138		int hat = SDL_HAT_CENTERED;
139		if (buttons&CONT_DPAD_UP) hat|=SDL_HAT_UP;
140		if (buttons&CONT_DPAD_DOWN) hat|=SDL_HAT_DOWN;
141		if (buttons&CONT_DPAD_LEFT) hat|=SDL_HAT_LEFT;
142		if (buttons&CONT_DPAD_RIGHT) hat|=SDL_HAT_RIGHT;
143		SDL_PrivateJoystickHat(joystick, 0, hat);
144	}
145	if ((changed)&(CONT_DPAD2_UP|CONT_DPAD2_DOWN|CONT_DPAD2_LEFT|CONT_DPAD2_RIGHT)) {
146		int hat = SDL_HAT_CENTERED;
147		if (buttons&CONT_DPAD2_UP) hat|=SDL_HAT_UP;
148		if (buttons&CONT_DPAD2_DOWN) hat|=SDL_HAT_DOWN;
149		if (buttons&CONT_DPAD2_LEFT) hat|=SDL_HAT_LEFT;
150		if (buttons&CONT_DPAD2_RIGHT) hat|=SDL_HAT_RIGHT;
151		SDL_PrivateJoystickHat(joystick, 1, hat);
152	}
153
154	for(i=0;i<sizeof(sdl_buttons)/sizeof(sdl_buttons[0]);i++) {
155		if (changed & sdl_buttons[i]) {
156			SDL_PrivateJoystickButton(joystick, i, (buttons & sdl_buttons[i])?SDL_PRESSED:SDL_RELEASED);
157		}
158	}
159
160	prev_cond = &joystick->hwdata->prev_cond;
161	if (cond.joyx!=prev_cond->joyx)
162		SDL_PrivateJoystickAxis(joystick, 0, cond.joyx-128);
163	if (cond.joyy!=prev_cond->joyy)
164		SDL_PrivateJoystickAxis(joystick, 1, cond.joyy-128);
165	if (cond.rtrig!=prev_cond->rtrig)
166		SDL_PrivateJoystickAxis(joystick, 2, cond.rtrig);
167	if (cond.ltrig!=prev_cond->ltrig)
168		SDL_PrivateJoystickAxis(joystick, 3, cond.ltrig);
169	if (cond.joy2x!=prev_cond->joy2x)
170		SDL_PrivateJoystickAxis(joystick, 4, cond.joy2x-128);
171	if (cond.joy2y!=prev_cond->joy2y)
172		SDL_PrivateJoystickAxis(joystick, 5, cond.joy2y-128);
173
174	joystick->hwdata->prev_buttons = buttons;
175	joystick->hwdata->prev_cond = cond;
176}
177
178/* Function to close a joystick after use */
179void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
180{
181	if (joystick->hwdata != NULL) {
182		/* free system specific hardware data */
183		SDL_free(joystick->hwdata);
184	}
185}
186
187/* Function to perform any system-specific joystick related cleanup */
188void SDL_SYS_JoystickQuit(void)
189{
190	return;
191}
192
193#endif /* SDL_JOYSTICK_DC */
194