6 #include "sdlv.h" // Dispatching video-related events
12 #if !defined(SDL_MAXMOUSE)
13 #define SDL_MAXMOUSE 1
19 unsigned short x2, y2;
24 #define kCornerButtonWidth (0.375)
25 #define kCornerButtonHeight (0.0833333333334)
26 #define kBigButtonWidth (0.125)
27 #define kBigButtonHeight (0.2777777777778)
29 static TouchButton touchbuttons[] = {
30 #define TB(actions, x, y, w, h) \
31 {actions, 0, 0, 0, 0, x, y, w, h}
32 #define P(x) SNES_##x##_MASK
33 TB(P(TL), 0.0, 0.0, kCornerButtonWidth, kCornerButtonHeight),
34 TB(P(TR), 0.625, 0.0, kCornerButtonWidth, kCornerButtonHeight),
35 TB(P(LEFT) | P(UP), 0.0, kCornerButtonHeight, kBigButtonWidth, kBigButtonHeight),
36 TB(P(UP), kBigButtonWidth, kCornerButtonHeight, kBigButtonWidth, kBigButtonHeight),
37 TB(P(RIGHT) | P(UP), 2.0 * kBigButtonWidth, kCornerButtonHeight, kBigButtonWidth, kBigButtonHeight),
38 TB(P(LEFT), 0.0, kCornerButtonHeight + kBigButtonHeight, kBigButtonWidth, kBigButtonHeight),
39 TB(P(RIGHT), 2.0 * kBigButtonWidth, kCornerButtonHeight + kBigButtonHeight, kBigButtonWidth, kBigButtonHeight),
40 TB(P(LEFT) | P(DOWN), 0, 1.0 - (kCornerButtonHeight + kBigButtonHeight), kBigButtonWidth, kBigButtonHeight),
41 TB(P(DOWN), kBigButtonWidth, 1.0 - (kCornerButtonHeight + kBigButtonHeight), kBigButtonWidth, kBigButtonHeight),
42 TB(P(RIGHT) | P(DOWN), 2.0 * kBigButtonWidth, 1.0 - (kCornerButtonHeight + kBigButtonHeight), kBigButtonWidth, kBigButtonHeight),
43 TB(P(SELECT), 0.0, 1.0 - kCornerButtonHeight, kCornerButtonWidth, kCornerButtonHeight),
44 TB(P(X), 1.0 - 2.0 * kBigButtonWidth, kCornerButtonHeight, kBigButtonWidth, kBigButtonHeight),
45 TB(P(Y), 1.0 - 3.0 * kBigButtonWidth, kCornerButtonHeight + kBigButtonHeight, kBigButtonWidth, kBigButtonHeight),
46 TB(P(A), 1.0 - kBigButtonWidth, kCornerButtonHeight + kBigButtonHeight, kBigButtonWidth, kBigButtonHeight),
47 TB(P(B), 1.0 - 2.0 * kBigButtonWidth, 1.0 - (kCornerButtonHeight + kBigButtonHeight), kBigButtonWidth, kBigButtonHeight),
48 TB(P(START), 1.0 - kCornerButtonWidth, 1.0 - kCornerButtonHeight, kCornerButtonWidth, kCornerButtonHeight),
53 static TouchButton* current[SDL_MAXMOUSE] = { 0 };
55 static uint32 joypads[2];
59 bool enabled, pressed;
62 static TouchButton* getButtonFor(unsigned int x, unsigned int y) {
65 for (i = 0; i < sizeof(touchbuttons)/sizeof(TouchButton); i++) {
66 if (x >= touchbuttons[i].x && x < touchbuttons[i].x2 &&
67 y >= touchbuttons[i].y && y < touchbuttons[i].y2) {
69 return &touchbuttons[i];
76 static inline void unpress(TouchButton* b) {
77 joypads[Config.touchscreenInput - 1] &= ~b->mask;
79 static inline void press(TouchButton* b) {
80 joypads[Config.touchscreenInput - 1] |= b->mask;
83 static void processMouse(int which, unsigned int x, unsigned int y, int pressed = 0)
86 /* no fullscreen escape button, we have to simulate one! */
87 /* TODO: don't hardcode sizes */
88 if (Config.fullscreen && x > (800 - 100) && y < 50 && pressed > 0) {
89 S9xDoAction(kActionQuit);
92 if (Config.touchscreenInput) {
97 unpress(current[which]);
101 // Button down, or mouse motion.
102 TouchButton* b = getButtonFor(x, y);
103 if (current[which] && b && current[which] != b) {
104 // Moving from button to button
105 unpress(current[which]);
107 press(current[which]);
108 } else if (current[which] && !b) {
110 unpress(current[which]);
112 } else if (!current[which] && b) {
115 press(current[which]);
118 } else if (mouse.enabled) {
122 if (mouse.x < GUI.RenderX) mouse.x = 0;
124 mouse.x -= GUI.RenderX;
125 if (mouse.x > GUI.RenderW) mouse.x = GUI.RenderW;
128 if (mouse.y < GUI.RenderY) mouse.y = 0;
130 mouse.y -= GUI.RenderY;
131 if (mouse.y > GUI.RenderH) mouse.y = GUI.RenderH;
134 // mouse.{x,y} are system coordinates.
135 // Scale them to emulated screen coordinates.
136 mouse.x = static_cast<unsigned int>(mouse.x / GUI.ScaleX);
137 mouse.y = static_cast<unsigned int>(mouse.y / GUI.ScaleY);
140 mouse.pressed = true;
141 else if (pressed < 0)
142 mouse.pressed = false;
146 static void processEvent(const SDL_Event& event)
148 if (videoEventFilter(event)) return;
153 if (Config.action[event.key.keysym.scancode])
154 S9xDoAction(Config.action[event.key.keysym.scancode]);
155 joypads[0] |= Config.joypad1Mapping[event.key.keysym.scancode];
156 joypads[1] |= Config.joypad2Mapping[event.key.keysym.scancode];
159 joypads[0] &= ~Config.joypad1Mapping[event.key.keysym.scancode];
160 joypads[1] &= ~Config.joypad2Mapping[event.key.keysym.scancode];
162 case SDL_MOUSEBUTTONUP:
163 case SDL_MOUSEBUTTONDOWN:
164 processMouse(event.button.which, event.button.x, event.button.y,
165 (event.button.state == SDL_PRESSED) ? 1 : - 1);
167 case SDL_MOUSEMOTION:
168 processMouse(event.button.which, event.motion.x, event.motion.y);
171 Config.quitting = true;
176 /** This function is called to return a bit-wise mask of the state of one of the
177 five emulated SNES controllers.
179 @return 0 if you're not supporting controllers past a certain number or
180 return the mask representing the current state of the controller number
181 passed as a parameter or'ed with 0x80000000.
184 uint32 S9xReadJoypad (int which)
186 if (which < 0 || which >= 2) {
187 // More joypads that we currently handle (could happen if bad conf)
191 return joypads[which];
194 /** Get the current position of the host pointing device, usually a mouse,
195 used to emulated the SNES mouse.
197 @param buttons The buttons return value is a bit-wise mask of the two SNES
198 mouse buttons, bit 0 for button 1 (left) and bit 1 for button 2 (right).
200 bool8 S9xReadMousePosition(int which, int *x, int *y, uint32 *buttons)
202 if (which != 0) return FALSE;
206 *buttons = mouse.pressed ? 1 : 0;
211 bool8 S9xReadSuperScopePosition(int *x, int *y, uint32 *buttons)
215 *buttons = mouse.pressed ? 8 : 0;
220 /** Get and process system/input events.
221 @param block true to block, false to poll until the queue is empty.
223 void S9xProcessEvents(bool block)
228 // Wheter blocking or non blocking, poll zeemotes now.
233 SDL_WaitEvent(&event);
236 while(SDL_PollEvent(&event)) {
242 void S9xInitInputDevices()
246 mouse.enabled = false;
247 mouse.pressed = false;
253 if (Config.joypad1Enabled) {
254 joypads[0] = 0x80000000UL;
256 if (Config.joypad2Enabled) {
257 joypads[1] = 0x80000000UL;
260 // Pretty print some information
262 if (Config.joypad1Enabled) {
263 printf("Player 1 (joypad)");
264 if (Config.joypad2Enabled) {
265 printf("+ player 2 (joypad)");
267 } else if (Config.joypad2Enabled) {
268 printf("Player 2 (joypad)");
274 // TODO Non-awful mouse & superscope support
276 S9xInputScreenChanged();
279 void S9xDeinitInputDevices()
286 mouse.enabled = false;
287 mouse.pressed = false;
290 void S9xInputScreenChanged()
293 const unsigned int w = GUI.Width, h = GUI.Height;
294 for (i = 0; i < sizeof(touchbuttons)/sizeof(TouchButton); i++) {
295 touchbuttons[i].x = (unsigned int)(touchbuttons[i].fx * w);
296 touchbuttons[i].y = (unsigned int)(touchbuttons[i].fy * h);
297 touchbuttons[i].x2 = (unsigned int)(touchbuttons[i].x + touchbuttons[i].fw * w);
298 touchbuttons[i].y2 = (unsigned int)(touchbuttons[i].y + touchbuttons[i].fh * h);
302 template <typename T>
303 static void drawControls(T * buffer, const int pitch)
307 const T black = static_cast<T>(0xFFFFFFFFU);
310 for (i = 0; i < sizeof(touchbuttons)/sizeof(TouchButton); i++) {
311 temp = buffer + touchbuttons[i].y * pitch + touchbuttons[i].x;
312 for (x = touchbuttons[i].x; x < touchbuttons[i].x2; x++) {
316 temp = buffer + touchbuttons[i].y2 * pitch + touchbuttons[i].x;
317 for (x = touchbuttons[i].x; x < touchbuttons[i].x2; x++) {
321 temp = buffer + touchbuttons[i].y * pitch + touchbuttons[i].x;
322 for (y = touchbuttons[i].y; y < touchbuttons[i].y2; y++) {
326 temp = buffer + touchbuttons[i].y * pitch + touchbuttons[i].x2;
327 for (y = touchbuttons[i].y; y < touchbuttons[i].y2; y++) {
334 void S9xInputScreenDraw(void * buffer, int pitch)
336 drawControls(reinterpret_cast<uint16*>(buffer), pitch / 2);