${B}main.o: ${B}main.c ${B}main.h ${B}usage.h ${B}input.c
${B}gp2x.o: ${B}gp2x.c ${B}gp2x.h
${B}throttle.o: ${B}throttle.c ${B}main.h ${B}throttle.h
+${B}menu.o: ${B}rev.h
ppu.o: ppu.c ppu.h
-include Makefile.common
+${B}rev.h: FORCE
+ @if [ -f $@ ]; then prevrev=`cat $@`; else prevrev="00"; fi; \
+ if [ "`which svn`" != "" ]; then \
+ rev=`svn update|tail -n 1|sed 's/.*\ \(.*\)\./\1/g'|sed "s/'//g"`; \
+ fi; \
+ if [ "$$rev" = "" ]; then rev="0"; fi; \
+ if [ "$$rev" != "$$prevrev" ]; then \
+ echo "$$rev" > $@; \
+ fi
+
+.PHONY: FORCE
-#x6502.o: x6502.c x6502.h ops.h fce.h sound.h
-# $(CC) $(CFLAGS) -finline-limit=60000 -c $< -o $@
+include Makefile.common
up: fceu
cp -v fceu /mnt/gp2x/mnt/sd/emus/Gpfce_v02/gpfce
#include "minimal.h"
#include "fonts.h"
-extern int showfps;
-
static char fps_str[32];
static int framesEmulated, framesRendered;
//*destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F;
//*destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F;
}
- if (showfps)
+ if (Settings.showfps)
{
int sep;
for (sep=1; sep < 5; sep++)
}
else
{
- if (showfps)
+ if (Settings.showfps)
{
gp2x_text(screen+32, 0, 0, fps_str, FPS_COLOR, 0);
}
//#define SOUND_RATE 44100
#define SOUND_RATE 22050
-#define GP2X_PORT_VERSION "0.4"
DSETTINGS Settings;
CFGSTRUCT DriverConfig[]={
+ ACA(Settings.KeyBinds),
+ ACA(Settings.JoyBinds),
+ AC(Settings.turbo_rate_add),
AC(Settings.sound),
- ACA(Settings.joyBMap),
- ACA(Settings.joyAMap),
- ACA(Settings.joy),
AC(Settings.showfps),
AC(Settings.scaling),
AC(Settings.frameskip),
AC(Settings.cpuclock),
AC(Settings.mmuhack),
AC(Settings.ramtimings),
+ AC(Settings.gamma),
// TODO
ENDCFGSTRUCT
};
static int docheckie[2]={0,0};
#endif
ARGPSTRUCT DriverArgs[]={
- {"-joy1",0,&Settings.joy[0],0},{"-joy2",0,&Settings.joy[1],0},
- {"-joy3",0,&Settings.joy[2],0},{"-joy4",0,&Settings.joy[3],0},
{"-sound",0,&Settings.sound,0},
{"-showfps",0,&Settings.showfps,0},
{"-mmuhack",0,&Settings.mmuhack,0},
Settings.cpuclock = 150;
Settings.frameskip = -1; // auto
Settings.mmuhack = 1;
- Settings.sound=SOUND_RATE;
+ Settings.sound = SOUND_RATE;
+ // default controls, RLDU SEBA
+ Settings.KeyBinds[ 0] = 0x010; // GP2X_UP
+ Settings.KeyBinds[ 4] = 0x020; // GP2X_DOWN
+ Settings.KeyBinds[ 2] = 0x040; // GP2X_LEFT
+ Settings.KeyBinds[ 6] = 0x080; // GP2X_RIGHT
+ Settings.KeyBinds[13] = 0x001; // GP2X_B
+ Settings.KeyBinds[14] = 0x002; // GP2X_X
+ Settings.KeyBinds[15] = 0x100; // GP2X_Y
+ Settings.KeyBinds[12] = 0x200; // GP2X_A
+ Settings.KeyBinds[ 8] = 0x008; // GP2X_START
+ Settings.KeyBinds[ 9] = 0x004; // GP2X_SELECT
}
void DoDriverArgs(void)
{
- int x;
-
#ifdef NETWORK
if(docheckie[0])
netplay=2;
if(netplay)
FCEUI_SetNetworkPlay(netplay);
#endif
-
- for(x=0;x<4;x++)
- if(!Settings.joy[x])
- {
- memset(Settings.joyBMap[x],0,sizeof(Settings.joyBMap[0]));
- memset(Settings.joyAMap[x],0,sizeof(Settings.joyAMap[0]));
- }
}
int InitMouse(void)
return NULL;
}
-extern int swapbuttons; // TODO: rm
+
char **g_argv;
+int mmuhack_status = 0;
// TODO: cleanup
gp2x_init();
cpuctrl_init();
- // unscale the screen, in case this is bad.
- gp2x_video_changemode(8);
- gp2x_video_RGB_setscaling(0, 320, 240);
-
SetDefaults();
ret = CLImain(argc,argv);
// unscale the screen, in case this is bad.
gp2x_video_RGB_setscaling(0, 320, 240);
+ if (mmuhack_status > 0)
+ mmuunhack();
+
cpuctrl_deinit();
gp2x_deinit();
}
-int mmuhack_status = 0;
-
/* optional GP2X stuff to be done after config is loaded */
void gp2x_opt_setup(void)
{
if (Settings.mmuhack) {
int ret = mmuhack();
- printf("squidge hack code finished and returned %i\n", ret); fflush(stdout);
+ printf("squidge hack code finished and returned %s\n", ret > 0 ? "ok" : "fail");
+ fflush(stdout);
mmuhack_status = ret;
}
if (Settings.ramtimings) {
}
}
+void gp2x_cpuclock_update(void)
+{
+ static int prev_cpuclock = 200;
+ if (Settings.cpuclock != 0 && Settings.cpuclock != prev_cpuclock)
+ {
+ set_FCLK(Settings.cpuclock);
+ prev_cpuclock = Settings.cpuclock;
+ }
+}
+
+
+#define GP2X_PORT_VERSION "0.4"
+
typedef struct {
- int sound;
- int joy[4];
- int joyAMap[4][2];
- int joyBMap[4][4];
// gp2x specific
+ int KeyBinds[32];
+ int JoyBinds[4][32];
+ int turbo_rate_add;
+ int sound;
int showfps;
int scaling; // unscaled=0, hw_hor, hw_hor_vert, sw_hor
int frameskip; // -1 ~ auto, >=0 ~ count
int cpuclock;
int mmuhack;
int ramtimings;
+ int gamma;
} DSETTINGS;
extern DSETTINGS Settings;
void gp2x_opt_setup(void);
+void gp2x_cpuclock_update(void);
extern uint8 Exit; // exit emu loop
-extern int swapbuttons;
extern int scaled_display;
-extern int FSkip_setting;
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)
void FCEUD_UpdateInput(void)
{
- 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 volpushed_frames = 0;
+ long lastpad2 = lastpad;
+ unsigned long keys = gp2x_joystick_read(0);
+ uint32 JS = 0; // RLDU SEBA
+ int i;
+
+ #define down(b) (keys & GP2X_##b)
+ if ((down(VOL_DOWN) && down(VOL_UP)) || (keys & (GP2X_L|GP2X_L|GP2X_START)) == (GP2X_L|GP2X_L|GP2X_START))
{
- // still pressed down from stretching from last one
- goto no_pad;
+ Exit = 1;
+ JSreturn = 0;
+ return;
}
- scaled_display = !scaled_display;
-
- if (scaled_display)
+ else if (down(VOL_UP))
{
- gp2x_video_RGB_setscaling(0, 256, 240);
+ /* 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
+ else if (down(VOL_DOWN))
{
- gp2x_video_RGB_setscaling(0, 320, 240);
+ if (volpushed_frames++ > 10) {
+ soundvol-=1;
+ if (soundvol < 0) soundvol=0;
+ //FCEUI_SetSoundVolume(soundvol);
+ setsoundvol(soundvol);
+ }
+ }
+ else
+ {
+ volpushed_frames = 0;
}
- 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
- }
-
- 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
- }
-
- //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
+ for (i = 0; i < 32; i++)
+ {
+ if (keys & (1 << i)) {
+ int acts = Settings.KeyBinds[i];
+ if (!acts) continue;
+ JS |= acts & 0xff;
+ }
+ }
- // start
- //padTmp=(pad & GP2X_START) >> 8; // 2^8,
- JS |= (((pad & GP2X_START) >> 8) << 3); // 0x8 is 2^3
- JSreturn = JS;
- lastpad=pad;
+ JSreturn = JS;
+ lastpad=keys;
- //JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
+ //JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
+#define pad keys
// JSreturn=(JSreturn&0xFF000000)|(JSreturn&0xFF)|((JSreturn&0xFF0000)>>8)|((JSreturn&0xFF00)<<8);
// TODO: make these bindable, use new interface
}
}
return;
-
-no_pad:
- JSreturn=0;
- lastpad=pad;
}
/* 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
*/
-/* This file contains or coordinates all of the code necessary to compile
- on a UNIX system that can use svgalib, such as FreeBSD and Linux.
- This code is not guaranteed to compile on FreeBSD, though.
-*/
-
#include <unistd.h>
#include <sys/types.h>
static int ntsccol=0,ntschue=-1,ntsctint=-1;
int soundvol=70;
int inited=0;
-int swapbuttons=0;
-int showfps=0;
int srendlinev[2]={0,0};
int erendlinev[2]={239,239};
ENDCFGSTRUCT
};
-static void SaveConfig(void)
+void SaveConfig(const char *name)
{
char tdir[2048];
- sprintf(tdir,"%s"PSS"fceu.cfg",BaseDirectory);
+ if (name)
+ sprintf(tdir,"%s"PSS"cfg"PSS"%s.cfg",BaseDirectory,name);
+ else sprintf(tdir,"%s"PSS"fceu2.cfg",BaseDirectory);
DriverInterface(DES_GETNTSCTINT,&ntsctint);
DriverInterface(DES_GETNTSCHUE,&ntschue);
SaveFCEUConfig(tdir,fceuconfig);
}
-static void LoadConfig(void)
+static void LoadConfig(const char *name)
{
char tdir[2048];
- sprintf(tdir,"%s"PSS"fceu.cfg",BaseDirectory);
+ if (name)
+ sprintf(tdir,"%s"PSS"cfg"PSS"%s.cfg",BaseDirectory,name);
+ else sprintf(tdir,"%s"PSS"fceu2.cfg",BaseDirectory);
LoadFCEUConfig(tdir,fceuconfig);
if(ntsctint>=0) DriverInterface(DES_SETNTSCTINT,&ntsctint);
if(ntschue>=0) DriverInterface(DES_SETNTSCHUE,&ntschue);
static void CreateDirs(void)
{
- char *subs[5]={"fcs","snaps","gameinfo","sav","cheats"};
+ char *subs[]={"fcs","snaps","gameinfo","sav","cheats","cfg"};
char tdir[2048];
int x;
mkdir(BaseDirectory,S_IRWXU);
- for(x=0;x<5;x++)
+ for(x=0;x<sizeof(subs)/sizeof(subs[0]);x++)
{
sprintf(tdir,"%s"PSS"%s",BaseDirectory,subs[x]);
mkdir(tdir,S_IRWXU);
{"-nothrottle",0,&eoptions,0x8000|EO_NOTHROTTLE},
{"-slstart",0,&srendlinev[0],0},{"-slend",0,&erendlinev[0],0},
{"-slstartp",0,&srendlinev[1],0},{"-slendp",0,&erendlinev[1],0},
- {"-swapbuttons",&swapbuttons, 0, 0},
- {"-showfps",&showfps, 0, 0},
{0,(void *)DriverArgs,0,0},
{0,0,0,0}
};
return ret;
}
+
#include "usage.h"
int CLImain(int argc, char *argv[])
lastLoadedGameName[0] = 0;
CreateDirs();
- LoadConfig();
- gp2x_opt_setup();
+ LoadConfig(NULL);
last_arg_parsed=DoArgs(argc-1,&argv[1]);
+ gp2x_opt_setup();
+ gp2x_cpuclock_update();
if(cpalette)
LoadCPalette();
if(InitSound())
}
else
{
- lastLoadedGameName[0] = 0;
Exit = 1;
}
fceugi=FCEUI_LoadGame(lastLoadedGameName);
if (fceugi)
{
+ LoadConfig(lastLoadedGameName);
ParseGI(fceugi);
//RefreshThrottleFPS();
InitOtherInput();
FCEUI_Emulate();
}
+ if (fceugi)
+ CloseGame();
+
DriverKill();
return 0;
}
static void DriverKill(void)
{
- SaveConfig();
+ SaveConfig(NULL);
SetSignals(SIG_IGN);
if(inited&2)
extern int NoWaiting;
extern FCEUGI *fceugi;
+
+void SaveConfig(const char *name);
+
#include "fonts.h"\r
#include "gp2x.h"\r
\r
+#include "../../input.h"\r
+#include "../../state.h"\r
+\r
#ifndef _DIRENT_HAVE_D_TYPE\r
#error "need d_type for file browser\r
#endif\r
\r
+static int GP2X_PORT_REV =\r
+#include "rev.h"\r
+;\r
+\r
extern char lastLoadedGameName[PATH_MAX];\r
extern int mmuhack_status;\r
//extern int state_slot; // TODO\r
extern uint8 Exit; // exit emu loop flag\r
\r
+#define CONFIGURABLE_KEYS (GP2X_UP|GP2X_LEFT|GP2X_DOWN|GP2X_RIGHT|GP2X_START|GP2X_SELECT|GP2X_L|GP2X_R|GP2X_A|GP2X_B|GP2X_X|GP2X_Y|GP2X_PUSH)\r
+\r
static char *gp2xKeyNames[] = {\r
"UP", "01???", "LEFT", "03???", "DOWN", "05???", "RIGHT", "07???",\r
"START", "SELECT", "L", "R", "A", "B", "X", "Y",\r
}\r
\r
static char *filter_exts[] = {\r
- // TODO\r
- ".mp3", ".MP3", ".srm", ".brm", "s.gz", ".mds", "bcfg", ".txt", ".htm", "html",\r
- ".jpg", ".gpe", ".cue"\r
+ ".gpe", ".png", "ck.o", ".txt"\r
};\r
\r
static int scandir_filter(const struct dirent *ent)\r
if(inp & GP2X_X) return 1;\r
}\r
}\r
+#endif\r
\r
// -------------- key config --------------\r
\r
return name;\r
}\r
\r
-static void draw_key_config(int curr_act, int is_p2)\r
+static char *action_binds(int player_idx, int action_mask)\r
{\r
- char strkeys[32*5];\r
+ static char strkeys[32*5];\r
int joy, i;\r
\r
strkeys[0] = 0;\r
- for (i = 0; i < 32; i++)\r
+ for (i = 0; i < 32; i++) // i is key index\r
{\r
- if (currentConfig.KeyBinds[i] & (1 << curr_act))\r
+ if (Settings.KeyBinds[i] & action_mask)\r
{\r
- if (curr_act < 16 && (currentConfig.KeyBinds[i] & (1 << 16)) != (is_p2 << 16)) continue;\r
+ if (player_idx >= 0 && ((Settings.KeyBinds[i] >> 16) & 3) != player_idx) continue;\r
if (strkeys[0]) { strcat(strkeys, " + "); strcat(strkeys, gp2xKeyNames[i]); break; }\r
else strcpy(strkeys, gp2xKeyNames[i]);\r
}\r
{\r
for (i = 0; i < 32; i++)\r
{\r
- if (currentConfig.JoyBinds[joy][i] & (1 << curr_act))\r
+ if (Settings.JoyBinds[joy][i] & action_mask)\r
{\r
- if (curr_act < 16 && (currentConfig.JoyBinds[joy][i] & (1 << 16)) != (is_p2 << 16)) continue;\r
+ if (player_idx >= 0 && ((Settings.KeyBinds[i] >> 16) & 3) != player_idx) continue;\r
if (strkeys[0]) {\r
strcat(strkeys, ", "); strcat(strkeys, usb_joy_key_name(joy + 1, i));\r
break;\r
}\r
}\r
\r
- //memset(gp2x_screen, 0, 320*240);\r
+ return strkeys;\r
+}\r
+\r
+static void unbind_action(int action)\r
+{\r
+ int i, u;\r
+\r
+ for (i = 0; i < 32; i++)\r
+ Settings.KeyBinds[i] &= ~action;\r
+ for (u = 0; u < 4; u++)\r
+ for (i = 0; i < 32; i++)\r
+ Settings.JoyBinds[u][i] &= ~action;\r
+}\r
+\r
+static int count_bound_keys(int action, int is_joy)\r
+{\r
+ int i, u, keys = 0;\r
+\r
+ if (is_joy)\r
+ {\r
+ for (u = 0; u < 4; u++)\r
+ for (i = 0; i < 32; i++)\r
+ if (Settings.JoyBinds[u][i] & action) keys++;\r
+ }\r
+ else\r
+ {\r
+ for (i = 0; i < 32; i++)\r
+ if (Settings.KeyBinds[i] & action) keys++;\r
+ }\r
+ return keys;\r
+}\r
+\r
+typedef struct { char *name; int mask; } bind_action_t;\r
+\r
+// b_turbo,a_turbo RLDU SEBA\r
+static bind_action_t ctrl_actions[] =\r
+{\r
+ { "UP ", 0x010 },\r
+ { "DOWN ", 0x020 },\r
+ { "LEFT ", 0x040 },\r
+ { "RIGHT ", 0x080 },\r
+ { "A ", 0x001 },\r
+ { "B ", 0x002 },\r
+ { "A TURBO", 0x100 },\r
+ { "B TURBO", 0x200 },\r
+ { "START ", 0x008 },\r
+ { "SELECT ", 0x004 },\r
+};\r
+\r
+static void draw_key_config(const bind_action_t *opts, int opt_cnt, int player_idx, int sel)\r
+{\r
+ int x, y, tl_y = 40, i;\r
+\r
gp2x_fceu_copy_bg();\r
- gp2x_text_out15(60, 40, "Action: %s", actionNames[curr_act]);\r
- gp2x_text_out15(60, 60, "Keys: %s", strkeys);\r
+ gp2x_text_out15(80, 20, "Player %i controls", player_idx + 1);\r
+\r
+ x = 40; y = tl_y;\r
+ for (i = 0; i < opt_cnt; i++, y+=10)\r
+ gp2x_text_out15(x, y, "%s : %s", opts[i].name, action_binds(player_idx, opts[i].mask));\r
+\r
+ gp2x_text_out15(x, y, "Done");\r
+\r
+ // draw cursor\r
+ gp2x_text_out15(x - 16, tl_y + sel*10, ">");\r
\r
- gp2x_text_out15(30, 180, "Use SELECT to change action");\r
- gp2x_text_out15(30, 190, "Press a key to bind/unbind");\r
- gp2x_text_out15(30, 200, "Select \"Done\" action and");\r
- gp2x_text_out15(30, 210, " press any key to finish");\r
+ if (sel < 10) {\r
+ gp2x_text_out15(30, 190, "Press a button to bind/unbind");\r
+ gp2x_text_out15(30, 200, "Use VOL+ to clear");\r
+ gp2x_text_out15(30, 210, "To bind UP/DOWN, hold VOL-");\r
+ gp2x_text_out15(30, 220, "Select \"Done\" to exit");\r
+ } else {\r
+ gp2x_text_out15(30, 220, "Press B or X to exit");\r
+ }\r
gp2x_video_flip();\r
}\r
\r
-static void key_config_loop(int is_p2)\r
+static void key_config_loop(const bind_action_t *opts, int opt_cnt, int player_idx)\r
{\r
- int curr_act = 0, joy = 0, i;\r
+ int joy = 0, sel = 0, menu_sel_max = opt_cnt, i;\r
unsigned long inp = 0;\r
\r
for (;;)\r
{\r
- draw_key_config(curr_act, is_p2);\r
- inp = wait_for_input_usbjoy(CONFIGURABLE_KEYS, &joy);\r
+ draw_key_config(opts, opt_cnt, player_idx, sel);\r
+ inp = wait_for_input_usbjoy(CONFIGURABLE_KEYS|GP2X_VOL_DOWN|GP2X_VOL_UP, &joy);\r
// printf("got %08lX from joy %i\n", inp, joy);\r
if (joy == 0) {\r
- if (inp & GP2X_SELECT) {\r
- curr_act++;\r
- while (!actionNames[curr_act] && curr_act < 32) curr_act++;\r
- if (curr_act > 31) curr_act = 0;\r
+ if (!(inp & GP2X_VOL_DOWN)) {\r
+ if(inp & GP2X_UP ) { sel--; if (sel < 0) sel = menu_sel_max; continue; }\r
+ if(inp & GP2X_DOWN) { sel++; if (sel > menu_sel_max) sel = 0; continue; }\r
+ }\r
+ if (sel >= opt_cnt) {\r
+ if (inp & (GP2X_B|GP2X_X)) break;\r
+ else continue;\r
}\r
+ // if we are here, we want to bind/unbind something\r
+ if (inp & GP2X_VOL_UP)\r
+ unbind_action(opts[sel].mask);\r
inp &= CONFIGURABLE_KEYS;\r
- inp &= ~GP2X_SELECT;\r
- }\r
- if (curr_act == 31 && inp) break;\r
- if (joy == 0) {\r
for (i = 0; i < 32; i++)\r
if (inp & (1 << i)) {\r
- currentConfig.KeyBinds[i] ^= (1 << curr_act);\r
- if (is_p2) currentConfig.KeyBinds[i] |= (1 << 16); // player 2 flag\r
- else currentConfig.KeyBinds[i] &= ~(1 << 16);\r
+ if (count_bound_keys(opts[sel].mask, 0) >= 2)\r
+ Settings.KeyBinds[i] &= ~opts[sel].mask; // allow to unbind only\r
+ else Settings.KeyBinds[i] ^= opts[sel].mask;\r
+ Settings.KeyBinds[i] &= ~(3 << 16);\r
+ Settings.KeyBinds[i] |= player_idx << 16;\r
}\r
- } else {\r
+ } else if (sel < opt_cnt) {\r
for (i = 0; i < 32; i++)\r
if (inp & (1 << i)) {\r
- currentConfig.JoyBinds[joy-1][i] ^= (1 << curr_act);\r
- if (is_p2) currentConfig.JoyBinds[joy-1][i] |= (1 << 16);\r
- else currentConfig.JoyBinds[joy-1][i] &= ~(1 << 16);\r
+ if (count_bound_keys(opts[sel].mask, 1) >= 1) // disallow combos for usbjoy\r
+ Settings.JoyBinds[joy-1][i] &= ~opts[sel].mask;\r
+ else Settings.JoyBinds[joy-1][i] ^= opts[sel].mask;\r
+ Settings.JoyBinds[joy-1][i] &= ~(3 << 16);\r
+ Settings.JoyBinds[joy-1][i] |= player_idx << 16;\r
}\r
}\r
}\r
char joyname[36];\r
\r
y = tl_y;\r
- //memset(gp2x_screen, 0, 320*240);\r
gp2x_fceu_copy_bg();\r
gp2x_text_out15(tl_x, y, "Player 1");\r
gp2x_text_out15(tl_x, (y+=10), "Player 2");\r
+ gp2x_text_out15(tl_x, (y+=10), "Emulator controls");\r
gp2x_text_out15(tl_x, (y+=10), "Done");\r
\r
// draw cursor\r
gp2x_text_out15(tl_x, (y+=10), "none");\r
}\r
\r
-\r
gp2x_video_flip();\r
}\r
\r
static void kc_sel_loop(void)\r
{\r
- int menu_sel = 2, menu_sel_max = 2;\r
+ int menu_sel = 3, menu_sel_max = 3;\r
unsigned long inp = 0;\r
\r
for(;;)\r
if(inp & GP2X_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; }\r
if(inp & GP2X_B) {\r
switch (menu_sel) {\r
- case 0: key_config_loop(0); return;\r
- case 1: key_config_loop(1); return;\r
+ case 0: key_config_loop(ctrl_actions, 10, 0); return;\r
+ case 1: key_config_loop(ctrl_actions, 8, 1); return;\r
default: return;\r
}\r
}\r
if(inp & GP2X_X) return;\r
}\r
}\r
-#endif\r
\r
\r
\r
static void draw_menu_options(int menu_sel)\r
{\r
int tl_x = 25, tl_y = 32, y;\r
- char monostereo[8], strframeskip[8], *strscaling, *strssconfirm;\r
+ char /*monostereo[8],*/ strframeskip[8], *strscaling, *strssconfirm;\r
\r
//strcpy(monostereo, (currentConfig.PicoOpt&0x08)?"stereo":"mono");\r
if (Settings.frameskip < 0)\r
//memset(gp2x_screen, 0, 320*240);\r
gp2x_fceu_copy_bg();\r
\r
- gp2x_text_out15(tl_x, (y+=10), "Scaling: %s", strscaling); // 0\r
+ gp2x_text_out15(tl_x, y, "Scaling: %s", strscaling); // 0\r
gp2x_text_out15(tl_x, (y+=10), "Show FPS %s", Settings.showfps?"ON":"OFF"); // 1\r
gp2x_text_out15(tl_x, (y+=10), "Frameskip %s", strframeskip); // 2\r
gp2x_text_out15(tl_x, (y+=10), "Enable sound %s", /*(currentConfig.EmuOpt &0x004)?"ON":*/"OFF"); // 3\r
gp2x_text_out15(tl_x, (y+=10), "Sound Quality: %5iHz %s", 0, "" /*currentConfig.PsndRate, monostereo*/); // 4\r
- gp2x_text_out15(tl_x, (y+=10), "Region: %s",\r
+ gp2x_text_out15(tl_x, (y+=10), "Region: %s",\r
Settings.region_force == 2 ? "NTSC" : Settings.region_force == 1 ? "PAL" : "OFF"); // 5\r
gp2x_text_out15(tl_x, (y+=10), "Use SRAM savestates %s", "OFF");\r
gp2x_text_out15(tl_x, (y+=10), "Confirm savestate %s", strssconfirm);\r
switch (menu_sel) {\r
case 1: Settings.showfps = !Settings.showfps; break;\r
//case 6: Settings. = !Settings.showfps; break;\r
- //case 16: amenu_loop_options(); break;\r
- case 17: // done (update and write)\r
- //if (emu_WriteConfig(0)) strcpy(menuErrorMsg, "config saved");\r
- //else strcpy(menuErrorMsg, "failed to write config");\r
+ //case 10: amenu_loop_options(); break;\r
+ case 11: // done (update and write)\r
+ gp2x_cpuclock_update();\r
+ SaveConfig(NULL);\r
return 1;\r
- case 18: // done (update and write for current game)\r
- //if (emu_WriteConfig(1)) strcpy(menuErrorMsg, "config saved");\r
- //else strcpy(menuErrorMsg, "failed to write config");\r
+ case 12: // done (update and write for current game)\r
+ gp2x_cpuclock_update();\r
+ if (lastLoadedGameName[0])\r
+ SaveConfig(lastLoadedGameName);\r
return 1;\r
}\r
}\r
if(inp & (GP2X_X|GP2X_A)) {\r
+ gp2x_cpuclock_update();\r
return 0; // done (update, no write)\r
}\r
if(inp & (GP2X_LEFT|GP2X_RIGHT)) { // multi choise\r
*/\r
case 5: int_incdec(&Settings.region_force, (inp & GP2X_LEFT) ? -1 : 1, 0, 2); break;\r
case 7: int_incdec(&Settings.sstate_confirm, (inp & GP2X_LEFT) ? -1 : 1, 0, 3); break;\r
- //case 8: int_incdec(&Settings., (inp & GP2X_LEFT) ? -1 : 1, 0, 9); break;\r
- case 14:\r
+ case 8: int_incdec(&CurrentState, (inp & GP2X_LEFT) ? -1 : 1, 0, 9); break;\r
+ case 9:\r
while ((inp = gp2x_joystick_read(1)) & (GP2X_LEFT|GP2X_RIGHT)) {\r
Settings.cpuclock += (inp & GP2X_LEFT) ? -1 : 1;\r
- if (Settings.cpuclock < 1) Settings.cpuclock = 1;\r
+ if (Settings.cpuclock < 0) Settings.cpuclock = 0; // 0 ~ do not change\r
draw_menu_options(menu_sel);\r
usleep(50*1000);\r
}\r
\r
static void draw_menu_credits(void)\r
{\r
- int tl_x = 15, tl_y = 70, y;\r
- //memset(gp2x_screen, 0, 320*240);\r
+ //int tl_x = 15, tl_y = 70;\r
gp2x_fceu_copy_bg();\r
\r
// TODO\r
\r
static void draw_menu_root(int menu_sel)\r
{\r
- int tl_x = 70, tl_y = 70, y;\r
+ int tl_x = 30, tl_y = 128, y;\r
gp2x_fceu_copy_bg();\r
\r
y = tl_y;\r
y += 30;\r
}\r
gp2x_text_out15(tl_x, (y+=10), "Load new ROM");\r
- gp2x_text_out15(tl_x, (y+=10), "Change options");\r
- gp2x_text_out15(tl_x, (y+=10), "Configure controls");\r
+ gp2x_text_out15(tl_x, (y+=10), "Options");\r
+ gp2x_text_out15(tl_x, (y+=10), "Controls");\r
gp2x_text_out15(tl_x, (y+=10), "Credits");\r
gp2x_text_out15(tl_x, (y+=10), "Exit");\r
// TODO\r
// draw cursor\r
gp2x_text_out15(tl_x - 16, tl_y + menu_sel*10, ">");\r
// error\r
- if (menuErrorMsg[0]) gp2x_text_out15(5, 226, menuErrorMsg);\r
+ if (menuErrorMsg[0]) gp2x_text_out15(1, 230, menuErrorMsg);\r
+ else {\r
+ char vstr[16];\r
+ sprintf(vstr, "v" GP2X_PORT_VERSION " r%i", GP2X_PORT_REV);\r
+ gp2x_text_out15(320-strlen(vstr)*8-1, 230, vstr);\r
+ }\r
gp2x_video_flip();\r
}\r
\r
\r
static int menu_loop_root(void)\r
{\r
- int ret, menu_sel = 4, menu_sel_max = 8, menu_sel_min = 4;\r
+ int ret, menu_sel_max = 8, menu_sel_min = 4;\r
+ static int menu_sel = 4;\r
unsigned long inp = 0;\r
char curr_path[PATH_MAX], *selfname;\r
FILE *tstf;\r
getcwd(curr_path, PATH_MAX);\r
}\r
\r
- if (fceugi) menu_sel = menu_sel_min = 0;\r
+ if (fceugi) menu_sel_min = 0;\r
// TODO if (PicoPatches) menu_sel_max = 9;\r
+ if (menu_sel < menu_sel_min || menu_sel > menu_sel_max)\r
+ menu_sel = menu_sel_min;\r
\r
/* make sure action buttons are not pressed on entering menu */\r
draw_menu_root(menu_sel);\r
if (fceugi) {\r
/*if(savestate_menu_loop(0))\r
continue;*/\r
+ FCEUI_SaveState();\r
return 0;\r
}\r
break;\r
if (fceugi) {\r
/*if(savestate_menu_loop(1))\r
continue;*/\r
+ FCEUI_LoadState();\r
return 0;\r
}\r
break;\r
case 3: // reset game\r
if (fceugi) {\r
+ FCEU_DoSimpleCommand(FCEUNPCMD_RESET);\r
+ Exit = 0;\r
return 0;\r
}\r
break;\r
if (ret == 1) continue; // status update\r
break;\r
case 6: // controls\r
- // TODO kc_sel_loop();\r
+ kc_sel_loop();\r
break;\r
case 7: // credits\r
draw_menu_credits();\r
int mmuhack(void)
{
char kocmd[1024];
- int i, mmufd = open("/dev/mmuhack", O_RDWR);
-
- if(mmufd < 0) {
- strcpy(kocmd, "/sbin/insmod ");
- strncpy(kocmd+13, g_argv[0], 1023-13);
- kocmd[1023] = 0;
- for (i = strlen(kocmd); i > 0; i--)
- if (kocmd[i] == '/') { kocmd[i] = 0; break; }
- strcat(kocmd, "/mmuhack.o");
-
- printf("Installing NK's kernel module for Squidge MMU Hack (%s)...\n", kocmd);
- system(kocmd);
- mmufd = open("/dev/mmuhack", O_RDWR);
- }
+ int i, mmufd;
+
+ /* some programs like some versions of gpSP use some weird version of mmuhack.o
+ * which doesn't seem to work. What's even worse they leave their mmuhack loaded on exit.
+ * So we must remove whatever may be left and always reload _our_ mmuhack.o */
+ system("/sbin/rmmod mmuhack");
+
+ strcpy(kocmd, "/sbin/insmod ");
+ strncpy(kocmd+13, g_argv[0], 1023-13);
+ kocmd[1023] = 0;
+ for (i = strlen(kocmd); i > 0; i--)
+ if (kocmd[i] == '/') { kocmd[i] = 0; break; }
+ strcat(kocmd, "/mmuhack.o");
+
+ printf("Installing NK's kernel module for Squidge MMU Hack (%s)...\n", kocmd);
+ system(kocmd);
+ mmufd = open("/dev/mmuhack", O_RDWR);
if(mmufd < 0) return 0;
-
+
close(mmufd);
return 1;
-}
+}
/* Unload MMU Hack kernel module after closing all memory devices*/
}
#ifdef FRAMESKIP
-int FSkip_setting=-1; // auto
int FSkip=0;
void FCEUI_FrameSkip(int x)
{
SetInputStuffFC();
}
-// quick paste
-#define FCEUNPCMD_RESET 0x01
-#define FCEUNPCMD_POWER 0x02
-
-#define FCEUNPCMD_VSUNICOIN 0x07
-#define FCEUNPCMD_VSUNIDIP0 0x08
-#define FCEUNPCMD_FDSINSERT 0x18
-#define FCEUNPCMD_FDSSELECT 0x1A
-
-
void FCEU_DoSimpleCommand(int cmd)
{
switch(cmd)
extern void (*PStrobe[2])(void);
extern void (*InputScanlineHook)(uint8 *buf, int line);
+#define FCEUNPCMD_RESET 0x01
+#define FCEUNPCMD_POWER 0x02
+
+#define FCEUNPCMD_VSUNICOIN 0x07
+#define FCEUNPCMD_VSUNIDIP0 0x08
+#define FCEUNPCMD_FDSINSERT 0x18
+#define FCEUNPCMD_FDSSELECT 0x1A
void FCEU_DoSimpleCommand(int cmd);
void FCEUI_FDSSelect(void);