snes mouse support
[drnoksnes] / platform / sdli.cpp
index 3fb883f..9cfa1f4 100644 (file)
 #include <SDL.h>
+#include <math.h>
 
 #include "platform.h"
 #include "snes9x.h"
 #include "display.h"
 
-#define kPollEveryNFrames      3
+struct TouchButton {
+       unsigned short mask;
+       unsigned short x, y;
+       unsigned short x2, y2;
+       float fx, fy;
+       float fw, fh;
+};
+
+#define TOUCH_BUTTON_INITIALIZER(name, x, y, w, h) \
+       {SNES_##name##_MASK, 0, 0, 0, 0, x, y, w, h}
+
+static TouchButton touchbuttons[] = {
+       TOUCH_BUTTON_INITIALIZER(TL, 0, 0, 0.375, 0.0833),
+       TOUCH_BUTTON_INITIALIZER(TR, 0.625, 0, 0.375, 0.0833),
+       TOUCH_BUTTON_INITIALIZER(UP, 0.125, 0.0833, 0.125, 0.2777), //2
+       TOUCH_BUTTON_INITIALIZER(LEFT, 0.0, 0.3611, 0.125, 0.2777), //3
+       TOUCH_BUTTON_INITIALIZER(RIGHT, 0.25, 0.3611, 0.125, 0.2777), //4
+       TOUCH_BUTTON_INITIALIZER(DOWN, 0.125, 0.6388, 0.125, 0.2777), //5
+       TOUCH_BUTTON_INITIALIZER(START, 0, 0.9166, 0.375, 0.0833),
+       TOUCH_BUTTON_INITIALIZER(Y, 0.75, 0.0833, 0.125, 0.2777),
+       TOUCH_BUTTON_INITIALIZER(X, 0.625, 0.3611, 0.125, 0.2777),
+       TOUCH_BUTTON_INITIALIZER(A, 0.875, 0.3611, 0.125, 0.2777),
+       TOUCH_BUTTON_INITIALIZER(B, 0.75, 0.6388, 0.125, 0.2777),
+       TOUCH_BUTTON_INITIALIZER(SELECT, 0.625, 0.9166, 0.375, 0.0833),
+};
+
+static TouchButton* current = 0;
 
 static uint32 joypads[2];
 static struct {
        unsigned x;
        unsigned y;
-       bool pressed;
+       bool enabled, pressed;
 } mouse;
 
+static TouchButton* getButtonFor(unsigned int x, unsigned int y) {
+       unsigned int i;
+
+       for (i = 0; i < sizeof(touchbuttons)/sizeof(TouchButton); i++) {
+               if (x > touchbuttons[i].x && x < touchbuttons[i].x2 &&
+                       y > touchbuttons[i].y && y < touchbuttons[i].y2) {
+
+                       return &touchbuttons[i];
+               }
+       }
+
+       return 0;
+}
+
+static inline void unpress(TouchButton* b) {
+       joypads[0] &= ~b->mask;
+}
+static inline void press(TouchButton* b) {
+       joypads[0] |= b->mask;
+}
+
+static void processMouse(unsigned int x, unsigned int y, int pressed = 0)
+{
+       if (Config.touchscreenInput) {
+               if (pressed < 0) {
+                       // Button up.
+                       if (current) {
+                               // Leaving button
+                               unpress(current);
+                               current = 0;
+                       }
+               } else {
+                       // Button down, or mouse motion.
+                       TouchButton* b = getButtonFor(x, y);
+                       if (current && b && current != b) {
+                               // Moving from button to button
+                               unpress(current);
+                               current = b;
+                               press(current);
+                       } else if (current && !b) {
+                               // Leaving button
+                               unpress(current);
+                               current = 0;
+                       } else if (!current && b) {
+                               // Entering button
+                               current = b;
+                               press(current);
+                       }
+               }
+       } else if (mouse.enabled) {
+               mouse.x = x;
+               mouse.y = y;
+
+               if (mouse.x < GUI.RenderX) mouse.x = 0;
+               else {
+                       mouse.x -= GUI.RenderX;
+                       if (mouse.x > GUI.RenderW) mouse.x = GUI.RenderW;
+               }
+
+               if (mouse.y < GUI.RenderY) mouse.y = 0;
+               else {
+                       mouse.y -= GUI.RenderY;
+                       if (mouse.y > GUI.RenderH) mouse.y = GUI.RenderH;
+               }
+
+#ifdef MAEMO
+               // Remember RenderH, RenderW is 2x if using Xsp.
+               if (Config.xsp) {
+                       mouse.x /= 2;
+                       mouse.y /= 2;
+               }
+#endif
+
+               if (pressed > 0)
+                       mouse.pressed = true;
+               else if (pressed < 0)
+                       mouse.pressed = false;
+       }
+}
+
 static void processEvent(const SDL_Event& event)
 {
        switch (event.type) 
@@ -27,21 +134,11 @@ static void processEvent(const SDL_Event& event)
                break;
        case SDL_MOUSEBUTTONUP:
        case SDL_MOUSEBUTTONDOWN:
-               mouse.x = event.button.x;
-               mouse.y = event.button.y;
-               if (Config.xsp) {
-                       mouse.x /= 2;
-                       mouse.y /= 2;
-               }
-               mouse.pressed = event.button.state == SDL_PRESSED;
+               processMouse(event.button.x, event.button.y,
+                               (event.button.state == SDL_PRESSED) ? 1 : - 1);
                break;
        case SDL_MOUSEMOTION:
-               mouse.x = event.motion.x;
-               mouse.y = event.motion.y;
-               if (Config.xsp) {
-                       mouse.x /= 2;
-                       mouse.y /= 2;
-               }
+               processMouse(event.motion.x, event.motion.y);
                break;
        case SDL_QUIT:
                Config.quitting = true;
@@ -105,19 +202,24 @@ void S9xInitInputDevices()
                        break;
                case SNES_MOUSE:
                        joypads[0] = 0x80000000UL;
+                       mouse.enabled = true;
                        printf("Input: 1 joypad + mouse\n");
                        break;
                case SNES_MOUSE_SWAPPED:
                        printf("Input: mouse\n");
+                       mouse.enabled = true;
                        break;
                case SNES_SUPERSCOPE:
                        joypads[0] = 0x80000000UL;
+                       mouse.enabled = true;
                        printf("Input: 1 joypad + superscope\n");
                        break;
                default:
                        printf("Input: unknown\n");
                        break;
        }
+
+       S9xInputScreenChanged();
 }
 
 void S9xDeinitInputDevices()
@@ -125,8 +227,15 @@ void S9xDeinitInputDevices()
 
 }
 
-void S9xInputFullscreenChanged()
+void S9xInputScreenChanged()
 {
-
+       unsigned int i = 0;
+       const unsigned int w = GUI.Width, h = GUI.Height;
+       for (i = 0; i < sizeof(touchbuttons)/sizeof(TouchButton); i++) {
+               touchbuttons[i].x = (unsigned)round(touchbuttons[i].fx * w);
+               touchbuttons[i].y = (unsigned)round(touchbuttons[i].fy * h);
+               touchbuttons[i].x2 = (unsigned)round(touchbuttons[i].x + touchbuttons[i].fw * w);
+               touchbuttons[i].y2 = (unsigned)round(touchbuttons[i].y + touchbuttons[i].fh * h);
+       }
 }