From: notaz <notasas@gmail.com>
Date: Sun, 19 Aug 2007 20:46:49 +0000 (+0000)
Subject: newstyle key config, code940.bin -> pico940.bin
X-Git-Tag: v1.85~694
X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d524c827cd65b50aa2f72099d9ac24f4efa7aeef;p=picodrive.git

newstyle key config, code940.bin -> pico940.bin

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@222 be3aeb3a-fb24-0410-a615-afba39da0efa
---

diff --git a/platform/gp2x/940ctl.c b/platform/gp2x/940ctl.c
index 8b3c7fe6..54b83b69 100644
--- a/platform/gp2x/940ctl.c
+++ b/platform/gp2x/940ctl.c
@@ -30,6 +30,7 @@ _940_ctl_t *shared_ctl = 0;
 unsigned char *mp3_mem = 0;
 
 #define MP3_SIZE_MAX (0x400000 + 0x800000) // 12M
+#define CODE940_FILE "pico940.bin"
 
 int crashed_940 = 0;
 
@@ -409,14 +410,14 @@ void YM2612Init_940(int baseclock, int rate)
 		binpath[1023] = 0;
 		for (i = strlen(binpath); i > 0; i--)
 			if (binpath[i] == '/') { binpath[i] = 0; break; }
-		strcat(binpath, "/code940.bin");
+		strcat(binpath, "/" CODE940_FILE);
 
 		fp = fopen(binpath, "rb");
 		if(!fp)
 		{
 			memset(gp2x_screen, 0, 320*240);
 			gp2x_text_out8(10, 100, "failed to open required file:");
-			gp2x_text_out8(10, 110, "code940.bin");
+			gp2x_text_out8(10, 110, CODE940_FILE);
 			gp2x_video_flip();
 			printf("failed to open %s\n", binpath);
 			exit(1);
diff --git a/platform/gp2x/code940/Makefile b/platform/gp2x/code940/Makefile
index 57892751..a344e022 100644
--- a/platform/gp2x/code940/Makefile
+++ b/platform/gp2x/code940/Makefile
@@ -18,7 +18,9 @@ AS = $(CROSS)as
 LD = $(CROSS)ld
 OBJCOPY = $(CROSS)objcopy
 
-all: code940.bin
+BIN = pico940.bin
+
+all: $(BIN)
 
 
 .c.o:
@@ -41,7 +43,7 @@ OBJS940 += uClibc/memset.o uClibc/s_floor.o uClibc/e_pow.o uClibc/e_sqrt.o uClib
 OBJS940 += uClibc/s_scalbn.o uClibc/s_copysign.o uClibc/k_sin.o uClibc/k_cos.o uClibc/s_sin.o
 OBJS940 += uClibc/e_rem_pio2.o uClibc/k_rem_pio2.o uClibc/e_log.o uClibc/wrappers.o
 
-code940.bin : code940.gpe
+$(BIN) : code940.gpe
 	@echo $@
 	@$(OBJCOPY) -O binary $< $@
 
@@ -64,8 +66,8 @@ misc.o : ../../../Pico/misc.s
 	@make -C ../helix/
 
 
-up: code940.bin
-	@cp -v code940.bin /mnt/gp2x/mnt/sd/emus/PicoDrive/
+up: $(BIN)
+	@cp -v $< /mnt/gp2x/mnt/sd/emus/PicoDrive/
 
 
 # cleanup
diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c
index 27e9d13d..cb924c34 100644
--- a/platform/gp2x/emu.c
+++ b/platform/gp2x/emu.c
@@ -32,14 +32,6 @@
 #define OSD_FPS_X 260
 #endif
 
-// PicoPad[] format: SACB RLDU
-char *actionNames[] = {
-	"UP", "DOWN", "LEFT", "RIGHT", "B", "C", "A", "START",
-	0, 0, 0, 0, 0, 0, 0, 0, // Z, Y, X, MODE (enabled only when needed), ?, ?, ?, ?
-	0, 0, 0, 0, 0, 0, 0, "ENTER MENU", // player2_flag, ?, ?, ?, ?, ?, ?, menu
-	"NEXT SAVE SLOT", "PREV SAVE SLOT", "SWITCH RENDERER", "SAVE STATE",
-	"LOAD STATE", "VOLUME UP", "VOLUME DOWN", "DONE"
-};
 
 int engineState;
 int select_exits = 0;
@@ -319,9 +311,9 @@ int emu_ReloadRom(void)
 	}
 
 	// load config for this ROM (do this before insert to get correct region)
-	ret = emu_ReadConfig(1);
+	ret = emu_ReadConfig(1, 1);
 	if (!ret)
-		emu_ReadConfig(0);
+		emu_ReadConfig(0, 1);
 
 	printf("PicoCartInsert(%p, %d);\n", rom_data, rom_size);
 	if(PicoCartInsert(rom_data, rom_size)) {
@@ -472,7 +464,7 @@ void scaling_update(void)
 }
 
 
-int emu_ReadConfig(int game)
+int emu_ReadConfig(int game, int no_defaults)
 {
 	FILE *f;
 	char cfg[512], extbuf[16];
@@ -480,33 +472,36 @@ int emu_ReadConfig(int game)
 
 	if (!game)
 	{
-		// set default config
-		memset(&currentConfig, 0, sizeof(currentConfig));
-		currentConfig.lastRomFile[0] = 0;
-		currentConfig.EmuOpt  = 0x1f | 0x600; // | confirm_save, cd_leds
-		currentConfig.PicoOpt = 0x0f | 0xe00; // | use_940, cd_pcm, cd_cdda
-		currentConfig.PsndRate = 22050; // 44100;
-		currentConfig.PicoRegion = 0; // auto
-		currentConfig.PicoAutoRgnOrder = 0x184; // US, EU, JP
-		currentConfig.Frameskip = -1; // auto
-		currentConfig.CPUclock = 200;
-		currentConfig.volume = 50;
-		currentConfig.KeyBinds[ 0] = 1<<0; // SACB RLDU
-		currentConfig.KeyBinds[ 4] = 1<<1;
-		currentConfig.KeyBinds[ 2] = 1<<2;
-		currentConfig.KeyBinds[ 6] = 1<<3;
-		currentConfig.KeyBinds[14] = 1<<4;
-		currentConfig.KeyBinds[13] = 1<<5;
-		currentConfig.KeyBinds[12] = 1<<6;
-		currentConfig.KeyBinds[ 8] = 1<<7;
-		currentConfig.KeyBinds[15] = 1<<26; // switch rend
-		currentConfig.KeyBinds[10] = 1<<27; // save state
-		currentConfig.KeyBinds[11] = 1<<28; // load state
-		currentConfig.KeyBinds[23] = 1<<29; // vol up
-		currentConfig.KeyBinds[22] = 1<<30; // vol down
-		currentConfig.gamma = 100;
-		currentConfig.PicoCDBuffers = 64;
-		currentConfig.scaling = 0;
+		if (!no_defaults)
+		{
+			// set default config
+			memset(&currentConfig, 0, sizeof(currentConfig));
+			currentConfig.lastRomFile[0] = 0;
+			currentConfig.EmuOpt  = 0x1f | 0x600; // | confirm_save, cd_leds
+			currentConfig.PicoOpt = 0x0f | 0xe00; // | use_940, cd_pcm, cd_cdda
+			currentConfig.PsndRate = 22050; // 44100;
+			currentConfig.PicoRegion = 0; // auto
+			currentConfig.PicoAutoRgnOrder = 0x184; // US, EU, JP
+			currentConfig.Frameskip = -1; // auto
+			currentConfig.CPUclock = 200;
+			currentConfig.volume = 50;
+			currentConfig.KeyBinds[ 0] = 1<<0; // SACB RLDU
+			currentConfig.KeyBinds[ 4] = 1<<1;
+			currentConfig.KeyBinds[ 2] = 1<<2;
+			currentConfig.KeyBinds[ 6] = 1<<3;
+			currentConfig.KeyBinds[14] = 1<<4;
+			currentConfig.KeyBinds[13] = 1<<5;
+			currentConfig.KeyBinds[12] = 1<<6;
+			currentConfig.KeyBinds[ 8] = 1<<7;
+			currentConfig.KeyBinds[15] = 1<<26; // switch rend
+			currentConfig.KeyBinds[10] = 1<<27; // save state
+			currentConfig.KeyBinds[11] = 1<<28; // load state
+			currentConfig.KeyBinds[23] = 1<<29; // vol up
+			currentConfig.KeyBinds[22] = 1<<30; // vol down
+			currentConfig.gamma = 100;
+			currentConfig.PicoCDBuffers = 64;
+			currentConfig.scaling = 0;
+		}
 		strncpy(cfg, PicoConfigFile, 511);
 		if (config_slot != 0)
 		{
@@ -539,10 +534,6 @@ int emu_ReadConfig(int game)
 	PicoRegionOverride = currentConfig.PicoRegion;
 	PicoAutoRgnOrder = currentConfig.PicoAutoRgnOrder;
 	PicoCDBuffers = currentConfig.PicoCDBuffers;
-	if (PicoOpt & 0x20) {
-		actionNames[ 8] = "Z"; actionNames[ 9] = "Y";
-		actionNames[10] = "X"; actionNames[11] = "MODE";
-	}
 	scaling_update();
 	// some sanity checks
 	if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200;
diff --git a/platform/gp2x/emu.h b/platform/gp2x/emu.h
index 17e855be..55bb53e7 100644
--- a/platform/gp2x/emu.h
+++ b/platform/gp2x/emu.h
@@ -47,7 +47,7 @@ void emu_Deinit(void);
 int  emu_SaveLoadGame(int load, int sram);
 void emu_Loop(void);
 void emu_ResetGame(void);
-int  emu_ReadConfig(int game);
+int  emu_ReadConfig(int game, int no_defaults);
 int  emu_WriteConfig(int game);
 char *emu_GetSaveFName(int load, int is_sram, int slot);
 int  emu_check_save_file(int slot);
diff --git a/platform/gp2x/main.c b/platform/gp2x/main.c
index 4d8317e8..d6438f6f 100644
--- a/platform/gp2x/main.c
+++ b/platform/gp2x/main.c
@@ -79,7 +79,7 @@ int main(int argc, char *argv[])
 {
 	g_argv = argv;
 
-	emu_ReadConfig(0);
+	emu_ReadConfig(0, 0);
 	gp2x_init();
 	if (currentConfig.EmuOpt&0x10) {
 		int ret = mmuhack();
diff --git a/platform/gp2x/menu.c b/platform/gp2x/menu.c
index 8de891b3..9b51d7c0 100644
--- a/platform/gp2x/menu.c
+++ b/platform/gp2x/menu.c
@@ -1,4 +1,4 @@
-// (c) Copyright 2006 notaz, All rights reserved.
+// (c) Copyright 2006,2007 notaz, All rights reserved.
 // Free for non-commercial use.
 
 // For commercial use, separate licencing terms must be obtained.
@@ -26,7 +26,6 @@
 #error "need d_type for file browser
 #endif
 
-extern char *actionNames[];
 extern char romFileName[PATH_MAX];
 extern char *rom_data;
 extern int  mmuhack_status;
@@ -817,17 +816,17 @@ static char *usb_joy_key_name(int joy, int num)
 	return name;
 }
 
-static void draw_key_config(int curr_act, int is_p2)
+static char *action_binds(int player_idx, int action_mask)
 {
-	char strkeys[32*5];
+	static char strkeys[32*5];
 	int joy, i;
 
 	strkeys[0] = 0;
-	for (i = 0; i < 32; i++)
+	for (i = 0; i < 32; i++) // i is key index
 	{
-		if (currentConfig.KeyBinds[i] & (1 << curr_act))
+		if (currentConfig.KeyBinds[i] & action_mask)
 		{
-			if (curr_act < 16 && (currentConfig.KeyBinds[i] & (1 << 16)) != (is_p2 << 16)) continue;
+			if (player_idx >= 0 && ((currentConfig.KeyBinds[i] >> 16) & 3) != player_idx) continue;
 			if (strkeys[0]) { strcat(strkeys, " + "); strcat(strkeys, gp2xKeyNames[i]); break; }
 			else strcpy(strkeys, gp2xKeyNames[i]);
 		}
@@ -836,9 +835,9 @@ static void draw_key_config(int curr_act, int is_p2)
 	{
 		for (i = 0; i < 32; i++)
 		{
-			if (currentConfig.JoyBinds[joy][i] & (1 << curr_act))
+			if (currentConfig.JoyBinds[joy][i] & action_mask)
 			{
-				if (curr_act < 16 && (currentConfig.JoyBinds[joy][i] & (1 << 16)) != (is_p2 << 16)) continue;
+				if (player_idx >= 0 && ((currentConfig.JoyBinds[joy][i] >> 16) & 3) != player_idx) continue;
 				if (strkeys[0]) {
 					strcat(strkeys, ", "); strcat(strkeys, usb_joy_key_name(joy + 1, i));
 					break;
@@ -848,51 +847,122 @@ static void draw_key_config(int curr_act, int is_p2)
 		}
 	}
 
-	//memset(gp2x_screen, 0, 320*240);
+	return strkeys;
+}
+
+static void unbind_action(int action)
+{
+	int i, u;
+
+	for (i = 0; i < 32; i++)
+		currentConfig.KeyBinds[i] &= ~action;
+	for (u = 0; u < 4; u++)
+		for (i = 0; i < 32; i++)
+			currentConfig.JoyBinds[u][i] &= ~action;
+}
+
+static int count_bound_keys(int action, int joy)
+{
+	int i, keys = 0;
+
+	if (joy)
+	{
+		for (i = 0; i < 32; i++)
+			if (currentConfig.JoyBinds[joy-1][i] & action) keys++;
+	}
+	else
+	{
+		for (i = 0; i < 32; i++)
+			if (currentConfig.KeyBinds[i] & action) keys++;
+	}
+	return keys;
+}
+
+typedef struct { char *name; int mask; } bind_action_t;
+
+static void draw_key_config(const bind_action_t *opts, int opt_cnt, int player_idx, int sel)
+{
+	int x, y, tl_y = 40, i;
+
 	gp2x_pd_clone_buffer2();
-	gp2x_text_out8(60, 40, "Action: %s", actionNames[curr_act]);
-	gp2x_text_out8(60, 60, "Keys: %s", strkeys);
+	if (player_idx >= 0) {
+		gp2x_text_out8(80, 20, "Player %i controls", player_idx + 1);
+		x = 100;
+	} else {
+		gp2x_text_out8(80, 20, "Emulator controls");
+		x = 40;
+	}
+
+	y = tl_y;
+	for (i = 0; i < opt_cnt; i++, y+=10)
+		gp2x_text_out8(x, y, "%s : %s", opts[i].name, action_binds(player_idx, opts[i].mask));
+
+	gp2x_text_out8(x, y, "Done");
 
-	gp2x_text_out8(30, 180, "Use SELECT to change action");
-	gp2x_text_out8(30, 190, "Press a key to bind/unbind");
-	gp2x_text_out8(30, 200, "Select \"Done\" action and");
-	gp2x_text_out8(30, 210, "  press any key to finish");
+	// draw cursor
+	gp2x_text_out8(x - 16, tl_y + sel*10, ">");
+
+	if (sel < opt_cnt) {
+		gp2x_text_out8(30, 190, "Press a button to bind/unbind");
+		gp2x_text_out8(30, 200, "Use SELECT to clear");
+		gp2x_text_out8(30, 210, "To bind UP/DOWN, hold SELECT");
+		gp2x_text_out8(30, 220, "Select \"Done\" to exit");
+	} else {
+		gp2x_text_out8(30, 200, "Use Options -> Save cfg");
+		gp2x_text_out8(30, 210, "to save controls");
+		gp2x_text_out8(30, 220, "Press B or X to exit");
+	}
 	gp2x_video_flip2();
 }
 
-static void key_config_loop(int is_p2)
+static void key_config_loop(const bind_action_t *opts, int opt_cnt, int player_idx)
 {
-	int curr_act = 0, joy = 0, i;
+	int joy = 0, sel = 0, menu_sel_max = opt_cnt, prev_select = 0, i;
 	unsigned long inp = 0;
 
 	for (;;)
 	{
-		draw_key_config(curr_act, is_p2);
+		draw_key_config(opts, opt_cnt, player_idx, sel);
 		inp = wait_for_input_usbjoy(CONFIGURABLE_KEYS, &joy);
 		// printf("got %08lX from joy %i\n", inp, joy);
 		if (joy == 0) {
-			if (inp & GP2X_SELECT) {
-				curr_act++;
-				while (!actionNames[curr_act] && curr_act < 32) curr_act++;
-				if (curr_act > 31) curr_act = 0;
+			if (!(inp & GP2X_SELECT)) {
+				prev_select = 0;
+				if(inp & GP2X_UP  ) { sel--; if (sel < 0) sel = menu_sel_max; continue; }
+				if(inp & GP2X_DOWN) { sel++; if (sel > menu_sel_max) sel = 0; continue; }
 			}
+			if (sel >= opt_cnt) {
+				if (inp & (GP2X_B|GP2X_X)) break;
+				else continue;
+			}
+			// if we are here, we want to bind/unbind something
+			if ((inp & GP2X_SELECT) && !prev_select)
+				unbind_action(opts[sel].mask);
+			prev_select = inp & GP2X_SELECT;
 			inp &= CONFIGURABLE_KEYS;
 			inp &= ~GP2X_SELECT;
-		}
-		if (curr_act == 31 && inp) break;
-		if (joy == 0) {
 			for (i = 0; i < 32; i++)
 				if (inp & (1 << i)) {
-					currentConfig.KeyBinds[i] ^= (1 << curr_act);
-					if (is_p2) currentConfig.KeyBinds[i] |=  (1 << 16); // player 2 flag
-					else       currentConfig.KeyBinds[i] &= ~(1 << 16);
+					if (count_bound_keys(opts[sel].mask, 0) >= 2)
+					     currentConfig.KeyBinds[i] &= ~opts[sel].mask; // allow to unbind only
+					else currentConfig.KeyBinds[i] ^=  opts[sel].mask;
+					if (player_idx >= 0) {
+						currentConfig.KeyBinds[i] &= ~(3 << 16);
+						currentConfig.KeyBinds[i] |= player_idx << 16;
+					}
 				}
-		} else {
+		}
+		else if (sel < opt_cnt)
+		{
 			for (i = 0; i < 32; i++)
 				if (inp & (1 << i)) {
-					currentConfig.JoyBinds[joy-1][i] ^= (1 << curr_act);
-					if (is_p2) currentConfig.JoyBinds[joy-1][i] |=  (1 << 16);
-					else       currentConfig.JoyBinds[joy-1][i] &= ~(1 << 16);
+					if (count_bound_keys(opts[sel].mask, joy) >= 1) // disallow combos for usbjoy
+					     currentConfig.JoyBinds[joy-1][i] &= ~opts[sel].mask;
+					else currentConfig.JoyBinds[joy-1][i] ^=  opts[sel].mask;
+					if (player_idx >= 0) {
+						currentConfig.JoyBinds[joy-1][i] &= ~(3 << 16);
+						currentConfig.JoyBinds[joy-1][i] |= player_idx << 16;
+					}
 				}
 		}
 	}
@@ -904,10 +974,10 @@ static void draw_kc_sel(int menu_sel)
 	char joyname[36];
 
 	y = tl_y;
-	//memset(gp2x_screen, 0, 320*240);
 	gp2x_pd_clone_buffer2();
 	gp2x_text_out8(tl_x, y,       "Player 1");
 	gp2x_text_out8(tl_x, (y+=10), "Player 2");
+	gp2x_text_out8(tl_x, (y+=10), "Emulator controls");
 	gp2x_text_out8(tl_x, (y+=10), "Done");
 
 	// draw cursor
@@ -924,34 +994,69 @@ static void draw_kc_sel(int menu_sel)
 		gp2x_text_out8(tl_x, (y+=10), "none");
 	}
 
-
 	gp2x_video_flip2();
 }
 
+
+// PicoPad[] format: MXYZ SACB RLDU
+static bind_action_t ctrl_actions[] =
+{
+	{ "UP     ", 0x001 },
+	{ "DOWN   ", 0x002 },
+	{ "LEFT   ", 0x004 },
+	{ "RIGHT  ", 0x008 },
+	{ "A      ", 0x040 },
+	{ "B      ", 0x010 },
+	{ "C      ", 0x020 },
+	{ "START  ", 0x080 },
+	{ "MODE   ", 0x800 },
+	{ "X      ", 0x400 },
+	{ "Y      ", 0x200 },
+	{ "Z      ", 0x100 },
+};
+
+// player2_flag, ?, ?, ?, ?, ?, ?, menu
+// "NEXT SAVE SLOT", "PREV SAVE SLOT", "SWITCH RENDERER", "SAVE STATE",
+// "LOAD STATE", "VOLUME UP", "VOLUME DOWN", "DONE"
+static bind_action_t emuctrl_actions[] =
+{
+	{ "Volume Down    ", 1<<30 },
+	{ "Volume Up      ", 1<<29 },
+	{ "Load State     ", 1<<28 },
+	{ "Save State     ", 1<<27 },
+	{ "Switch Renderer", 1<<26 },
+	{ "Prev Save Slot ", 1<<25 },
+	{ "Next Save Slot ", 1<<24 },
+	{ "Enter Menu     ", 1<<23 },
+};
+
 static void kc_sel_loop(void)
 {
-	int menu_sel = 2, menu_sel_max = 2;
+	int menu_sel = 3, menu_sel_max = 3;
 	unsigned long inp = 0;
+	int is_6button = currentConfig.PicoOpt & 0x020;
 
-	for(;;)
+	while (1)
 	{
 		draw_kc_sel(menu_sel);
 		inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_B|GP2X_X);
-		if(inp & GP2X_UP  ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; }
-		if(inp & GP2X_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; }
-		if(inp & GP2X_B) {
+		if (inp & GP2X_UP  ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; }
+		if (inp & GP2X_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; }
+		if (inp & GP2X_B) {
 			switch (menu_sel) {
-				case 0: key_config_loop(0); return;
-				case 1: key_config_loop(1); return;
+				case 0: key_config_loop(ctrl_actions, is_6button ? 12 : 8, 0); return;
+				case 1: key_config_loop(ctrl_actions, is_6button ? 12 : 8, 1); return;
+				case 2: key_config_loop(emuctrl_actions,
+						sizeof(emuctrl_actions)/sizeof(emuctrl_actions[0]), -1); return;
+				case 3: if (rom_data == NULL) emu_WriteConfig(0); return;
 				default: return;
 			}
 		}
-		if(inp & GP2X_X) return;
+		if (inp & GP2X_X) return;
 	}
 }
 
 
-
 // --------- sega/mega cd options ----------
 
 menu_entry cdopt_entries[] =
@@ -1359,11 +1464,9 @@ static void menu_options_save(void)
 	PicoOpt = currentConfig.PicoOpt;
 	PsndRate = currentConfig.PsndRate;
 	PicoRegionOverride = currentConfig.PicoRegion;
-	if (PicoOpt & 0x20) {
-		actionNames[ 8] = "Z"; actionNames[ 9] = "Y";
-		actionNames[10] = "X"; actionNames[11] = "MODE";
-	} else {
-		actionNames[8] = actionNames[9] = actionNames[10] = actionNames[11] = 0;
+	if (!(PicoOpt & 0x20)) {
+		// unbind XYZ MODE, just in case
+		unbind_action(0xf00);
 	}
 	scaling_update();
 }
@@ -1382,6 +1485,7 @@ static int menu_loop_options(void)
 	me_enable(opt_entries, OPT_ENTRY_COUNT, MA_OPT_SAVECFG_GAME, rom_data != NULL);
 	me_enable(opt_entries, OPT_ENTRY_COUNT, MA_OPT_LOADCFG, config_slot != config_slot_current);
 	menu_sel_max = me_count_enabled(opt_entries, OPT_ENTRY_COUNT) - 1;
+	if (menu_sel > menu_sel_max) menu_sel = menu_sel_max;
 
 	while (1)
 	{
@@ -1477,9 +1581,9 @@ static int menu_loop_options(void)
 						else strcpy(menuErrorMsg, "failed to write config");
 						return 1;
 					case MA_OPT_LOADCFG:
-						ret = emu_ReadConfig(1);
-						if (!ret) ret = emu_ReadConfig(0);
-						if (!ret) strcpy(menuErrorMsg, "config loaded");
+						ret = emu_ReadConfig(1, 1);
+						if (!ret) ret = emu_ReadConfig(0, 1);
+						if (ret)  strcpy(menuErrorMsg, "config loaded");
 						else      strcpy(menuErrorMsg, "failed to load config");
 						return 1;
 					default:
@@ -1585,6 +1689,7 @@ static void menu_loop_root(void)
 	me_enable(main_entries, MAIN_ENTRY_COUNT, MA_MAIN_PATCHES,     PicoPatches != NULL);
 
 	menu_sel_max = me_count_enabled(main_entries, MAIN_ENTRY_COUNT) - 1;
+	if (menu_sel > menu_sel_max) menu_sel = menu_sel_max;
 
 	/* make sure action buttons are not pressed on entering menu */
 	draw_menu_root(menu_sel);
diff --git a/platform/readme.txt b/platform/readme.txt
index ee8ca859..9a731872 100644
--- a/platform/readme.txt
+++ b/platform/readme.txt
@@ -240,6 +240,9 @@ Changelog
     if "accurate timing" was not enabled.
   * Fixed support for large hacked ROMs like "Ultimate Mortal Kombat Trilogy".
     Upto 10MB hacked ROMs are supported now.
+  + Config profiles added (press left/right when saving config).
+  * Changed key configuration behaviour to the one from gpfce (should be more
+    intuitive).
 
 1.32
   + Added some new scaling options.