/* 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 uint8 Exit; // exit emu loop
-
-extern int swapbuttons;
-extern int scaled_display;
-extern int FSkip_setting;
-
+#include "../../state.h"
+#include "../../general.h"
+#include "../../input.h"
+#include "../../svga.h"
+#include "../../video.h"
+#include "usbjoy.h"
+extern int FSkip;
/* 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;
-
-extern void ResetNES(void);
-extern void CleanSurface(void);
-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 uint32 combo_acts = 0, combo_keys = 0;
+static uint32 prev_emu_acts = 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);
+ 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);
}
+static void do_emu_acts(uint32 acts)
+{
+ uint32 actsc = acts;
+ acts &= acts ^ prev_emu_acts;
+ prev_emu_acts = actsc;
+
+ 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_CancelDispMessage();
+ }
+ 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_CancelDispMessage();
+ }
+ }
+ 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);
+ }
+}
+
-void FCEUD_UpdateInput(void)
+#define down(b) (keys & GP2X_##b)
+static void do_fake_mouse(unsigned long keys)
{
- long lastpad2=lastpad;
- unsigned long pad=gp2x_joystick_read(1); // TODO: USB joys and stuff
- uint32 JS=0;
-
-#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);
- }
- else if (down(VOL_DOWN) && down(VOL_UP))
- {
- Exit = 1;
- }
-
- 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))
+ {
+ x -= speed;
+ if (x < 0) x = 0;
+ }
+ else if (down(RIGHT))
{
- // still pressed down from stretching from last one
- goto no_pad;
+ x += speed;
+ if (x > 255) x = 255;
}
- scaled_display = !scaled_display;
- if (scaled_display)
+ if (down(UP))
{
- gp2x_video_RGB_setscaling(0, 256, 240);
+ y -= speed;
+ if (y < 0) y = 0;
}
- else
+ else if (down(DOWN))
{
- gp2x_video_RGB_setscaling(0, 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
- }
+static 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
- }
- }
-
- // select
- //padTmp=(pad & GP2X_SELECT) >> 9; // 0x40 is 2^9,
- JS |= (((pad & GP2X_SELECT) >> 9) << 2); // 0x4 is 2^2
-
- // start
- //padTmp=(pad & GP2X_START) >> 8; // 2^8,
- JS |= (((pad & GP2X_START) >> 8) << 3); // 0x8 is 2^3
-
- JSreturn = JS;
- lastpad=pad;
-
- //JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
-
-
- // JSreturn=(JSreturn&0xFF000000)|(JSreturn&0xFF)|((JSreturn&0xFF0000)>>8)|((JSreturn&0xFF00)<<8);
- // TODO: make these bindable, use new interface
- 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);
- }
- }
- return;
-
-no_pad:
- JSreturn=0;
- lastpad=pad;
+ if ((down(VOL_DOWN) && down(VOL_UP)) || (keys & (GP2X_L|GP2X_L|GP2X_START)) == (GP2X_L|GP2X_L|GP2X_START))
+ {
+ Exit = 1;
+ FSkip = 0; /* force rendering the last frame for menu */
+ 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;
+ }
+
+ JSreturn = 0; // RLDU SEBA
+
+ 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;
+ }
+ }
+
+ // 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;
+ }
+ }
+ }
+ }
+
+ // 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]);
}
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;
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);
+}
+