snes mouse support
[drnoksnes] / platform / sdli.cpp
1 #include <SDL.h>
2 #include <math.h>
3
4 #include "platform.h"
5 #include "snes9x.h"
6 #include "display.h"
7
8 struct TouchButton {
9         unsigned short mask;
10         unsigned short x, y;
11         unsigned short x2, y2;
12         float fx, fy;
13         float fw, fh;
14 };
15
16 #define TOUCH_BUTTON_INITIALIZER(name, x, y, w, h) \
17         {SNES_##name##_MASK, 0, 0, 0, 0, x, y, w, h}
18
19 static TouchButton touchbuttons[] = {
20         TOUCH_BUTTON_INITIALIZER(TL, 0, 0, 0.375, 0.0833),
21         TOUCH_BUTTON_INITIALIZER(TR, 0.625, 0, 0.375, 0.0833),
22         TOUCH_BUTTON_INITIALIZER(UP, 0.125, 0.0833, 0.125, 0.2777), //2
23         TOUCH_BUTTON_INITIALIZER(LEFT, 0.0, 0.3611, 0.125, 0.2777), //3
24         TOUCH_BUTTON_INITIALIZER(RIGHT, 0.25, 0.3611, 0.125, 0.2777), //4
25         TOUCH_BUTTON_INITIALIZER(DOWN, 0.125, 0.6388, 0.125, 0.2777), //5
26         TOUCH_BUTTON_INITIALIZER(START, 0, 0.9166, 0.375, 0.0833),
27         TOUCH_BUTTON_INITIALIZER(Y, 0.75, 0.0833, 0.125, 0.2777),
28         TOUCH_BUTTON_INITIALIZER(X, 0.625, 0.3611, 0.125, 0.2777),
29         TOUCH_BUTTON_INITIALIZER(A, 0.875, 0.3611, 0.125, 0.2777),
30         TOUCH_BUTTON_INITIALIZER(B, 0.75, 0.6388, 0.125, 0.2777),
31         TOUCH_BUTTON_INITIALIZER(SELECT, 0.625, 0.9166, 0.375, 0.0833),
32 };
33
34 static TouchButton* current = 0;
35
36 static uint32 joypads[2];
37 static struct {
38         unsigned x;
39         unsigned y;
40         bool enabled, pressed;
41 } mouse;
42
43 static TouchButton* getButtonFor(unsigned int x, unsigned int y) {
44         unsigned int i;
45
46         for (i = 0; i < sizeof(touchbuttons)/sizeof(TouchButton); i++) {
47                 if (x > touchbuttons[i].x && x < touchbuttons[i].x2 &&
48                         y > touchbuttons[i].y && y < touchbuttons[i].y2) {
49
50                         return &touchbuttons[i];
51                 }
52         }
53
54         return 0;
55 }
56
57 static inline void unpress(TouchButton* b) {
58         joypads[0] &= ~b->mask;
59 }
60 static inline void press(TouchButton* b) {
61         joypads[0] |= b->mask;
62 }
63
64 static void processMouse(unsigned int x, unsigned int y, int pressed = 0)
65 {
66         if (Config.touchscreenInput) {
67                 if (pressed < 0) {
68                         // Button up.
69                         if (current) {
70                                 // Leaving button
71                                 unpress(current);
72                                 current = 0;
73                         }
74                 } else {
75                         // Button down, or mouse motion.
76                         TouchButton* b = getButtonFor(x, y);
77                         if (current && b && current != b) {
78                                 // Moving from button to button
79                                 unpress(current);
80                                 current = b;
81                                 press(current);
82                         } else if (current && !b) {
83                                 // Leaving button
84                                 unpress(current);
85                                 current = 0;
86                         } else if (!current && b) {
87                                 // Entering button
88                                 current = b;
89                                 press(current);
90                         }
91                 }
92         } else if (mouse.enabled) {
93                 mouse.x = x;
94                 mouse.y = y;
95
96                 if (mouse.x < GUI.RenderX) mouse.x = 0;
97                 else {
98                         mouse.x -= GUI.RenderX;
99                         if (mouse.x > GUI.RenderW) mouse.x = GUI.RenderW;
100                 }
101
102                 if (mouse.y < GUI.RenderY) mouse.y = 0;
103                 else {
104                         mouse.y -= GUI.RenderY;
105                         if (mouse.y > GUI.RenderH) mouse.y = GUI.RenderH;
106                 }
107
108 #ifdef MAEMO
109                 // Remember RenderH, RenderW is 2x if using Xsp.
110                 if (Config.xsp) {
111                         mouse.x /= 2;
112                         mouse.y /= 2;
113                 }
114 #endif
115
116                 if (pressed > 0)
117                         mouse.pressed = true;
118                 else if (pressed < 0)
119                         mouse.pressed = false;
120         }
121 }
122
123 static void processEvent(const SDL_Event& event)
124 {
125         switch (event.type) 
126         {
127         case SDL_KEYDOWN:
128                 if (Config.action[event.key.keysym.scancode]) 
129                         S9xDoAction(Config.action[event.key.keysym.scancode]);
130                 joypads[0] |= Config.joypad1Mapping[event.key.keysym.scancode];
131                 break;
132         case SDL_KEYUP:
133                 joypads[0] &= ~Config.joypad1Mapping[event.key.keysym.scancode];
134                 break;
135         case SDL_MOUSEBUTTONUP:
136         case SDL_MOUSEBUTTONDOWN:
137                 processMouse(event.button.x, event.button.y,
138                                 (event.button.state == SDL_PRESSED) ? 1 : - 1);
139                 break;
140         case SDL_MOUSEMOTION:
141                 processMouse(event.motion.x, event.motion.y);
142                 break;
143         case SDL_QUIT:
144                 Config.quitting = true;
145                 break;
146         }
147 }
148
149 uint32 S9xReadJoypad (int which)
150 {
151         if (which < 0 || which > 2) {
152                 return 0;
153         }
154
155         return joypads[which];
156 }
157
158 bool8 S9xReadMousePosition(int which1, int& x, int& y, uint32& buttons)
159 {
160         if (which1 != 0) return FALSE;
161
162         x = mouse.x;
163         y = mouse.y;
164         buttons = mouse.pressed ? 1 : 0;
165
166         return TRUE;
167 }
168
169 bool8 S9xReadSuperScopePosition(int& x, int& y, uint32& buttons)
170 {
171         x = mouse.x;
172         y = mouse.y;
173         buttons = mouse.pressed ? 8 : 0;
174
175         return TRUE;
176 }
177
178 void S9xProcessEvents(bool8_32 block)
179 {
180         SDL_Event event;
181
182         if (block) {
183                 SDL_WaitEvent(&event);
184                 processEvent(event);
185         } else {
186                 while(SDL_PollEvent(&event)) 
187                 {      
188                         processEvent(event);
189                 }
190         }
191 }
192
193 void S9xInitInputDevices()
194 {
195         joypads[0] = 0;
196         joypads[1] = 0;
197
198         switch (Settings.ControllerOption) {
199                 case SNES_JOYPAD:
200                         joypads[0] = 0x80000000UL;
201                         printf("Input: 1 joypad, keyboard only\n");
202                         break;
203                 case SNES_MOUSE:
204                         joypads[0] = 0x80000000UL;
205                         mouse.enabled = true;
206                         printf("Input: 1 joypad + mouse\n");
207                         break;
208                 case SNES_MOUSE_SWAPPED:
209                         printf("Input: mouse\n");
210                         mouse.enabled = true;
211                         break;
212                 case SNES_SUPERSCOPE:
213                         joypads[0] = 0x80000000UL;
214                         mouse.enabled = true;
215                         printf("Input: 1 joypad + superscope\n");
216                         break;
217                 default:
218                         printf("Input: unknown\n");
219                         break;
220         }
221
222         S9xInputScreenChanged();
223 }
224
225 void S9xDeinitInputDevices()
226 {
227
228 }
229
230 void S9xInputScreenChanged()
231 {
232         unsigned int i = 0;
233         const unsigned int w = GUI.Width, h = GUI.Height;
234         for (i = 0; i < sizeof(touchbuttons)/sizeof(TouchButton); i++) {
235                 touchbuttons[i].x = (unsigned)round(touchbuttons[i].fx * w);
236                 touchbuttons[i].y = (unsigned)round(touchbuttons[i].fy * h);
237                 touchbuttons[i].x2 = (unsigned)round(touchbuttons[i].x + touchbuttons[i].fw * w);
238                 touchbuttons[i].y2 = (unsigned)round(touchbuttons[i].y + touchbuttons[i].fh * h);
239         }
240 }
241