⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 input.c

📁 NES game Emulator in Linux.c and asm codes.
💻 C
字号:
/*

SNEeSe, an Open Source Super NES emulator.


Copyright (c) 1998-2004 Charles Bilyue'.
Portions Copyright (c) 2003-2004 Daniel Horchner.

This is free software.  See 'LICENSE' for details.
You must read and accept the license prior to use.

*/

/*
 Virtual game controller 'key' emulation

 Bit 7 of scancode is still reserved for make/break codes.

 Each controller begins at 0 - (1024 * controller #).
 Each controller is allowed up to 32 sticks, each with 4 axes.
 Each controller is allowed up to 256 buttons.

 Scancode layout is:
     0- 127: sticks  0-15, axes 0-3, directions 0-1
   256- 383: sticks 16-31, axes 0-3, directions 0-1
   512- 639: buttons   0-127
   768- 895: buttons 128-255
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "wrapaleg.h"

#include "input.h"
#include "helper.h"
#include "cpu/cpu.h"
#include "apu/sound.h"

/* PPU.asm */
extern unsigned char Layering_Mode;
extern unsigned char Layer_Disable_Mask;
extern unsigned char Offset_Change_Disable;
extern void Update_Layering(void);
extern void Toggle_Offset_Change(void);


SNES_CONTROLLER_INPUTS input_player1, input_player2;

signed char mouse_available;

unsigned char CONTROLLER_1_TYPE;
unsigned char CONTROLLER_2_TYPE;

volatile char key_released[KEY_MAX];

static void key_release_callback(int scancode)
{
 key_released[scancode & ~0x80] |= (scancode & 0x80);
}
END_OF_STATIC_FUNCTION(key_release_callback);

void install_key_release_callback()
{
 int i;
 static int key_release_callback_installed = (0 != 0);

 if (key_release_callback_installed) return;

 LOCK_FUNCTION(key_release_callback);
 LOCK_VARIABLE(key_released);

 for (i = 0; i < KEY_MAX; i++) key_released[i] = -1;

 keyboard_lowlevel_callback = key_release_callback;
 key_release_callback_installed = (0 == 0);
}

int UPDATE_KEYS(void)
{
 if (keyboard_needs_poll()) poll_keyboard();

 if (key[KEY_F1] && key_released[KEY_F1] != 0)
 {
  key_released[KEY_F1] = 0; SPC_MASK ^= 1;
 }

 if (key[KEY_F2] && key_released[KEY_F2] != 0)
 {
  key_released[KEY_F2] = 0; SPC_MASK ^= 2;
 }

 if (key[KEY_F3] && key_released[KEY_F3] != 0)
 {
  key_released[KEY_F3] = 0; SPC_MASK ^= 4;
 }

 if (key[KEY_F4] && key_released[KEY_F4] != 0)
 {
  key_released[KEY_F4] = 0; SPC_MASK ^= 8;
 }

 if (key[KEY_F5] && key_released[KEY_F5] != 0)
 {
  key_released[KEY_F5] = 0; SPC_MASK ^= 0x10;
 }

 if (key[KEY_F6] && key_released[KEY_F6] != 0)
 {
  key_released[KEY_F6] = 0; SPC_MASK ^= 0x20;
 }

 if (key[KEY_F7] && key_released[KEY_F7] != 0)
 {
  key_released[KEY_F7] = 0; SPC_MASK ^= 0x40;
 }

 if (key[KEY_F8] && key_released[KEY_F8] != 0)
 {
  key_released[KEY_F8] = 0; SPC_MASK ^= 0x80;
 }

 if (key[KEY_F11] && key_released[KEY_F11] != 0)
 {
  key_released[KEY_F11] = 0; FPS_ENABLED ^= (0 - 1);
 }

 if (key[KEY_F12] && key_released[KEY_F12] != 0)
 {
  key_released[KEY_F12] = 0; BREAKS_ENABLED ^= (0 - 1);
 }

 if (key[KEY_1] && key_released[KEY_1] != 0)
 {
  key_released[KEY_1] = 0; Layer_Disable_Mask ^= 1;
 }

 if (key[KEY_2] && key_released[KEY_2] != 0)
 {
  key_released[KEY_2] = 0; Layer_Disable_Mask ^= 2;
 }

 if (key[KEY_3] && key_released[KEY_3] != 0)
 {
  key_released[KEY_3] = 0; Layer_Disable_Mask ^= 4;
 }

 if (key[KEY_4] && key_released[KEY_4] != 0)
 {
  key_released[KEY_4] = 0; Layer_Disable_Mask ^= 8;
 }

 if (key[KEY_5] && key_released[KEY_5] != 0)
 {
  key_released[KEY_5] = 0; Layer_Disable_Mask ^= 0x10;
 }

 if (key[KEY_7] && key_released[KEY_7] != 0)
 {
  key_released[KEY_7] = 0; Toggle_Offset_Change();
 }

 if (key[KEY_6] && key_released[KEY_6] != 0)
 {
  key_released[KEY_6] = 0;
  if (Offset_Change_Disable != 0) Toggle_Offset_Change();
  Layering_Mode = 0;
  Layer_Disable_Mask = 0xFF;
  SPC_MASK = 0xFF;
 }

 if (key[KEY_8] && key_released[KEY_8] != 0)
 {
  key_released[KEY_8] = 0;
  if (Layering_Mode++ >= 2) Layering_Mode = 0;
 }

 Update_Layering();

 if (key[KEY_0] && key_released[KEY_0] != 0)
 {
  key_released[KEY_0] = 0;
  OutputScreen();
 }

 if (key[KEY_ESC] && key_released[KEY_ESC] != 0)
 {
  key_released[KEY_ESC] = 0;
  return (0 == 0);
 }

 while (key[KEY_F9]);

 if (key[KEY_F10])
 {
extern volatile unsigned Timer_Counter_Throttle;
  while (key[KEY_F10]);
  while (!key[KEY_F10] && !key[KEY_F11]);
  Timer_Counter_Throttle = 0;
 }

 return (0 != 0);
}

char fast_forward_enabled(void)
{
 if (keyboard_needs_poll()) poll_keyboard();

 return key[KEY_TILDE];
}

unsigned short MickeyRead;  /* MSB = Yyyyyyyy  LSB = Xxxxxxxx */
unsigned char MouseButtons;

void MickeyMouse()
{
 int mx,my;

 get_mouse_mickeys(&mx, &my);

 MouseButtons=mouse_b << 6;   /* save button state at time of read */

 MickeyRead = 0;
 if (mx < 0)
 {
  MickeyRead |= 0x80;
  mx = -mx;
 }
 MickeyRead |= (mx >> 1) & 0x7F;
 if (my < 0)
 {
  MickeyRead |= 0x8000;
  my = -my;
 }
 MickeyRead |= ((my >> 1) & 0x7F) << 8;
}

extern unsigned char NMITIMEN;
extern unsigned char Controller1_Pos, Controller23_Pos, Controller45_Pos;
extern unsigned char JOY1L, JOY1H, JOY2L, JOY2H;
extern unsigned char JOY3L, JOY3H, JOY4L, JOY4H;

int joystick_vkey_state(int vkey)
{
 int joystick, stick, axis, button;

 joystick = (vkey + 1) / JOYSTICK_OFFSET(0);
 if (joystick >= num_joysticks) return FALSE;

 vkey -= JOYSTICK_OFFSET(joystick);

 if (vkey < JOYSTICK_BUTTONS_OFFSET)
 {
  stick = (((vkey & ~255) >> 1) + (vkey & 127)) /
   (JOYSTICK_MAX_AXES_PER_STICK * 2);

  if (stick >= joy[joystick].num_sticks) return FALSE;

  vkey &= (JOYSTICK_MAX_AXES_PER_STICK * 2) - 1;

  axis = vkey >> 1;

  if (axis >= joy[joystick].stick[stick].num_axis) return FALSE;

  if (!(vkey & 1))
  {
   return joy[joystick].stick[stick].axis[vkey >> 1].d1;
  }
  else
  {
   return joy[joystick].stick[stick].axis[vkey >> 1].d2;
  }
 }


 /* If we get here, it's a button */
 vkey -= JOYSTICK_BUTTONS_OFFSET;

 button = (((vkey & ~255) >> 1) + (vkey & 127));

 if (button >= joy[joystick].num_buttons) return FALSE;

 return joy[joystick].button[button].b;
}

int get_vkey_state(int vkey)
{
 if (vkey < 0) return joystick_vkey_state(vkey);

 return key[vkey];
}

void update_controller(const SNES_CONTROLLER_INPUTS *input,
 unsigned char *JOYL, unsigned char *JOYH)
{
 if (CONTROLLER_1_TYPE != 1)
 {
  *JOYL = 0;

  /* Is A pressed? */
  if (get_vkey_state(input->a)) *JOYL |= 0x80;
  /* Is X pressed? */
  if (get_vkey_state(input->x)) *JOYL |= 0x40;
  /* Is L pressed? */
  if (get_vkey_state(input->l)) *JOYL |= 0x20;
  /* Is R pressed? */
  if (get_vkey_state(input->r)) *JOYL |= 0x10;

  *JOYH = 0;

  /* Is B pressed? */
  if (get_vkey_state(input->b)) *JOYH |= 0x80;
  /* Is Y pressed? */
  if (get_vkey_state(input->y)) *JOYH |= 0x40;
  /* Is SELECT pressed? */
  if (get_vkey_state(input->select)) *JOYH |= 0x20;
  /* Is START pressed? */
  if (get_vkey_state(input->start)) *JOYH |= 0x10;
  /* Is UP or DOWN pressed? */
  if (get_vkey_state(input->up)) *JOYH |=
   !get_vkey_state(input->down) ? 0x08 : 0;
  else *JOYH |= get_vkey_state(input->down) ? 0x04 : 0;
  /* Is LEFT or RIGHT pressed? */
  if (get_vkey_state(input->left)) *JOYH |=
   !get_vkey_state(input->right) ? 0x02 : 0;
  else *JOYH |= get_vkey_state(input->right) ? 0x01 : 0;
 }
}

/* JOYPAD UPDATE FUNCTION */
/* now called during VBL to accomodate JOYC1 & JOYC2 */
void update_controllers(void)
{
 if (keyboard_needs_poll()) poll_keyboard();

 poll_joystick();

 if (CONTROLLER_1_TYPE == 1 || CONTROLLER_2_TYPE == 1)
 /* mouse */
 {
  MickeyMouse();
 }

 /* reset controllers */
 if (NMITIMEN & 1)
 {
  Controller1_Pos = Controller23_Pos = Controller45_Pos = 0;
 }

 /* update controller 1 */
 update_controller(&input_player1, &JOY1L, &JOY1H);

 /* update controller 2 */
 update_controller(&input_player2, &JOY2L, &JOY2H);
}

void joyscantotext(int vkey, char *text)
{
 int joystick, stick;

 joystick = (vkey + 1) / JOYSTICK_OFFSET(0);
 vkey -= JOYSTICK_OFFSET(joystick);

 if (vkey < JOYSTICK_BUTTONS_OFFSET)
 {
  stick = (((vkey & ~255) >> 1) + (vkey & 127)) /
   (JOYSTICK_MAX_AXES_PER_STICK * 2);

  vkey &= (JOYSTICK_MAX_AXES_PER_STICK * 2) - 1;

  if (!(vkey & 1))
  {
   sprintf(text, "J%dS%dA%d-", joystick + 1, stick + 1, (vkey >> 1) + 1);
  }
  else
  {
   sprintf(text, "J%dS%dA%d+", joystick + 1, stick + 1, (vkey >> 1) + 1);
  }
 }
 else
 {
  vkey -= JOYSTICK_BUTTONS_OFFSET;

  sprintf(text, "J%dB%d", joystick + 1,
   (((vkey & ~255) >> 1) + (vkey & 127)) + 1);
 }
}

void scantotext(int scanc, char *text)
{
 if (scanc < 0)
 {
  joyscantotext(scanc, text);
  return;
 }
 text[0]=toupper(scancode_to_ascii(scanc));
 text[1]=0;
 switch(scanc)
 {
  case KEY_ALT: strcpy(text,"LAlt"); break;
  case KEY_ALTGR: strcpy(text,"RAlt"); break;
  case KEY_BACKSPACE: strcpy(text,"Bksp"); break;
  case KEY_CAPSLOCK: strcpy(text,"Caps"); break;
  case KEY_DEL: strcpy(text,"Del"); break;
  case KEY_DOWN: strcpy(text,"Down"); break;
  case KEY_END: strcpy(text,"End"); break;
  case KEY_ENTER: strcpy(text,"Ent"); break;
  case KEY_ENTER_PAD: strcpy(text,"GEnt"); break;
  case KEY_HOME: strcpy(text,"Home"); break;
  case KEY_INSERT: strcpy(text,"Ins"); break;
  case KEY_LCONTROL: strcpy(text,"LCtl"); break;
  case KEY_LEFT: strcpy(text,"Left"); break;
  case KEY_LSHIFT: strcpy(text,"LShf"); break;
  case KEY_LWIN: strcpy(text,"LWin"); break;
  case KEY_MENU: strcpy(text,"Menu"); break;
  case KEY_PGDN: strcpy(text,"PgDn"); break;
  case KEY_PGUP: strcpy(text,"PgUp"); break;
  case KEY_RCONTROL: strcpy(text,"RCtl"); break;
  case KEY_RIGHT: strcpy(text,"Rght"); break;
  case KEY_RSHIFT: strcpy(text,"RShf"); break;
  case KEY_RWIN: strcpy(text,"RWin"); break;
  case KEY_SPACE: strcpy(text,"Spc"); break;
  case KEY_TAB: strcpy(text,"Tab"); break;
  case KEY_UP: strcpy(text,"Up"); break;
  case KEY_F1: strcpy(text,"F1"); break;
  case KEY_F2: strcpy(text,"F2"); break;
  case KEY_F3: strcpy(text,"F3"); break;
  case KEY_F4: strcpy(text,"F4"); break;
  case KEY_F5: strcpy(text,"F5"); break;
  case KEY_F6: strcpy(text,"F6"); break;
  case KEY_F7: strcpy(text,"F7"); break;
  case KEY_F8: strcpy(text,"F8"); break;
  case KEY_F9: strcpy(text,"F9"); break;
  case KEY_F10: strcpy(text,"F10"); break;
  case KEY_F11: strcpy(text,"F11"); break;
  case KEY_F12: strcpy(text,"F12"); break;
  case KEY_0_PAD: strcpy(text,"Num0"); break;
  case KEY_1_PAD: strcpy(text,"Num1"); break;
  case KEY_2_PAD: strcpy(text,"Num2"); break;
  case KEY_3_PAD: strcpy(text,"Num3"); break;
  case KEY_4_PAD: strcpy(text,"Num4"); break;
  case KEY_5_PAD: strcpy(text,"Num5"); break;
  case KEY_6_PAD: strcpy(text,"Num6"); break;
  case KEY_7_PAD: strcpy(text,"Num7"); break;
  case KEY_8_PAD: strcpy(text,"Num8"); break;
  case KEY_9_PAD: strcpy(text,"Num9"); break;
  case KEY_PLUS_PAD: strcpy(text,"Num+"); break;
  case KEY_MINUS_PAD: strcpy(text,"Num-"); break;
  case KEY_SLASH_PAD: strcpy(text,"Num/"); break;
  case KEY_ASTERISK: strcpy(text,"Num*"); break;
  case KEY_DEL_PAD: strcpy(text,"Num."); break;
 }
}

// 4 joysticks, 256 buttons, 32 sticks * 4 axes * 2 directions
signed char joystick_key[4][2][256];

int joystick_axis_direction_to_vkey(int joystick, int stick, int axis,
 int direction)
{
 return JOYSTICK_OFFSET(joystick) + JOYSTICK_STICK_OFFSET(stick) +
  axis * 2 + direction;
}

int joystick_button_to_vkey(int joystick, int button)
{
 return JOYSTICK_OFFSET(joystick) + JOYSTICK_BUTTON_OFFSET(button);
}

int update_joystick_vkeys(void)
{
 int last_vkey = 0;
 int joystick, stick, axis, button;

 poll_joystick();

 for (joystick = 0; joystick < 4; joystick++)
 {
  if (joystick >= num_joysticks) break;

  for (stick = 0; stick < 32; stick++)
  {
   if (stick >= joy[joystick].num_sticks) break;

   for (axis = 0; axis < 4; axis++)
   {
    if (axis >= joy[joystick].stick[stick].num_axis) break;

    if (!last_vkey &&
     !joystick_key[joystick][0][(stick * 4 + axis) * 2 + 0] &&
     joy[joystick].stick[stick].axis[axis].d1)
    {
     last_vkey =
      joystick_axis_direction_to_vkey(joystick, stick, axis, 0);
    }

    joystick_key[joystick][0][(stick * 4 + axis) * 2 + 0] =
     joy[joystick].stick[stick].axis[axis].d1;

    if (!last_vkey &&
     !joystick_key[joystick][0][(stick * 4 + axis) * 2 + 1] &&
     joy[joystick].stick[stick].axis[axis].d2)
    {
     last_vkey =
      joystick_axis_direction_to_vkey(joystick, stick, axis, 1);
    }

    joystick_key[joystick][0][(stick * 4 + axis) * 2 + 1] =
     joy[joystick].stick[stick].axis[axis].d2;
   }
  }

  for (button = 0; button < 256; button++)
  {
   if (button >= joy[joystick].num_buttons) break;

   if (!last_vkey &&
    !joystick_key[joystick][1][button] && joy[joystick].button[button].b)
   {
    last_vkey = joystick_button_to_vkey(joystick, button);
   }

   joystick_key[joystick][1][button] = joy[joystick].button[button].b;
  }
 }

 return last_vkey;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -