minor adjustments
[fceu.git] / drivers / gp2x / input.c
index 704cb3a..43da4b3 100644 (file)
@@ -1,7 +1,4 @@
 /* FCE Ultra - NES/Famicom Emulator
- *
- * Copyright notice for this file:
- *  Copyright (C) 2002 Ben Parnell
  *
  * 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
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#define JOY_A   1
-#define JOY_B   2
-#define JOY_SELECT      4
-#define JOY_START       8
-#define JOY_UP  0x10
-#define JOY_DOWN        0x20
-#define JOY_LEFT        0x40
-#define JOY_RIGHT       0x80
-
-
-#include "minimal.h"
-extern int swapbuttons;
-extern int scaled_display;
-extern int FSkip_setting;
-
-extern void SetVideoScaling(int pixels,int width,int height);
-static INLINE long UpdateGamepadGP2X(void);
-
-
+#include "../../state.h"
+#include "../../general.h"
+#include "../../input.h"
+#include "../../svga.h"
+#include "../../video.h"
+#include "usbjoy.h"
 
 /* UsrInputType[] is user-specified.  InputType[] is current
-       (game loading can override user settings)
+       (game loading can override user settings)
 */
 static int UsrInputType[2]={SI_GAMEPAD,SI_GAMEPAD};
-static int InputType[2];
-
 static int UsrInputTypeFC={SI_NONE};
+
+static int InputType[2];
 static int InputTypeFC;
 
 static uint32 JSreturn;
-int NoWaiting=0;
 
 static int powerpadsc[2][12];
 static int powerpadside=0;
 
-
 static uint32 MouseData[3];
 static uint8 fkbkeys[0x48];
-unsigned long lastpad=0;
 
-void FCEUD_UpdateInput(void)
+static uint32 combo_acts = 0, combo_keys = 0;
+static uint32 prev_emu_acts = 0;
+
+
+static void setsoundvol(int soundvolume)
 {
-  int t=0;
-  long lastpad2=lastpad;
-  long pad = UpdateGamepadGP2X();
-  t=1;
-  //  JSreturn=(JSreturn&0xFF000000)|(JSreturn&0xFF)|((JSreturn&0xFF0000)>>8)|((JSreturn&0xFF00)<<8);
-  if(gametype==GIT_FDS)
-  {
-    NoWaiting&=~1;
-       if ((pad & GP2X_PUSH) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_R)) && (!(lastpad2 & GP2X_PUSH)))
-       {
-      DriverInterface(DES_FDSSELECT,0);
-       }
-       else if ((pad & GP2X_L) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_PUSH)) && (!(pad & GP2X_R))&& (!(lastpad2 & GP2X_L)))
-       {
-      DriverInterface(DES_FDSINSERT,0);
-       }
-       else if ((pad & GP2X_R) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_PUSH)) && (!(lastpad2 & GP2X_R)))
-       {
-      DriverInterface(DES_FDSEJECT,0);
-       }
-  }
+       int soundvolIndex;
+       static char soundvolmeter[24];
 
+       // draw on screen :D
+       gp2x_sound_volume(soundvolume, soundvolume);
+       int meterval=soundvolume/5;
+       for (soundvolIndex = 0; soundvolIndex < 20; soundvolIndex++)
+       {
+               if (soundvolIndex < meterval)
+               {
+                       soundvolmeter[soundvolIndex]='*';
+               }
+               else
+               {
+                       soundvolmeter[soundvolIndex]='_';
+               }
+       }
+       soundvolmeter[20]=0;
+       FCEU_DispMessage("|%s|", soundvolmeter);
 }
 
 
-//#ifdef GP2X
+static void do_emu_acts(uint32 acts)
+{
+       uint32 actsc = acts;
+       acts &= acts ^ prev_emu_acts;
+       prev_emu_acts = actsc;
 
-extern void ResetNES(void);
-extern void CleanSurface(void);
+       if (acts & (3 << 30))
+       {
+               unsigned long keys;
+               int do_it = 1;
+               if (acts & (1 << 30))
+               {
+                       if (Settings.sstate_confirm & 2)
+                       {
+                               FCEU_DispMessage("LOAD STATE? (Y=yes, X=no)");
+                               FCEU_PutImage();
+                               FCEUD_Update(XBuf+8,NULL,0);
+                               while( !((keys = gp2x_joystick_read(1)) & (GP2X_X|GP2X_Y)) ) usleep(50*1024);
+                               if (keys & GP2X_X) do_it = 0;
+                               FCEU_DispMessage("");
+                       }
+                       if (do_it) FCEUI_LoadState();
+               }
+               else
+               {
+                       if (Settings.sstate_confirm & 1)
+                       {
+                               char *fname = FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0);
+                               FILE *st=fopen(fname,"rb");
+                               free(fname);
+                               if (st)
+                               {
+                                       fclose(st);
+                                       FCEU_DispMessage("OVERWRITE SAVE? (Y=yes, X=no)");
+                                       FCEU_PutImage();
+                                       FCEUD_Update(XBuf+8,NULL,0);
+                                       while( !((keys = gp2x_joystick_read(1)) & (GP2X_X|GP2X_Y)) ) usleep(50*1024);
+                                       if (keys & GP2X_X) do_it = 0;
+                                       FCEU_DispMessage("");
+                               }
+                       }
+                       if (do_it) FCEUI_SaveState();
+               }
+               RefreshThrottleFPS();
+       }
+       else if (acts & (3 << 28)) // state slot next/prev
+       {
+               FILE *st;
+               char *fname;
+
+               CurrentState += (acts & (1 << 29)) ? 1 :  -1;
+               if (CurrentState > 9) CurrentState = 0;
+               if (CurrentState < 0) CurrentState = 9;
+
+               fname = FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0);
+               st=fopen(fname,"rb");
+               free(fname);
+               FCEU_DispMessage("[%s] State Slot %i", st ? "USED" : "FREE", CurrentState);
+               if (st) fclose(st);
+       }
+       else if (acts & (1 << 27)) // FDS insert/eject
+       {
+               if(FCEUGameInfo.type == GIT_FDS)
+                       FCEU_DoSimpleCommand(FCEUNPCMD_FDSINSERT);
+       }
+       else if (acts & (1 << 26)) // FDS select
+       {
+               if(FCEUGameInfo.type == GIT_FDS)
+                       FCEU_DoSimpleCommand(FCEUNPCMD_FDSSELECT);
+       }
+       else if (acts & (1 << 25)) // VS Unisystem insert coin
+       {
+               if(FCEUGameInfo.type == GIT_VSUNI)
+                       FCEU_DoSimpleCommand(FCEUNPCMD_VSUNICOIN);
+       }
+}
 
-char soundvolmeter[21];
-int soundvolIndex=0;
-int L_count=0;
-int R_count=0;
-extern int CurrentState;
-int TurboFireOff=1;
-int TurboFireTop=0;  // 0 is none  // 1 is  A & X turbo  // 2 is Y & B turbo
-int TurboFireBottom=0;
-int turbo_toggle_A=0;
-int turbo_toggle_B=0;
 
-static void setsoundvol(int soundvolume)
-{
-    //FCEUI_SetSoundVolume(soundvol);
-    // draw on screen :D
-    gp2x_sound_volume(soundvolume, soundvolume);
-    int meterval=soundvolume/5;
-    for (soundvolIndex=0; soundvolIndex < 20; soundvolIndex++)
-    {
-       if (soundvolIndex < meterval)
-       {
-                 soundvolmeter[soundvolIndex]='*';
-       }
-       else
-       {
-                 soundvolmeter[soundvolIndex]='_';
-       }
-    }
-    soundvolmeter[20]=0;
-    FCEU_DispMessage("|%s|", soundvolmeter);
-}
-/**
- * GP2x joystick reader
- *
- */
-static INLINE long UpdateGamepadGP2X(void)
+#define down(b) (keys & GP2X_##b)
+static void do_fake_mouse(unsigned long keys)
 {
-  uint32 JS=0;
-
-  unsigned long pad=gp2x_joystick_read();
-#define down(b) (pad & GP2X_##b)
-#define last_down(b) (lastpad & GP2X_##b)
-#define L_down (pad & GP2X_L)
-#define R_down (pad & GP2X_R)
-#define last_L_down (lastpad & GP2X_L)
-#define last_R_down (lastpad & GP2X_R)
-#define shift      ((pad     & GP2X_PUSH) || ((pad     & (GP2X_VOL_UP|GP2X_VOL_DOWN)) == (GP2X_VOL_UP|GP2X_VOL_DOWN)))
-#define last_shift ((lastpad & GP2X_PUSH) || ((lastpad & (GP2X_VOL_UP|GP2X_VOL_DOWN)) == (GP2X_VOL_UP|GP2X_VOL_DOWN)))
-
-  if (L_down && R_down && !(pad & GP2X_PUSH) && !(last_R_down && last_L_down))
-  {
-     ResetNES();
-     puts("Reset");
-     goto no_pad;
-  }
-
-  if (down(VOL_UP) && !down(VOL_DOWN))
-  {
-    soundvol+=1;
-    if (soundvol >= 100) soundvol=100;
-    //FCEUI_SetSoundVolume(soundvol);
-    setsoundvol(soundvol);
-  }
-  else if (down(VOL_DOWN) && !down(VOL_UP))
-  {
-    soundvol-=1;
-    if (soundvol < 0) soundvol=0;
-    //FCEUI_SetSoundVolume(soundvol);
-    setsoundvol(soundvol);
-  }
-
-  if (shift)
-  {
-    // only if it's something else then last time, and not moving around the joystick
-    if (!(pad & (GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT)))
-    {
-      if (down(SELECT))
-      {
-        if (last_down(SELECT) && last_shift)
+       static int x=256/2, y=240/2;
+       int speed = 3;
+
+       if (down(A)) speed = 1;
+       if (down(Y)) speed = 5;
+
+       if (down(LEFT))
        {
-          // still pressed down from stretching from last one
-          goto no_pad;
+               x -= speed;
+               if (x < 0) x = 0;
+       }
+       else if (down(RIGHT))
+       {
+               x += speed;
+               if (x > 255) x = 255;
        }
-        scaled_display = !scaled_display;
 
-        if (scaled_display)
+       if (down(UP))
        {
-         SetVideoScaling(320, 256, 240);
+               y -= speed;
+               if (y < 0) y = 0;
        }
-        else
+       else if (down(DOWN))
        {
-          SetVideoScaling(320, 320, 240);
+               y += speed;
+               if (y > 239) y = 239;
        }
 
-        goto no_pad;
-      }
-      else if (L_down && R_down)
-      {
-        FCEUI_CloseGame();
-        puts("Quit");
-        goto no_pad;
-      }
-      else if (R_down && !(last_R_down && last_shift))
-      {
-       FCEUI_LoadState();
-       goto no_pad;
-      }
-      else if (L_down && !(last_L_down && last_shift))
-      {
-       FCEUI_SaveState();
-       goto no_pad;
-      }
-      else if (down(A) && !(last_down(A) && last_shift))
-      {
-       FSkip_setting--;
-       if (FSkip_setting < 0) {
-        FSkip_setting = -1;
-        FCEUI_DispMessage("Auto frameskip");
-       }
-       else
-        FCEUI_DispMessage("Frameskip: %i", FSkip_setting);
-       goto no_pad;
-      }
-      else if (down(Y) && !(last_down(Y) && last_shift))
-      {
-       FSkip_setting++;
-       if (FSkip_setting > 8) FSkip_setting = 8;
-       FCEUI_DispMessage("Frameskip: %i", FSkip_setting);
-       goto no_pad;
-      }
-    }
-  }
-
-  // r is toggle savestate
-  if (R_down)
-  {
-       if (last_R_down)
-       {
-         R_count++;
-      if ((R_count & 31)== 31)
-      {
-               CurrentState=(CurrentState+1) % 10;
-               FCEUI_DispMessage("Now Using Save State %d", CurrentState);
-         }
-       }
-  }
-  else
-  {
-    R_count=0;
-  }
-
-  // l is toggle turbo
-  if (L_down)
-  {
-       if (last_L_down)
-       {
-         L_count++;
-      if ((L_count & 31)== 31)
-      {
-       // 0 is none  // 1 is  Y & B turbo  // 2 is X & A turbo
-        if ((!TurboFireTop) && (!TurboFireBottom))
-        {
-               // was off
-               TurboFireTop=1;
-               TurboFireBottom=0;
-               if (swapbuttons)
-               {
-                 FCEUI_DispMessage("Turbo A and Y");
-               }
-               else
-               {
-                 FCEUI_DispMessage("Turbo Y and B");
-               }
-        }
-        else if (TurboFireTop)
-        {
-               TurboFireTop=0;
-               TurboFireBottom=1;
-               if (swapbuttons)
-               {
-                         FCEUI_DispMessage("Turbo X and B");
-               }
-               else
-               {
-                         FCEUI_DispMessage("Turbo A and X");
-               }
-        }
-        else
-        {
-               TurboFireTop=0;
-               TurboFireBottom=0;
-               FCEUI_DispMessage("Turbo Off");
-        }
-
-         }
-       }
-  }
-  else
-  {
-    L_count=0;
-  }
-
-  //unsigned long padTmp=0;
-  // shift the bits in
-  // up
-  //padTmp=(pad & GP2X_UP) ;  // 1 is 2^0,
-  JS |= ((pad & GP2X_UP) << (4-0));  // 0x10 is 2^4
-
-  //padTmp=(pad & GP2X_DOWN);  // 0x10 is 2^4,
-  JS |= ((pad & GP2X_DOWN) << (5-4));  // 0x20 is 2^5
-
-  //padTmp=(pad & GP2X_LEFT);  // 0x4 is 2^2,
-  JS |= ((pad & GP2X_LEFT) << (6-2));  // 0x40 is 2^6
-
-  //padTmp=(pad & GP2X_RIGHT);  // 0x40 is 2^6,
-  JS |= ((pad & GP2X_RIGHT) << (7-6));  // 0x80 is 2^7
-
-
-#define  A_down (pad & GP2X_A)
-#define  B_down (pad & GP2X_B)
-#define  X_down (pad & GP2X_X)
-#define  Y_down (pad & GP2X_Y)
-
-  // should be 2 cycles held, 1 cycle release
-  turbo_toggle_A=(turbo_toggle_A+1) % 3;
-  turbo_toggle_B=(turbo_toggle_B+1) % 3;
-
-   // 0 is none  // 1 is  Y & B turbo  // 2 is X & A turbo
-  // B or X are both considered A
-  //padTmp=B_down >> 13;  // 2^13,
-
-   if (!(TurboFireTop && (!turbo_toggle_A)))
-   {
-    JS |= ((B_down >> 13) << 0);  // 0x1 is 2^0
-   }
-   // A or Y are both considered B
-   //padTmp=A_down >> 12;  // 2^13,
-   if (!(TurboFireBottom && (!turbo_toggle_B)))
-   {
-    JS |= ((A_down >> 12) << 1);  // 0x2 is 2^1
-   }
+       MouseData[0] = x;
+       MouseData[1] = y;
+       MouseData[2] = 0;
+       if (down(B)) MouseData[2] |= 1;
+       if (down(X)) MouseData[2] |= 2;
+}
 
-  if (swapbuttons)
-  {
-   //padTmp=X_down >> 14;  // 2^13,
-   if (!(TurboFireBottom && (!turbo_toggle_A)))
-   {
-//    JS |= ((X_down >> 14) << 0);  // 0x1 is 2^0
-    JS |= ((Y_down >> 15) << 0);  // 0x1 is 2^0
-   }
 
-   //padTmp=Y_down >> 15;  // 2^13,
-   if (!(TurboFireTop && (!turbo_toggle_B)))
-   {
-    JS |= ((X_down >> 14) << 1);  // 0x2 is 2^1
-   }
-  }
-  else
-  {
-   //padTmp=X_down >> 14;  // 2^13,
-   if (!(TurboFireBottom && (!turbo_toggle_A)))
-   {
-    JS |= ((X_down >> 14) << 0);  // 0x1 is 2^0
-   }
+void FCEUD_UpdateInput(void)
+{
+       static int volpushed_frames = 0;
+       static int turbo_rate_cnt_a[2] = {0,0}, turbo_rate_cnt_b[2] = {0,0};
+       unsigned long keys = gp2x_joystick_read(0);
+       uint32 all_acts[2] = {0,0};
+       int i;
 
-   //padTmp=Y_down >> 15;  // 2^13,
-   if (!(TurboFireTop && (!turbo_toggle_B)))
-   {
-    JS |= ((Y_down >> 15) << 1);  // 0x2 is 2^1
-   }
-  }
+       if ((down(VOL_DOWN) && down(VOL_UP)) || (keys & (GP2X_L|GP2X_L|GP2X_START)) == (GP2X_L|GP2X_L|GP2X_START))
+       {
+               Exit = 1;
+               return;
+       }
+       else if (down(VOL_UP))
+       {
+               /* wait for at least 10 updates, because user may be just trying to enter menu */
+               if (volpushed_frames++ > 10) {
+                       soundvol++;
+                       if (soundvol > 100) soundvol=100;
+                       //FCEUI_SetSoundVolume(soundvol);
+                       setsoundvol(soundvol);
+               }
+       }
+       else if (down(VOL_DOWN))
+       {
+               if (volpushed_frames++ > 10) {
+                       soundvol-=1;
+                       if (soundvol < 0) soundvol=0;
+                       //FCEUI_SetSoundVolume(soundvol);
+                       setsoundvol(soundvol);
+               }
+       }
+       else
+       {
+               volpushed_frames = 0;
+       }
 
-  // select
-  //padTmp=(pad & GP2X_SELECT) >> 9;  // 0x40 is 2^9,
-  JS |= (((pad & GP2X_SELECT) >> 9) << 2);  // 0x4 is 2^2
+       JSreturn = 0; // RLDU SEBA
 
-  // start
-  //padTmp=(pad & GP2X_START) >> 8;  //   2^8,
-  JS |= (((pad & GP2X_START) >> 8) << 3);  // 0x8 is 2^3
+       if (InputType[1] != SI_GAMEPAD)
+       {
+               /* try to feed fake mouse there */
+               do_fake_mouse(keys);
+       }
 
+       for (i = 0; i < 32; i++)
+       {
+               if (keys & (1 << i))
+               {
+                       uint32 acts, u = 32;
+                       acts = Settings.KeyBinds[i];
+                       if (!acts) continue;
+                       if ((1 << i) & combo_keys)
+                       {
+                               // combo key detected, try to find if other is pressed
+                               for (u = i+1; u < 32; u++)
+                               {
+                                       if ((keys & (1 << u)) && (Settings.KeyBinds[u] & acts))
+                                       {
+                                               keys &= ~(1 << u);
+                                               break;
+                                       }
+                               }
+                       }
+                       if (u != 32) acts &=  combo_acts; // other combo key pressed
+                       else         acts &= ~combo_acts;
+                       all_acts[(acts>>16)&1] |= acts;
+               }
+       }
 
-  JSreturn = JS;
-  lastpad=pad;
+       // add joy inputs
+       if (num_of_joys > 0)
+       {
+               int joy;
+               gp2x_usbjoy_update();
+               for (joy = 0; joy < num_of_joys; joy++) {
+                       int keys = gp2x_usbjoy_check2(joy);
+                       for (i = 0; i < 32; i++) {
+                               if (keys & (1 << i)) {
+                                       int acts = Settings.JoyBinds[joy][i];
+                                       all_acts[(acts>>16)&1] |= acts;
+                               }
+                       }
+               }
+       }
 
-  return pad;
-  //JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
-no_pad:
-  JSreturn=0;
-  lastpad=pad;
-  return 0;
+       // player 1
+       JSreturn |= all_acts[0] & 0xff;
+       if (all_acts[0] & 0x100) {              // A turbo
+               turbo_rate_cnt_a[0] += Settings.turbo_rate_add;
+               JSreturn |= (turbo_rate_cnt_a[0] >> 24) & 1;
+       }
+       if (all_acts[0] & 0x200) {              // B turbo
+               turbo_rate_cnt_b[0] += Settings.turbo_rate_add;
+               JSreturn |= (turbo_rate_cnt_b[0] >> 23) & 2;
+       }
+
+       // player 2
+       JSreturn |= (all_acts[1] & 0xff) << 16;
+       if (all_acts[1] & 0x100) {              // A turbo
+               turbo_rate_cnt_a[1] += Settings.turbo_rate_add;
+               JSreturn |= (turbo_rate_cnt_a[1] >> 8) & 0x10000;
+       }
+       if (all_acts[1] & 0x200) {              // B turbo
+               turbo_rate_cnt_b[1] += Settings.turbo_rate_add;
+               JSreturn |= (turbo_rate_cnt_b[1] >> 7) & 0x20000;
+       }
+
+       do_emu_acts(all_acts[0]|all_acts[1]);
 }
-//#endif
 
 
 static void InitOtherInput(void)
@@ -393,6 +305,9 @@ static void InitOtherInput(void)
    int x;
    int attrib;
 
+   printf("InitOtherInput: InputType[0]: %i, InputType[1]: %i, InputTypeFC: %i\n",
+       InputType[0], InputType[1], InputTypeFC);
+
    for(t=0,x=0;x<2;x++)
    {
     attrib=0;
@@ -422,9 +337,43 @@ static void InitOtherInput(void)
    FCEUI_SetInputFC(InputTypeFC,InputDPtr,attrib);
    FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE);
 
-   if(t && !(inited&16))
-   {
-    InitMouse();
-    inited|=16;
-   }
+   inited|=16;
 }
+
+
+static void PrepareOtherInput(void)
+{
+       uint32 act, key, seen_acts;
+
+       combo_acts = combo_keys = prev_emu_acts = seen_acts = 0;
+
+       // find combo_acts
+       for (act = 1; act; act <<= 1)
+       {
+               for (key = 1; key < 32; key++)
+               {
+                       if (Settings.KeyBinds[key] & act)
+                       {
+                               if (seen_acts & act) combo_acts |= act;
+                               else seen_acts |= act;
+                       }
+               }
+       }
+
+       combo_acts &= ~0x00030000; // don't take player_id bits
+
+       // find combo_keys
+       for (act = 1; act; act <<= 1)
+       {
+               for (key = 0; key < 32; key++)
+               {
+                       if (Settings.KeyBinds[key] & combo_acts)
+                       {
+                               combo_keys |= 1 << key;
+                       }
+               }
+       }
+
+       // printf("generated combo_acts: %08x, combo_keys: %08x\n", combo_acts, combo_keys);
+}
+