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