Logo Search packages:      
Sourcecode: scummvm version File versions

osys_n64_events.cpp

/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL$
 * $Id$
 *
 */

#include <math.h> // Needed for "tan()" function

#include "osys_n64.h"

// Pad buttons
#define START_BUTTON(a) (a & 0x1000)
#define A_BUTTON(a)     (a & 0x8000)
#define B_BUTTON(a)     (a & 0x4000)
#define Z_BUTTON(a)     (a & 0x2000)

// Triggers
#define TL_BUTTON(a)    (a & 0x0020)
#define TR_BUTTON(a)    (a & 0x0010)

// D-Pad
#define DL_BUTTON(a)    (a & 0x0200)
#define DR_BUTTON(a)    (a & 0x0100)
#define DU_BUTTON(a)    (a & 0x0800)
#define DD_BUTTON(a)    (a & 0x0400)

// Yellow C buttons
#define CL_BUTTON(a)    (a & 0x0002)
#define CR_BUTTON(a)    (a & 0x0001)
#define CU_BUTTON(a)    (a & 0x0008)
#define CD_BUTTON(a)    (a & 0x0004)

// Macro for button press checking
#define PRESSED_START(now, before)  (START_BUTTON(now) && !START_BUTTON(before))
#define RELEASED_START(now, before) (!START_BUTTON(now) && START_BUTTON(before))
#define PRESSED_A(now, before)            (A_BUTTON(now) && !A_BUTTON(before))
#define RELEASED_A(now, before)           (!A_BUTTON(now) && A_BUTTON(before))
#define PRESSED_B(now, before)            (B_BUTTON(now) && !B_BUTTON(before))
#define RELEASED_B(now, before)           (!B_BUTTON(now) && B_BUTTON(before))
#define PRESSED_Z(now, before)            (Z_BUTTON(now) && !Z_BUTTON(before))
#define RELEASED_Z(now, before)           (!Z_BUTTON(now) && Z_BUTTON(before))
#define PRESSED_TL(now, before)           (TL_BUTTON(now) && !TL_BUTTON(before))
#define RELEASED_TL(now, before)    (!TL_BUTTON(now) && TL_BUTTON(before))
#define PRESSED_TR(now, before)           (TR_BUTTON(now) && !TR_BUTTON(before))
#define RELEASED_TR(now, before)    (!TR_BUTTON(now) && TR_BUTTON(before))
#define PRESSED_DL(now, before)           (DL_BUTTON(now) && !DL_BUTTON(before))
#define RELEASED_DL(now, before)    (!DL_BUTTON(now) && DL_BUTTON(before))
#define PRESSED_DR(now, before)           (DR_BUTTON(now) && !DR_BUTTON(before))
#define RELEASED_DR(now, before)    (!DR_BUTTON(now) && DR_BUTTON(before))
#define PRESSED_DU(now, before)     (DU_BUTTON(now) && !DU_BUTTON(before))
#define RELEASED_DU(now, before)    (!DU_BUTTON(now) && DU_BUTTON(before))
#define PRESSED_DD(now, before)           (DD_BUTTON(now) && !DD_BUTTON(before))
#define RELEASED_DD(now, before)    (!DD_BUTTON(now) && DD_BUTTON(before))
#define PRESSED_CL(now, before)           (CL_BUTTON(now) && !CL_BUTTON(before))
#define RELEASED_CL(now, before)    (!CL_BUTTON(now) && CL_BUTTON(before))
#define PRESSED_CR(now, before)           (CR_BUTTON(now) && !CR_BUTTON(before))
#define RELEASED_CR(now, before)    (!CR_BUTTON(now) && CR_BUTTON(before))
#define PRESSED_CU(now, before)           (CU_BUTTON(now) && !CU_BUTTON(before))
#define RELEASED_CU(now, before)    (!CU_BUTTON(now) && CU_BUTTON(before))
#define PRESSED_CD(now, before)           (CD_BUTTON(now) && !CD_BUTTON(before))
#define RELEASED_CD(now, before)    (!CD_BUTTON(now) && CD_BUTTON(before))

#define MOUSE_DEADZONE 0
#define MOUSE_SENSIBILITY 1.5f
#define PAD_DEADZONE 1
#define PAD_ACCELERATION 15
#define PAD_CHECK_TIME 40

static controller_data_buttons _ctrlData;

void OSystem_N64::readControllerAnalogInput(void) {
      int8 pad_analogX, pad_analogY;
      int8 pad_mouseX, pad_mouseY;

      // Read current controller status
      controller_Read_Buttons(&_ctrlData);

      pad_analogX = (_ctrlData.c[_controllerPort].throttle >> 8) & 0xFF;
      pad_analogY = (_ctrlData.c[_controllerPort].throttle >> 0) & 0xFF;

      pad_mouseX = 0;
      pad_mouseY = 0;

      if (_mousePort >= 0) { // If mouse is present, read movement values
            pad_mouseX = (_ctrlData.c[_mousePort].throttle >> 8) & 0xFF;
            pad_mouseY = (_ctrlData.c[_mousePort].throttle >> 0) & 0xFF;
      }

      float mx = _tempMouseX;
      float my = _tempMouseY;

      // Limit the analog range for pad.
      // When moving in diagonal the max/min of 128/-128 was not reached
      // yielding weird results for the tangent acceleration function
      if (pad_analogX > 60) pad_analogX = 60;
      else if (pad_analogX < -60) pad_analogX = -60;
      if (pad_analogY > 60) pad_analogY = 60;
      else if (pad_analogY < -60) pad_analogY = -60;

      // Gamepad
      if (abs(pad_analogX) > PAD_DEADZONE)
            mx += tan(pad_analogX * (M_PI / 140));
      if (abs(pad_analogY) > PAD_DEADZONE)
            my -= tan(pad_analogY * (M_PI / 140));

      // Mouse
      if (abs(pad_mouseX) > MOUSE_DEADZONE)
            mx += (pad_mouseX / MOUSE_SENSIBILITY);
      if (abs(pad_mouseY) > MOUSE_DEADZONE)
            my -= (pad_mouseY / MOUSE_SENSIBILITY);

      if (mx < 0)
            mx = 0;

      if (mx >= _mouseMaxX)
            mx = _mouseMaxX - 1;

      if (my < 0)
            my = 0;

      if (my >= _mouseMaxY)
            my = _mouseMaxY - 1;

      _tempMouseX = mx;
      _tempMouseY = my;
}

00147 bool OSystem_N64::pollEvent(Common::Event &event) {
      // Check Timers. Not the best place, but checking in interrupts proved to be unsafe
      checkTimers();

      // Refill audio buffers, doing this inside interrupts could be harmful
      refillAudioBuffers();

      // Read current controller status
      controller_Read_Buttons(&_ctrlData);

      static uint16 oldButtons = 0; // old button data... used for button press/release
      static uint16 oldMouseButtons = 0;

      uint16 newButtons = _ctrlData.c[_controllerPort].buttons; // Read from controller
      uint16 newMouseButtons = 0;

      if (_mousePort >= 0)
            newMouseButtons = _ctrlData.c[_mousePort].buttons;

      bool buttonPressed = false;
      static bool left_digital = false;
      static bool right_digital = false;
      static bool up_digital = false;
      static bool down_digital = false;

      if (newButtons != oldButtons) { // Check PAD button press
            if (PRESSED_DL(newButtons, oldButtons)) // Pressed LEFT
                  left_digital = true;
            else if (RELEASED_DL(newButtons, oldButtons)) // Released LEFT
                  left_digital = false;

            if (PRESSED_DR(newButtons, oldButtons)) // Pressed RIGHT
                  right_digital = true;
            else if (RELEASED_DR(newButtons, oldButtons)) // Released RIGHT
                  right_digital = false;

            if (PRESSED_DU(newButtons, oldButtons)) // Pressed UP
                  up_digital = true;
            else if (RELEASED_DU(newButtons, oldButtons)) // Released UP
                  up_digital = false;

            if (PRESSED_DD(newButtons, oldButtons)) // Pressed DOWN
                  down_digital = true;
            else if (RELEASED_DD(newButtons, oldButtons)) // Released DOWN
                  down_digital = false;

            // Check if there is a button pressed, apart from DPAD
            if ((newButtons & 0xF0FF) != (oldButtons & 0xF0FF))
                  buttonPressed = true;

            if (PRESSED_B(newButtons, oldButtons)) { // Pressed B - Right Mouse Button
                  event.type = Common::EVENT_RBUTTONDOWN;
            } else if (RELEASED_B(newButtons, oldButtons)) { // Released B
                  event.type = Common::EVENT_RBUTTONUP;
            } else if (PRESSED_A(newButtons, oldButtons)) { // Pressed A - Period
                  event.kbd.keycode = Common::KEYCODE_PERIOD;
                  event.kbd.ascii = '.';
                  event.type = Common::EVENT_KEYDOWN;
            } else if (RELEASED_A(newButtons, oldButtons)) { // Released A
                  event.kbd.keycode = Common::KEYCODE_PERIOD;
                  event.kbd.ascii = '.';
                  event.type = Common::EVENT_KEYUP;
            } else if (PRESSED_START(newButtons, oldButtons)) { // Pressed START
                  event.kbd.keycode = Common::KEYCODE_F5;
                  event.kbd.ascii = Common::ASCII_F5;
                  event.type = Common::EVENT_KEYDOWN;
            } else if (RELEASED_START(newButtons, oldButtons)) { // Released START
                  event.kbd.keycode = Common::KEYCODE_F5;
                  event.kbd.ascii = Common::ASCII_F5;
                  event.type = Common::EVENT_KEYUP;
            } else if (PRESSED_TL(newButtons, oldButtons)) { // Pressed Trigger Left - ESC
                  event.kbd.keycode = Common::KEYCODE_ESCAPE;
                  event.kbd.ascii = 27;
                  event.type = Common::EVENT_KEYDOWN;
            } else if (RELEASED_TL(newButtons, oldButtons)) { // Released Trigger Left
                  event.kbd.keycode = Common::KEYCODE_ESCAPE;
                  event.kbd.ascii = 27;
                  event.type = Common::EVENT_KEYUP;
            } else if (PRESSED_TR(newButtons, oldButtons)) { // Pressed Trigger Right - F7
                  event.kbd.keycode = Common::KEYCODE_F7;
                  event.kbd.ascii = Common::ASCII_F7;
                  event.type = Common::EVENT_KEYDOWN;
            } else if (RELEASED_TR(newButtons, oldButtons)) { // Released Trigger Right
                  event.kbd.keycode = Common::KEYCODE_F7;
                  event.kbd.ascii = Common::ASCII_F7;
                  event.type = Common::EVENT_KEYUP;
            } else if (PRESSED_Z(newButtons, oldButtons)) { // Pressed Z - Left Mouse Button
                  event.type = Common::EVENT_LBUTTONDOWN;
            } else if (RELEASED_Z(newButtons, oldButtons)) { // Released Z
                  event.type = Common::EVENT_LBUTTONUP;
            }

            uint8 curKPad = 0; // Current simulated keypad button press
            static uint8 lastKPad = 0; // Previously simulated keypad button press

            // Check which directions are pressed
            if (CU_BUTTON(newButtons)) {
                  if (CL_BUTTON(newButtons)) {
                        curKPad = 7;
                  } else if (CR_BUTTON(newButtons)) {
                        curKPad = 9;
                  } else {
                        curKPad = 8;
                  }
            } else if (CD_BUTTON(newButtons)) {
                  if (CL_BUTTON(newButtons)) {
                        curKPad = 1;
                  } else if (CR_BUTTON(newButtons)) {
                        curKPad = 3;
                  } else {
                        curKPad = 2;
                  }
            } else if (CL_BUTTON(newButtons)) {
                  curKPad = 4;
            } else if (CR_BUTTON(newButtons)) {
                  curKPad = 6;
            }

            switch (lastKPad) {
            case 7: // UP - LEFT
                  if (curKPad != 7) {
                        event.kbd.keycode = Common::KEYCODE_KP7;
                        event.type = Common::EVENT_KEYUP;
                        lastKPad = 0;
                  }
                  break;
            case 9: // UP - RIGHT
                  if (curKPad != 9) {
                        event.kbd.keycode = Common::KEYCODE_KP9;
                        event.type = Common::EVENT_KEYUP;
                        lastKPad = 0;
                  }
                  break;
            case 1: // DOWN - LEFT
                  if (curKPad != 1) {
                        event.kbd.keycode = Common::KEYCODE_KP1;
                        event.type = Common::EVENT_KEYUP;
                        lastKPad = 0;
                  }
                  break;
            case 3: // DOWN - RIGHT
                  if (curKPad != 3) {
                        event.kbd.keycode = Common::KEYCODE_KP3;
                        event.type = Common::EVENT_KEYUP;
                        lastKPad = 0;
                  }
                  break;
            case 4: // LEFT
                  if (curKPad != 4) {
                        event.kbd.keycode = Common::KEYCODE_KP4;
                        event.type = Common::EVENT_KEYUP;
                        lastKPad = 0;
                  }
                  break;
            case 6: // RIGHT
                  if (curKPad != 6) {
                        event.kbd.keycode = Common::KEYCODE_KP6;
                        event.type = Common::EVENT_KEYUP;
                        lastKPad = 0;
                  }
                  break;
            case 8: // UP
                  if (curKPad != 8) {
                        event.kbd.keycode = Common::KEYCODE_KP8;
                        event.type = Common::EVENT_KEYUP;
                        lastKPad = 0;
                  }
                  break;
            case 2: // DOWN
                  if (curKPad != 2) {
                        event.kbd.keycode = Common::KEYCODE_KP2;
                        event.type = Common::EVENT_KEYUP;
                        lastKPad = 0;
                  }
                  break;
            case 0: // No previous press
                  if (curKPad == 7) { // UP - LEFT
                        event.type = Common::EVENT_KEYDOWN;
                        event.kbd.keycode = Common::KEYCODE_KP7;
                  } else if (curKPad == 9) { // UP - RIGHT
                        event.type = Common::EVENT_KEYDOWN;
                        event.kbd.keycode = Common::KEYCODE_KP9;
                  } else if (curKPad == 1) { // DOWN - LEFT
                        event.type = Common::EVENT_KEYDOWN;
                        event.kbd.keycode = Common::KEYCODE_KP1;
                  } else if (curKPad == 3) { // DOWN - RIGHT
                        event.type = Common::EVENT_KEYDOWN;
                        event.kbd.keycode = Common::KEYCODE_KP3;
                  } else if (curKPad == 4) { // LEFT
                        event.type = Common::EVENT_KEYDOWN;
                        event.kbd.keycode = Common::KEYCODE_KP4;
                  } else if (curKPad == 6) { // RIGHT
                        event.type = Common::EVENT_KEYDOWN;
                        event.kbd.keycode = Common::KEYCODE_KP6;
                  } else if (curKPad == 8) { // UP
                        event.type = Common::EVENT_KEYDOWN;
                        event.kbd.keycode = Common::KEYCODE_KP8;
                  } else if (curKPad == 2) { // DOWN
                        event.type = Common::EVENT_KEYDOWN;
                        event.kbd.keycode = Common::KEYCODE_KP2;
                  }
                  lastKPad = curKPad;

                  break;
            default:
                  lastKPad = 0;
                  break; // Do nothing.
            }

            // A simulated keypad has been "pressed", input the ascii code
            if (curKPad != 0) {
                  event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0';
            }

            oldButtons = newButtons; // Save current button status

            if (buttonPressed) {
                  event.mouse.x = _mouseX;
                  event.mouse.y = _mouseY;
                  return true;
            }
      }

      if (newMouseButtons != oldMouseButtons) { // Check mouse button press
            buttonPressed = true;

            if (PRESSED_B(newMouseButtons, oldMouseButtons)) { // Pressed Right Mouse Button
                  event.type = Common::EVENT_RBUTTONDOWN;
            } else if (RELEASED_B(newMouseButtons, oldMouseButtons)) { // Released RMB
                  event.type = Common::EVENT_RBUTTONUP;
            } else if (PRESSED_A(newMouseButtons, oldMouseButtons)) { // Pressed Left Mouse Button
                  event.type = Common::EVENT_LBUTTONDOWN;
            } else if (RELEASED_A(newMouseButtons, oldMouseButtons)) { // Released LMB
                  event.type = Common::EVENT_LBUTTONUP;
            }

            oldMouseButtons = newMouseButtons; // Save current button status

            if (buttonPressed) {
                  event.mouse.x = _mouseX;
                  event.mouse.y = _mouseY;
                  return true;
            }
      }

      static uint32 _lastPadCheck = 0;
      uint32 curTime = getMillis();

      if ((curTime - _lastPadCheck) > PAD_CHECK_TIME) {
            _lastPadCheck = curTime;

            float mx = _tempMouseX;
            float my = _tempMouseY;

            if (left_digital || right_digital || up_digital || down_digital) {
                  if (left_digital)
                        mx -= 2;
                  else if (right_digital)
                        mx += 2;
                  if (up_digital)
                        my -= 2;
                  else if (down_digital)
                        my += 2;
            }

            if (mx < 0)
                  mx = 0;

            if (mx >= _mouseMaxX)
                  mx = _mouseMaxX - 1;

            if (my < 0)
                  my = 0;

            if (my >= _mouseMaxY)
                  my = _mouseMaxY - 1;

            if ((mx != _mouseX) || (my != _mouseY)) {
                  event.type = Common::EVENT_MOUSEMOVE;
                  event.mouse.x = _mouseX = _tempMouseX = mx;
                  event.mouse.y = _mouseY = _tempMouseY = my;

                  _dirtyOffscreen = true;

                  return true;
            }

      }

      return false;
}


Generated by  Doxygen 1.6.0   Back to index