1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Joystick driver for the SNES controller.
12 *
13 * By Kerry High, based on sample code by Earle F. Philhower, III.
14 *
15 * Mucked about with until it works better by Paul Hampson.
16 *
17 * Lower CPU usage by Paul Hampson, based on the Linux implementation
18 * by Vojtech Pavlik.
19 *
20 * See readme.txt for copyright information.
21 */
22
23
24 #include "allegro.h"
25
26 #ifndef ALLEGRO_DOS
27 #error something is wrong with the makefile
28 #endif
29
30
31
32 #define LPT1_BASE 0x378
33 #define LPT2_BASE 0x278
34 #define LPT3_BASE 0x3bc
35 #define SNES_POWER 248
36 #define SNES_CLOCK 1
37 #define SNES_LATCH 2
38 #define SNES_BUTTONS 12 /* actually 16, but the last 4 aren't
39 * connected in a real SNESpad
40 */
41
42 /* driver functions */
43 static int sp_init(void);
44 static void sp_exit(void);
45 static int sp_poll(int);
46 static int sp1_poll(void);
47 static int sp2_poll(void);
48 static int sp3_poll(void);
49
50
51 JOYSTICK_DRIVER joystick_sp1 =
52 {
53 JOY_TYPE_SNESPAD_LPT1,
54 empty_string,
55 empty_string,
56 "SNESpad-LPT1",
57 sp_init,
58 sp_exit,
59 sp1_poll,
60 NULL, NULL,
61 NULL, NULL
62 };
63
64
65 JOYSTICK_DRIVER joystick_sp2 =
66 {
67 JOY_TYPE_SNESPAD_LPT2,
68 empty_string,
69 empty_string,
70 "SNESpad-LPT2",
71 sp_init,
72 sp_exit,
73 sp2_poll,
74 NULL, NULL,
75 NULL, NULL
76 };
77
78
79 JOYSTICK_DRIVER joystick_sp3 =
80 {
81 JOY_TYPE_SNESPAD_LPT3,
82 empty_string,
83 empty_string,
84 "SNESpad-LPT3",
85 sp_init,
86 sp_exit,
87 sp3_poll,
88 NULL, NULL,
89 NULL, NULL
90 };
91
92
93
94 /* sp_init:
95 * Initialises the driver.
96 */
sp_init(void)97 static int sp_init(void)
98 {
99 int i;
100
101 /* can't autodetect this... */
102 num_joysticks = 5;
103
104 for (i=0; i<num_joysticks; i++) {
105 joy[i].flags = JOYFLAG_DIGITAL;
106
107 joy[i].num_sticks = 1;
108 joy[i].stick[0].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED;
109 joy[i].stick[0].num_axis = 2;
110 joy[i].stick[0].axis[0].name = get_config_text("X");
111 joy[i].stick[0].axis[1].name = get_config_text("Y");
112 joy[i].stick[0].name = get_config_text("Pad");
113
114 joy[i].num_buttons = 8;
115
116 joy[i].button[0].name = get_config_text("B");
117 joy[i].button[1].name = get_config_text("Y");
118 joy[i].button[2].name = get_config_text("A");
119 joy[i].button[3].name = get_config_text("X");
120 joy[i].button[4].name = get_config_text("Select");
121 joy[i].button[5].name = get_config_text("Start");
122 joy[i].button[6].name = get_config_text("L");
123 joy[i].button[7].name = get_config_text("R");
124 }
125
126 return 0;
127 }
128
129
130
131 /* sp_exit:
132 * Shuts down the driver.
133 */
sp_exit(void)134 static void sp_exit(void)
135 {
136 }
137
138
139
140 /* sp_poll:
141 * Common - Updates the joystick status variables.
142 */
sp_poll(int base)143 static int sp_poll(int base)
144 {
145 static const int snes_in[] = {0x40, 0x20, 0x10, 0x08, 0x80};
146 int buttondata[SNES_BUTTONS];
147 int i, b;
148
149 /* read bits from all the SNESpads in parallel */
150 for (i = 0; i < SNES_BUTTONS; i++) {
151 outportb(base, SNES_POWER);
152
153 if (i == 0)
154 outportb(base, SNES_POWER + SNES_LATCH + SNES_CLOCK);
155 else
156 outportb(base, SNES_POWER + SNES_CLOCK);
157
158 outportb(base, SNES_POWER);
159
160 /* last LPT line (0x80) is inverted compared to the others */
161 buttondata[i] = (inportb(base + 1) ^ 0x80);
162 }
163
164 outportb(base, 0);
165
166 for (i=0; i<num_joysticks; i++) {
167
168 /* get b button */
169 joy[i].button[0].b = ((buttondata[0] & snes_in[i]) == 0);
170 /* get y button */
171 joy[i].button[1].b = ((buttondata[1] & snes_in[i]) == 0);
172 /* get select button */
173 joy[i].button[4].b = ((buttondata[2] & snes_in[i]) == 0);
174 /* get start button */
175 joy[i].button[5].b = ((buttondata[3] & snes_in[i]) == 0);
176
177 /* now, do the direction */
178 joy[i].stick[0].axis[1].d1 = ((buttondata[4] & snes_in[i]) == 0);
179 joy[i].stick[0].axis[1].d2 = ((buttondata[5] & snes_in[i]) == 0);
180 joy[i].stick[0].axis[0].d1 = ((buttondata[6] & snes_in[i]) == 0);
181 joy[i].stick[0].axis[0].d2 = ((buttondata[7] & snes_in[i]) == 0);
182
183 for (b=0; b<2; b++) {
184 if (joy[i].stick[0].axis[b].d1)
185 joy[i].stick[0].axis[b].pos = -128;
186 else if (joy[i].stick[0].axis[b].d2)
187 joy[i].stick[0].axis[b].pos = 128;
188 else
189 joy[i].stick[0].axis[b].pos = 0;
190 }
191
192 /* get a button */
193 joy[i].button[2].b = ((buttondata[8] & snes_in[i]) == 0);
194 /* get x button */
195 joy[i].button[3].b = ((buttondata[9] & snes_in[i]) == 0);
196 /* get l button */
197 joy[i].button[6].b = ((buttondata[10] & snes_in[i]) == 0);
198 /* get r button */
199 joy[i].button[7].b = ((buttondata[11] & snes_in[i]) == 0);
200
201 }
202
203 return 0;
204 }
205
206
207
208 /* sp1_poll:
209 * LPT1 - Updates the joystick status variables.
210 */
sp1_poll(void)211 static int sp1_poll(void)
212 {
213 return sp_poll(LPT1_BASE);
214 }
215
216
217
218 /* sp2_poll:
219 * LPT2 - Updates the joystick status variables.
220 */
sp2_poll(void)221 static int sp2_poll(void)
222 {
223 return sp_poll(LPT2_BASE);
224 }
225
226
227
228 /* sp3_poll:
229 * LPT3 - Updates the joystick status variables.
230 */
sp3_poll(void)231 static int sp3_poll(void)
232 {
233 return sp_poll(LPT3_BASE);
234 }
235