#include "ncdz.h"

static int state_loaded;

static const int keycfg_button_map[13] =
{
	0,
	PSP_CTRL_UP,
	PSP_CTRL_DOWN,
	PSP_CTRL_LEFT,
	PSP_CTRL_RIGHT,
	PSP_CTRL_CIRCLE,
	PSP_CTRL_CROSS,
	PSP_CTRL_SQUARE,
	PSP_CTRL_TRIANGLE,
	PSP_CTRL_LTRIGGER,
	PSP_CTRL_RTRIGGER,
	PSP_CTRL_START,
	PSP_CTRL_SELECT
};

static const char *keycfg_button_name[13] =
{
	"Not use",
	"\x01",
	"\x02",
	"\x03",
	"\x04",
	"\x05",
	"\x06",
	"\x07",
	"\x08",
	"L TRIGGER",
	"R TRIGGER",
	"START",
	"SELECT"
};

typedef struct {
	const char label[64];
	int	type;
	int	code;
} keycfg_menu_t;


#define KEYCFG_MENU_ITEMS 34
keycfg_menu_t keycfg_menu[KEYCFG_MENU_ITEMS] =
{
	{ "\x01", 1, P1_UP },
	{ "\x02", 1, P1_DOWN },
	{ "\x03", 1, P1_LEFT },
	{ "\x04", 1, P1_RIGHT },
	{ "Button A",  1, P1_BUTTONA },
	{ "Button B",  1, P1_BUTTONB },
	{ "Button C",  1, P1_BUTTONC },
	{ "Button D",  1, P1_BUTTOND },
	{ "Start",  1, P1_START },
	{ "Select",  1, P1_SELECT },
	{ "\n", },

	{ "Autofire A",  1, P1_AF_A },
	{ "Autofire B",  1, P1_AF_B },
	{ "Autofire C",  1, P1_AF_C },
	{ "Autofire D",  1, P1_AF_D },
	{ "Autofire Interval",  2, 0 },
	{ "\n", },

	{ "Hotkey A+B",  1, P1_AB },
	{ "Hotkey A+C",  1, P1_AC },
	{ "Hotkey A+D",  1, P1_AD },
	{ "Hotkey B+C",  1, P1_BC },
	{ "Hotkey B+D",  1, P1_BD },
	{ "Hotkey C+D",  1, P1_CD },
	{ "Hotkey A+B+C",  1, P1_ABC },
	{ "Hotkey A+B+D",  1, P1_ABD },
	{ "Hotkey A+C+D",  1, P1_ACD },
	{ "Hotkey B+C+D",  1, P1_BCD },
	{ "Hotkey A+B+C+D",  1, P1_ABCD },
	{ "\n", },

	{ "Show menu",  1, SHOWMENU },
	{ "Save snapshot",  1, SNAPSHOT },
	{ "Switch player",  1, SWPLAYER },
	{ "\n", },
	{ "Return to main menu", }
};

static int keycfg_value[KEYCFG_MENU_ITEMS];


static int menu_keycfg(void)
{
	int sel = 0, rows = 12, top = 0;
	int i, j, arrowl, arrowr;

	for (i = 0; i < KEYCFG_MENU_ITEMS; i++)
	{
		keycfg_value[i] = 0;

		if (keycfg_menu[i].type == 1)
		{
			int code = input_map[keycfg_menu[i].code];

			if (code)
			{
				for (j = 0; j < 13; j++)
				{
					if (code == keycfg_button_map[j])
					{
						keycfg_value[i] = j;
						break;
					}
				}
			}
		}
		else if (keycfg_menu[i].type == 2)
		{
			keycfg_value[i] = af_interval;
		}
	}

	pad_wait_clear();

	while (1)
	{
	  	show_background();

		if (pad_pressed_memory(PSP_CTRL_RTRIGGER) && pad_pressed_memory(PSP_CTRL_CIRCLE))
		{
			char path[MAX_PATH];

			sprintf(path, "%ssnap/menu3.png", launchDir);
			save_png(path);
		}
		else if (pad_pressed_memory(PSP_CTRL_CIRCLE))
		{
			if (sel == KEYCFG_MENU_ITEMS - 1)
				break;
		}
		else if (pad_pressed_memory(PSP_CTRL_CROSS))
		{
			break;
		}
		else if (pad_pressed_memory(PSP_CTRL_UP))
		{
			sel--;
			if (keycfg_menu[sel].label[0] == '\n') sel--;
		}
		else if (pad_pressed_memory(PSP_CTRL_DOWN))
		{
			sel++;
			if (keycfg_menu[sel].label[0] == '\n') sel++;
		}
		else if (pad_pressed_memory(PSP_CTRL_LEFT))
		{
			if (keycfg_menu[sel].type)
			{
				if (keycfg_value[sel] - 1 >= 0)
					keycfg_value[sel]--;
			}
		}
		else if (pad_pressed_memory(PSP_CTRL_RIGHT))
		{
			if (keycfg_menu[sel].type == 1)
			{
				if (keycfg_value[sel] + 1 < 13)
					keycfg_value[sel]++;
			}
			else if (keycfg_menu[sel].type == 2)
			{
				if (keycfg_value[sel] + 1 < 11)
					keycfg_value[sel]++;
			}
		}

		if (top > KEYCFG_MENU_ITEMS - rows) top = KEYCFG_MENU_ITEMS - rows;
		if (top < 0) top = 0;
		if (sel >= KEYCFG_MENU_ITEMS) sel = 0;
		if (sel < 0) sel = KEYCFG_MENU_ITEMS - 1;
		if (sel >= top + rows) top = sel - rows + 1;
		if (sel < top) top = sel;

		boxfill(0, 21, 479,  43, BG3_COL);
		hline_brightness(0, 479, 21, 25);
		hline_brightness(0, 479, 22, 50);
		hline_brightness(0, 479, 23, 75);
		small_icon_shadow(8, 23, ICON_S_KEYCONFIG, 4);
		small_icon(8, 23, TITLE_COL, ICON_S_KEYCONFIG);
		font_print_shadow(36, 23, TITLE_COL, "Key configration menu", 4);

		boxfill(0, 254, 479, 271, BG1_COL);
		font_print_shadow(8, 252, INFOBAR_COL, " \x01\x02 Browse list   \x03\x04 Change value  \x06 Return to main menu", 4);

		draw_scrollbar(470, 47, 479, 251, 16, KEYCFG_MENU_ITEMS, sel);

		arrowl = 0;
		arrowr = 0;
		if (keycfg_menu[sel].type)
		{
			if (keycfg_value[sel] > 0) arrowl = 1;
			if (keycfg_menu[sel].type == 1 && keycfg_value[sel] < 12) arrowr = 1;
			if (keycfg_menu[sel].type == 2 && keycfg_value[sel] < 10) arrowr = 1;
		}

		for (i = 0; i < rows; i++)
		{
			if ((top + i) >= KEYCFG_MENU_ITEMS) break;

			if (keycfg_menu[top + i].label[0] == '\n')
				continue;

			if ((top + i) == sel)
			{
				font_print_shadow(16, 50 + i * 16, SELECT_COL, keycfg_menu[top + i].label, 4);
				if (arrowl) font_print_shadow(170 - 20, 50 + i * 16, SELECT_COL, "\x0b", 4);
			}
			else
				font_print(16, 50 + i * 16, NORMAL_COL, keycfg_menu[top + i].label);

			if (keycfg_menu[top + i].type == 1)
			{
				if ((top + i) == sel)
				{
					font_print_shadow(170, 50 + i * 16, SELECT_COL, keycfg_button_name[keycfg_value[top + i]], 4);
					if (arrowr) font_print_shadow(170 + font_get_string_width(keycfg_button_name[keycfg_value[top + i]]) + 4, 50 + i * 16, SELECT_COL, "\x0c", 4);
				}
				else
					font_print(170, 50 + i * 16, NORMAL_COL, keycfg_button_name[keycfg_value[top + i]]);
			}
			else if (keycfg_menu[top + i].type == 2)
			{
				char s[8];

				if (keycfg_value[top + i] == 0)
					sprintf(s, "%d frame", keycfg_value[top + i] + 1);
				else
					sprintf(s, "%d frames", keycfg_value[top + i] + 1);

				if ((top + i) == sel)
				{
					font_print_shadow(170, 50 + i * 16, SELECT_COL, s, 4);
					if (arrowr) font_print_shadow(170 + font_get_string_width(s) + 4, 50 + i * 16, SELECT_COL, "\x0c", 4);
				}
				else
					font_print(170, 50 + i * 16, NORMAL_COL, s);
			}
		}

		draw_battery_status(1);
		video_flip_screen(1);
		pad_update();

		if (get_app_status()) break;
	}

	for (i = 0; i < KEYCFG_MENU_ITEMS; i++)
	{
		if (keycfg_menu[i].type == 1)
		{
			input_map[keycfg_menu[i].code] = keycfg_button_map[keycfg_value[i]];
		}
		else if (keycfg_menu[i].type == 2)
		{
			af_interval = keycfg_value[i];
		}
	}

	if (input_map[SHOWMENU] == 0)
		input_map[SHOWMENU] = PSP_CTRL_LTRIGGER;

	pad_wait_clear();

	return 0;
}


int menu_reset(void)
{
	boxfill_alpha(0, 0, 479, 271, 0, 16);

	draw_dialog(240-110+1, 136-32+1, 240+110-1, 136+32-1);
	font_print_shadow_center(136-26+1, MAKECOL15(255,255,127), "Reset NEOGEO emulation.", 4);
	font_print_shadow_center(136+4+1, MAKECOL15(255,255,255), "\x05 to confirm, \x06 to cancel", 4);

	video_flip_screen(1);

	pad_wait_clear();

	do
	{
		pad_update();

		if (pad_pressed_memory(PSP_CTRL_CIRCLE))
		{
			video_clear_screen();
			video_flip_screen(1);
			bLoop = LOOP_RESET;
			bSleep = 0;
			return 1;
		}

   		if (get_app_status()) break;

	} while (!pad_pressed_memory(PSP_CTRL_CROSS));

	return 0;
}


int menu_restart(void)
{
	boxfill_alpha(0, 0, 479, 271, 0, 16);

	draw_dialog(240-110+1, 136-32+1, 240+110-1, 136+32-1);
	font_print_shadow_center(136-26+1, MAKECOL15(255,255,127), "Need to restart NEOGEO.", 4);
	font_print_shadow_center(136+4+1, MAKECOL15(255,255,255), "Press \x05 button", 4);

	video_flip_screen(1);

	pad_wait_clear();

	while (1)
	{
		pad_update();

		if (pad_pressed_memory(PSP_CTRL_CIRCLE))
		{
			video_clear_screen();
			video_flip_screen(1);
			bLoop = LOOP_RESTART;
			bSleep = 0;
			break;
		}

   		if (get_app_status()) break;
	}

	return 1;
}


int menu_browser(void)
{
	bLoop = LOOP_BROWSER;
	bSleep = 0;
	return 1;
}

int menu_exit(void)
{
	bLoop = LOOP_EXIT;
	bSleep = 0;
	return 1;
}


typedef struct {
	const char label[32];
	int	*value;
	int flag;
	int old_value;
	int	value_max;
	char *values_label[32];
} gamecfg_t;


#define CFG_CONTINUE	0
#define CFG_RESTART		1
#define CFG_RESET		2

#define GAMECFG_MENU_ITEMS 24

gamecfg_t gamecfg_menu[GAMECFG_MENU_ITEMS] =
{
	{
		"Machine region", &neogeo_region, CFG_RESTART, 0,
		2, { "Japan", "USA", "Europe" }
	},
	{
		"Emulate load screen", &neogeo_loadscreen, CFG_RESTART, 0,
		1, { "No", "Yes" }
	},
	{"\n" },

	{
		"Render", &neogeo_blitter, CFG_CONTINUE, 0,
		3, { "1:1", "Zoom1", "Zoom2", "Full" }
	},
	{
		"Video sync", &neogeo_vsync, CFG_CONTINUE, 0,
		1, { "Off", "On" }
	},
	{
		"Auto frameskip", &neogeo_autoframeskip, CFG_CONTINUE, 0,
		1, { "Disable", "Enable" }
	},
	{
		"Auto frameskip limit", &neogeo_autoframeskip_limit, CFG_CONTINUE, 0,
		9, { "90%","91%","92%","93%","94%","95%","96%","97%","98%","99%" }
	},
	{
		"Frameskip", &neogeo_frameskip, CFG_CONTINUE, 0,
		11, { "0","1","2","3","4","5","6","7","8","9","10","11" }
	},
	{
		"Show FPS", &neogeo_showfps, CFG_CONTINUE, 0,
		1, { "Off", "On" }
	},
	{
		"60fps limit", &neogeo_speedlimit, CFG_CONTINUE, 0,
		1, { "Off","On" }
	},
	{
		"Cache clear timing", &neogeo_cacheclear, CFG_CONTINUE, 0,
		6,{"Not clear","Over 10frames","Over 20frames","Over 30frames","Over 40frames","Over 50frames","Over 60frames"}
	},
	{
		"Palette refresh type", &neogeo_paletterefresh, CFG_CONTINUE, 0,
		1, { "Clear all caches","Clear dirty palette only" }
	},
	{"\n" },

	{
		"Enable Sound", &neogeo_sound_enable, CFG_RESTART, 0,
		1, { "No","Yes" }
	},
	{
		"Sample Rate", &neogeo_samplerate, CFG_RESTART, 0,
		2, {"11025Hz","22050Hz","44100Hz"}
	},
	{
		"Sound Volume", &neogeo_sound_volume, CFG_CONTINUE, 0,
		10, {"0%","10%","20%","30%","40%","50%","60%","70%","80%","90%","100%"}
	},
	{
		"Enable CD-DA", &neogeo_cdda_enable, CFG_RESTART, 0,
		1, {"No","Yes"}
	},
	{
		"CDDA Volume", &neogeo_cdda_volume, CFG_CONTINUE, 0,
		10, {"0%", "10%","20%","30%","40%","50%","60%","70%","80%","90%","100%"}
	},
	{ "\n" },

	{
		"Controler", &neogeo_input_port, CFG_CONTINUE, 0,
		1, {"Player 1","Player 2"}
	},
	{ "\n" },

	{
		"PSP clock", &psp_cpuclock, CFG_CONTINUE, 0,
		2, {"222MHz","266MHz","333MHz"}
	},
	{ "\n" },

	{"Return to main menu" }
};


int menu_gamecfg(void)
{
	int sel = 0, rows = 12, top = 0;
	int i, arrowl, arrowr;

	for (i = 0; i < GAMECFG_MENU_ITEMS; i++)
	{
		if (gamecfg_menu[i].value)
		{
			if (*gamecfg_menu[i].value < 0)
				*gamecfg_menu[i].value = 0;
			if (*gamecfg_menu[i].value > gamecfg_menu[i].value_max)
				*gamecfg_menu[i].value = gamecfg_menu[i].value_max;

			gamecfg_menu[i].old_value = *gamecfg_menu[i].value;
		}
	}

	while (1)
	{
	  	show_background();

		if (pad_pressed_memory(PSP_CTRL_RTRIGGER) && pad_pressed_memory(PSP_CTRL_CIRCLE))
		{
			char path[MAX_PATH];

			sprintf(path, "%ssnap/menu2.png", launchDir);
			save_png(path);
		}
		else if (pad_pressed_memory(PSP_CTRL_CIRCLE))
		{
			if (sel == GAMECFG_MENU_ITEMS - 1)
				break;
		}
		else if (pad_pressed_memory(PSP_CTRL_CROSS))
		{
			break;
		}
		else if (pad_pressed_memory(PSP_CTRL_UP))
		{
			sel--;
			if (gamecfg_menu[sel].label[0] == '\n') sel--;
		}
		else if (pad_pressed_memory(PSP_CTRL_DOWN))
		{
			sel++;
			if (gamecfg_menu[sel].label[0] == '\n') sel++;
		}
		else if (pad_pressed_memory(PSP_CTRL_LEFT))
		{
			if (gamecfg_menu[sel].value)
			{
				int cur = *gamecfg_menu[sel].value;

				if (cur > 0)
					*gamecfg_menu[sel].value = cur - 1;
			}
		}
		else if (pad_pressed_memory(PSP_CTRL_RIGHT))
		{
			if (gamecfg_menu[sel].value)
			{
				int cur = *gamecfg_menu[sel].value;

				if (cur < gamecfg_menu[sel].value_max)
					*gamecfg_menu[sel].value = cur + 1;
			}
		}

		if (top > GAMECFG_MENU_ITEMS - rows) top = GAMECFG_MENU_ITEMS - rows;
		if (top < 0) top = 0;
		if (sel >= GAMECFG_MENU_ITEMS) sel = 0;
		if (sel < 0) sel = GAMECFG_MENU_ITEMS - 1;
		if (sel >= top + rows) top = sel - rows + 1;
		if (sel < top) top = sel;

		arrowl = 0;
		arrowr = 0;
		if (gamecfg_menu[sel].value)
		{
			int cur = *gamecfg_menu[sel].value;

			if (cur > 0) arrowl = 1;
			if (cur < gamecfg_menu[sel].value_max) arrowr = 1;
		}

		boxfill(0, 21, 479,  43, BG2_COL);
		hline_brightness(0, 479, 21, 25);
		hline_brightness(0, 479, 22, 50);
		hline_brightness(0, 479, 23, 75);
		small_icon_shadow(8 + 1, 23 + 1, ICON_S_CONFIG, 4);
		small_icon(8, 23, TITLE_COL, ICON_S_CONFIG);
		font_print_shadow(36, 23, TITLE_COL, "Game configration menu", 4);
		boxfill(0, 254, 479, 271, BG1_COL);
		font_print_shadow(8, 252, INFOBAR_COL, " \x01\x02 Browse list   \x03\x04 Change value  \x06 Return to main menu", 4);

		draw_scrollbar(470, 47, 479, 251, 16, GAMECFG_MENU_ITEMS, sel);

		for (i = 0; i < rows; i++)
		{
			if (top + i >= GAMECFG_MENU_ITEMS) break;

			if (gamecfg_menu[top + i].label[0] == '\n')
				continue;

			if ((top + i) == sel)
			{
				font_print_shadow(16, 50 + i * 16, SELECT_COL, gamecfg_menu[top + i].label, 4);
				if (arrowl) font_print_shadow(200 - 20, 50 + i * 16, SELECT_COL, "\x0b", 4);
			}
			else
				font_print(16, 50 + i * 16, NORMAL_COL, gamecfg_menu[top + i].label);

			if (gamecfg_menu[top + i].value)
			{
				int val = *gamecfg_menu[top + i].value;

				if ((top + i) == sel)
				{
					font_print_shadow(200, 50 + i * 16, SELECT_COL, gamecfg_menu[top + i].values_label[val], 4);
					if (arrowr) font_print_shadow(200 + font_get_string_width(gamecfg_menu[top + i].values_label[val]) + 4, 50 + i * 16, SELECT_COL, "\x0c", 4);
				}
				else
					font_print(200, 50 + i * 16, NORMAL_COL, gamecfg_menu[top + i].values_label[val]);
			}
		}

		draw_battery_status(1);
		video_flip_screen(1);
		pad_update();

   		if (get_app_status()) break;
	}

	for (i = 0; i < GAMECFG_MENU_ITEMS; i++)
	{
		if (gamecfg_menu[i].value && gamecfg_menu[i].flag == CFG_RESTART)
		{
			if (gamecfg_menu[i].old_value != *gamecfg_menu[i].value)
			{
				menu_restart();
				return 1;
			}
		}
	}

	pad_wait_clear();

	return 0;
}


#ifdef SAVE_STATE

static u8 slot[10];
static int st_which;
static int st_sel;
static int st_light_level;
static int st_light_dir;


static void menu_delete_slot(void)
{
	boxfill_alpha(0, 0, 479, 271, 0, 16);

	draw_dialog(240-110+1, 136-32+1, 240+110-1, 136+32-1);
	font_print_shadow_center(136-26+1, MAKECOL15(255,255,127), "Delete save state.", 4);
	font_print_shadow_center(136+4+1, MAKECOL15(255,255,255), "\x05 to confirm, \x06 to cancel", 4);

	video_flip_screen(1);

	pad_wait_clear();

	do
	{
		pad_update();

		if (pad_pressed_memory(PSP_CTRL_CIRCLE))
		{
			char path[MAX_PATH];

			sprintf(path, "%sstate/%s.sv%d", launchDir, game_name, st_sel);
			sceIoRemove(path);
			slot[st_sel] = 0;
			st_which = 0;
			break;
		}

   		if (get_app_status()) break;

	} while (!pad_pressed_memory(PSP_CTRL_CROSS));

	pad_wait_clear();
}


int draw_state_menu(int progress)
{
	int x, y;

  	show_background();

	st_light_level += st_light_dir;
	if (st_light_level > 31)
	{
		st_light_level = 31;
		st_light_dir = -1;
	}
	else if (st_light_level < 0)
	{
		st_light_level = 0;
		st_light_dir = 1;
	}

	boxfill(0, 21, 479,  43, BG2_COL);
	hline_brightness(0, 479, 21, 25);
	hline_brightness(0, 479, 22, 50);
	hline_brightness(0, 479, 23, 75);
	font_print(8, 23, NORMAL_COL, "Main menu");
	font_print(88, 23, NORMAL_COL, "\x0bL	R\x0c");
	font_print_shadow(158, 23, TITLE_COL, "Save/Load state", 4);
	draw_battery_status(0);

	for (y = 0; y < 10; y++)
	{
		char name[16], state[32];

		sprintf(name, "Slot %d:", y);
		if (slot[y])
			sprintf(state, "%s.sv%d", game_name, y);
		else
			strcpy(state, "Empty");

		if (y == st_sel)
		{
			small_icon_lightshadow(16, 54 + y * 20, ICON_S_MEMSTICK, st_light_level);
			small_icon_shadow(16, 54 + y * 20, ICON_S_MEMSTICK, 4);
			small_icon(16, 54 + y * 20, SELECT_COL, ICON_S_MEMSTICK);

			font_print_shadow(40, 54 + y * 20, SELECT_COL, name, 4);
			font_print_shadow(90, 54 + y * 20, SELECT_COL, state, 4);

			if (slot[st_sel])
			{
				if (st_which == 1)
				{
					font_print_shadow(192, 54 + y * 20, SELECT_COL, "\x0b", 4);
					font_print_shadow(210, 54 + y * 20, SELECT_COL, "load", 4);
					font_print_shadow(244, 54 + y * 20, SELECT_COL, "\x0c", 4);
				}
				else if (st_which == 2)
				{
					font_print_shadow(192, 54 + y * 20, SELECT_COL, "\x0b", 4);
					font_print_shadow(210, 54 + y * 20, SELECT_COL, "Delete", 4);
				}
				else
				{
					font_print_shadow(210, 54 + y * 20, SELECT_COL, "Save", 4);
					font_print_shadow(244, 54 + y * 20, SELECT_COL, "\x0c", 4);
				}
			}
			else
			{
				font_print_shadow(210, 54 + y * 20, SELECT_COL, "Save", 4);
			}

			hline_gradation(40, 260, 54 + y * 20 + 18, NORMAL_COL, SELECT_COL, 28);
			hline_gradation(41, 261, 54 + y * 20 + 19, 0, 0, 15);
		}
		else
		{
			small_icon(16, 54 + y * 20, NORMAL_COL, ICON_S_MEMSTICK);
			font_print(40, 54 + y * 20, NORMAL_COL, name);
			font_print(90, 54 + y * 20, NORMAL_COL, state);
		}
	}

	u16 *p = video_frame_addr(draw_frame, 0, 0);
	for (y = 0; y < 112; y++)
	{
		for (x = 0; x < 152; x++)
		{
			p[(62 + y) * BUF_WIDTH + (298 + x)] = thumbnail_buf[y * 152 + x];
		}
	}

	font_print(290, 182, NORMAL_COL, "Play Date");
	font_print(368, 182, NORMAL_COL, date_str);
	font_print(290, 202, NORMAL_COL, "Save Time");
	font_print(368, 202, NORMAL_COL, time_str);
	font_print(290, 222, NORMAL_COL, "Version");
	font_print(368, 222, NORMAL_COL, stver_str);

	if (progress != 0)
	{
		if (st_which == 2) return;

		boxfill_alpha(0, 0, 479, 271, 0, 16);
		draw_dialog(80, 16, 479-80, 271-16);

		if (st_which)
		{
			font_print_shadow_center(20, MAKECOL15(255,255,127), "Load state", 4);

			if (progress == 1)
			{
				font_print_shadow(90, 40, MAKECOL15(255,255,255), "Press \05 to start load state. (\x06 to cancel)", 4);
				video_flip_screen(1);

				pad_wait_clear();

				do
				{
					if (pad_pressed_memory(PSP_CTRL_CIRCLE))
					{
						pad_wait_clear();
						return 1;
					}

			   		if (get_app_status()) break;

					pad_update();
				} while (!pad_pressed_memory(PSP_CTRL_CROSS));

				pad_wait_clear();
				return 0;
			}
			if (progress > 1) font_print_shadow(90, 40, MAKECOL15(255,255, 255), "Read header...", 4);
			if (progress > 2) font_print_shadow(90, 40 + 18, MAKECOL15(255,255, 255), "Skip snap shot...", 4);
			if (progress > 3) font_print_shadow(90, 40 + 18*2, MAKECOL15(255,255, 255), "Read state data...", 4);
			if (progress > 4) font_print_shadow(90, 40 + 18*3, MAKECOL15(255,255, 255), "Uncompress state data...", 4);
			if (progress > 5) font_print_shadow(90, 40 + 18*4, MAKECOL15(255,255, 255), "Restore state data...", 4);
			if (progress > 6)
			{
				font_print_shadow(90, 40 + 18*5, MAKECOL15(255,255, 255), "Complete.", 4);
				font_print_shadow_center(231, MAKECOL15(255,255, 255), "Press any button to return to game.", 4);
				video_flip_screen(1);
				pad_wait_press(-1);
				pad_wait_clear();
				return 0;
			}
		}
		else
		{
			font_print_shadow_center(20, MAKECOL15(255,255,127), "Save state", 4);

			if (progress <= 8)
			{
				font_print_shadow_center(211, MAKECOL15(255,127,127), "Save state is very slow.", 4);
				font_print_shadow_center(231, MAKECOL15(255,127,127), "Please wait for a while.", 4);
			}

			if (progress == 1)
			{
				font_print_shadow(90, 40, MAKECOL15(255,255, 255), "Press \05 to start save state. (\x06 to cancel)", 4);
				video_flip_screen(1);

				pad_wait_clear();

				do
				{
					if (pad_pressed_memory(PSP_CTRL_CIRCLE))
					{
						pad_wait_clear();
						return 1;
					}

			   		if (get_app_status()) break;

					pad_update();
				} while (!pad_pressed_memory(PSP_CTRL_CROSS));

				pad_wait_clear();
				return 0;
			}
			if (progress > 1) font_print_shadow(90, 40, MAKECOL15(255,255, 255), "Write header...", 4);
			if (progress > 2) font_print_shadow(90, 40 + 18*1, MAKECOL15(255,255, 255), "Capture snap shot...", 4);
			if (progress > 3) font_print_shadow(90, 40 + 18*2, MAKECOL15(255,255, 255), "Compress snap shot...", 4);
			if (progress > 4) font_print_shadow(90, 40 + 18*3, MAKECOL15(255,255, 255), "Write snap shot...", 4);
			if (progress > 5) font_print_shadow(90, 40 + 18*4, MAKECOL15(255,255, 255), "Register state data...", 4);
			if (progress > 6) font_print_shadow(90, 40 + 18*5, MAKECOL15(255,255, 255), "Compress state data...", 4);
			if (progress > 7) font_print_shadow(90, 40 + 18*6, MAKECOL15(255,255, 255), "Write state data...", 4);
			if (progress > 8)
			{
				font_print_shadow(90, 40 + 18*7, MAKECOL15(255,255, 255), "Complete.", 4);
				font_print_shadow_center(211, MAKECOL15(255,255, 255), "Press \x06 to return to game.", 4);
				font_print_shadow_center(231, MAKECOL15(255,255, 255), "Press other button to return to menu.", 4);
				video_flip_screen(1);
				pad_wait_clear();

				do
				{
					if (pad_pressed_memory(PSP_CTRL_CROSS))
					{
						pad_wait_clear();
						return 1;
					}

			   		if (get_app_status()) break;

					pad_update();
				} while (!pad_pressed_any(PSP_CTRL_CROSS));

				pad_wait_clear();
				return 0;
			}
		}
	}

	video_flip_screen(1);

	return 0;
}


int menu_state(void)
{
	int i, prev_sel = -1;
	int thumbnail_loaded = 0;

	st_which = 0;
	st_sel = 0;
	st_light_level = 0;
	st_light_dir = 1;
	thumbnail_loaded = 0;

	memset(slot, 0, sizeof(slot));

	find_state_file(slot);

	while (1)
	{
		if (prev_sel == st_sel)
		{
			if (pad_pressed_memory(PSP_CTRL_RTRIGGER) && pad_pressed_memory(PSP_CTRL_CIRCLE))
			{
				char path[MAX_PATH];

				sprintf(path, "%ssnap/menu1.png", launchDir);
				save_png(path);
			}
			else if (pad_pressed_memory(PSP_CTRL_CIRCLE))
			{
				if (st_which == 1)
				{
					if (slot[st_sel])
					{
						if (draw_state_menu(1))
						{
							set_cpu_clock();
							state_load(st_sel);
							scePowerSetClockFrequency(222, 222, 111);
							state_loaded = 1;
							draw_state_menu(7);
							return 1;
						}
						continue;
					}
				}
				else if (st_which == 2)
				{
					if (slot[st_sel])
					{
						draw_state_menu(1);
						menu_delete_slot();
						prev_sel = -1;
						continue;
					}
				}
				else
				{
					if (draw_state_menu(1))
					{
						set_cpu_clock();
						state_save(st_sel);
						scePowerSetClockFrequency(222, 222, 111);
						find_state_file(slot);
						state_load_screen(st_sel);

						if (draw_state_menu(9))
							return 1;
					}
					continue;
				}
			}
			draw_state_menu(0);
		}
		else
		{
			prev_sel = st_sel;
			st_light_level = 0;
			st_light_dir = 1;

			if (neogeo_region)
				strcpy(date_str, "--/--/----");
			else
				strcpy(date_str, "----/--/--");
			strcpy(time_str, "--:--:--");
			strcpy(stver_str, "--------");

			if (slot[st_sel] == 1)
			{
				state_load_screen(st_sel);
			}
			else
			{
				st_which = 0;
				memset(thumbnail_buf, 0, sizeof(thumbnail_buf));
			}
		}

		if (pad_pressed_memory(PSP_CTRL_UP))
		{
			st_sel--;
			if (st_sel < 0) st_sel = 10 - 1;
		}
		else if (pad_pressed_memory(PSP_CTRL_DOWN))
		{
			st_sel++;
			if (st_sel >= 10) st_sel = 0;
		}
		else if (pad_pressed_memory(PSP_CTRL_LEFT))
		{
			if (st_which > 0) st_which--;
		}
		else if (pad_pressed_memory(PSP_CTRL_RIGHT))
		{
			if (slot[st_sel])
			{
				if (st_which < 2) st_which++;
			}
		}
		else if (pad_pressed_memory(PSP_CTRL_LTRIGGER))
		{
			break;
		}

		pad_update();

   		if (get_app_status()) break;
	}

	pad_wait_clear();

	return 0;
}

#endif


typedef struct
{
	const char label[64];
	int (*menu_func)(void);
	int	icon;
	const char help[128];
} menu_t;


#define MENU_ITEMS 6

menu_t main_menu[MENU_ITEMS] =
{
	{"Game configration", menu_gamecfg, ICON_L_CONFIG, "Change game settings." },
	{"Key configration", menu_keycfg, ICON_L_KEYCONFIG, "Change buttons and autofire/hotkey settings." },
	{"Reset NEOGEO", menu_reset, ICON_L_RESET, "Reset NEOGEO CDZ emulation."},
	{"Return to file browser", menu_browser, ICON_L_FOLDER, "Stop emulation and return to file browser." },
	{"Return to game", NULL, ICON_L_RETURN, "Return to game emulation." },
	{"Exit emulator", menu_exit, ICON_L_EXIT, "Exit emulation and return to PSP menu." },
};


void showmenu(void)
{
	static int sel = 0;
	int y, light_level = 0, light_dir = 1, prev_sel = 0;
	int mp3_paused = 0;

	load_background();

	state_loaded = 0;

	if (mp3_get_status() == MP3_PLAY)
	{
		mp3_pause(1);
		mp3_paused = 1;
	}

	sound_enable(0);

	scePowerSetClockFrequency(222, 222, 111);
	video_clear_screen();

	pad_wait_clear();

	while (1)
	{
	  	show_background();

		if (prev_sel == sel)
		{
			light_level += light_dir;
			if (light_level > 31)
			{
				light_level = 31;
				light_dir = -1;
			}
			else if (light_level < 0)
			{
				light_level = 0;
				light_dir = 1;
			}

			boxfill(0, 21, 479,  43, BG2_COL);
			hline_brightness(0, 479, 21, 25);
			hline_brightness(0, 479, 22, 50);
			hline_brightness(0, 479, 23, 75);
			font_print_shadow(8, 23, TITLE_COL, "Main menu", 4);
#ifdef SAVE_STATE
			font_print(88, 23, NORMAL_COL, "\x0bL	R\x0c");
			font_print(158, 23, NORMAL_COL, "Save/Load state");
#endif

			for (y = 0; y < MENU_ITEMS; y++)
			{
				if (y == sel)
				{
					large_icon_lightshadow(16, 54 + y * 35, main_menu[y].icon, light_level);
					large_icon_shadow(16, 54 + y * 35, main_menu[y].icon, 4);
					large_icon(16, 54 + y * 35, SELECT_COL, main_menu[y].icon);

					font_print_shadow(56, 45 + y * 35, SELECT_COL, main_menu[y].label, 4);
					font_print_shadow(56, 49 + y * 35 + 16, SELECT_COL, main_menu[y].help, 4);

					hline_gradation(56, 460, 47 + y * 35 + 19, NORMAL_COL, SELECT_COL, 28);
					hline_gradation(57, 460, 47 + y * 35 + 20, 0, 0, 15);
				}
				else
				{
					large_icon(16, 54 + y * 35, NORMAL_COL, main_menu[y].icon);
					font_print(56, 47 + y * 35 + 8, NORMAL_COL, main_menu[y].label);
				}
			}

			if (pad_pressed_memory(PSP_CTRL_CIRCLE))
			{
				if (main_menu[sel].menu_func)
				{
					if (main_menu[sel].menu_func())
						break;
				}
				else break;
			}
			else if (pad_pressed_memory(PSP_CTRL_CROSS))
			{
				break;
			}
			else if (pad_pressed_memory(PSP_CTRL_RTRIGGER))
			{
				if (menu_state()) break;
			}

			draw_battery_status(1);
			ui_show_popup();
			video_flip_screen(1);
		}
		else
		{
			prev_sel = sel;
			light_level = 0;
			light_dir = 1;
		}

		if (pad_pressed_memory(PSP_CTRL_RTRIGGER) && pad_pressed_memory(PSP_CTRL_CIRCLE))
		{
			char path[MAX_PATH];

			sprintf(path, "%ssnap/menu0.png", launchDir);
			save_png(path);
		}
		else if (pad_pressed_memory(PSP_CTRL_UP))
		{
			sel--;
			if (sel < 0) sel = MENU_ITEMS - 1;
		}
		else if (pad_pressed_memory(PSP_CTRL_DOWN))
		{
			sel++;
			if (sel >= MENU_ITEMS) sel = 0;
		}

		pad_update();

   		if (get_app_status()) break;
	}

	pad_wait_clear();

	set_cpu_clock();

	init_autoframeskip();
	blit_clear_cache();

	sound_set_volume();

	mp3_file_reopen();
	mp3_set_volume();

	if (state_loaded)
	{
		if (mp3_get_status() == MP3_SEEK)
		{
			mp3_seek_start();

			while (mp3_get_status() == MP3_SEEK)
				wait(100);
		}
	}
	else if (!neogeo_cdda_enable)
	{
		cdda_stop();
	}
	else if (mp3_paused)
	{
		mp3_pause(0);
	}

	if (neogeo_sound_enable)
	{
		timer_suspend_cpu(CPU_Z80, 1, SUSPEND_REASON_NOTSUSPEND);
		sound_enable(1);
	}
	else
	{
		timer_suspend_cpu(CPU_Z80, 0, SUSPEND_REASON_DISABLE);
		sound_enable(0);
	}

	video_clear_screen();
}


#define COLOR_ITEMS 11


void show_color_menu(void)
{
	static int sel = 0;
	int x, prev_sel = 0;
	int prev_brightness;
	int save_r;
	int save_g;
	int save_b;
	UI_PALETTE *pal;
	char buf[256];
	int sel_y = 0;
	u16 sel_col = COLOR_WHITE;
	u16 nor_col = MAKECOL15(200,200,200);

	prev_brightness = bg_brightness;

	while (1)
	{
	  	show_background();

		boxfill(0, 21, 479,  43, BG2_COL);
		boxfill(0, 254, 479, 271, BG1_COL);
		hline_brightness(0, 479, 21, 25);
		hline_brightness(0, 479, 22, 50);
		hline_brightness(0, 479, 23, 75);
		font_print_shadow(8, 23, TITLE_COL, "Color settings", 4);
		font_print_shadow(16, 252, INFOBAR_COL, "\x01\x02 Select    \x03\x04 Change value   \x06 Return to file browser", 4);

		font_print_shadow(8, 45 + 0 * 16, LOGO_COL, "Logo bar text", 4);
		font_print_shadow(8, 45 + 1 * 16, TITLE_COL, "Title bar text", 4);
		font_print_shadow(8, 45 + 2 * 16, INFOBAR_COL, "Infomation bar text", 4);
		font_print_shadow(8, 45 + 3 * 16, SELECT_COL, "Selected text", 4);
		font_print(8, 45 + 4 * 16, NORMAL_COL, "Normal text");

		boxfill_gradation(4, 45 + 5 * 16 + 4, 475, 45 + 5 * 16 + 20, FILESEL1_COL, FILESEL2_COL, 15);
		font_print_shadow(8, 45 + 5 * 16, SELECT_COL, "File select bar", 4);

		draw_dialog(296, 47, 477, 99);
		font_print_shadow(300, 47, COLOR_WHITE, "Note:", 4);
		font_print_shadow(300, 63, COLOR_WHITE, " Press \x08 to restore all", 4);
		font_print_shadow(300, 79, COLOR_WHITE, " values to default.", 4);

		draw_dialog(96, 156, 383, 250);

		if (sel == 0)
		{
			font_print_center(164, MAKECOL15(255,255,128), "Background image brightness");
			sprintf(buf, "%3d%%", bg_brightness);

			if (sel_y)
			{
				font_print(200, 200, sel_col, "\x0b");
				font_print(262, 200, sel_col, "\x0c");
				font_print_center(200, sel_col, buf);
			}
			else
			{
				font_print(105, 164, sel_col, "\x0b");
				font_print(358, 164, sel_col, "\x0c");
				font_print_center(200, nor_col, buf);
			}
		}
		else
		{
			switch (sel)
			{
			case 1: strcpy(buf, "Logo bar text");  pal = &logo_pal;  break;
			case 2: strcpy(buf, "Title bar text"); pal = &title_pal; break;
			case 3: strcpy(buf, "Infomation bar text"); pal = &infobar_pal; break;
			case 4: strcpy(buf, "Selected text"); pal = &select_pal;  break;
			case 5: strcpy(buf, "Normal text"); pal = &normal_pal; break;
			case 6: strcpy(buf, "Background 1"); pal = &bg1_pal; break;
			case 7: strcpy(buf, "Background 2"); pal = &bg2_pal; break;
			case 8: strcpy(buf, "Background 3"); pal = &bg3_pal; break;
			case 9: strcpy(buf, "File select bar 1");  pal = &filesel1_pal; break;
			case 10: strcpy(buf, "File select bar 2"); pal = &filesel2_pal; break;
			}

			font_print_center(164, MAKECOL15(255,255,128), buf);

			if (sel_y == 0)
			{
				font_print(105, 164, sel_col, "\x0b");
				font_print(374-16, 164, sel_col, "\x0c");
			}

			font_print(110, 186, (sel_y == 1) ? sel_col : nor_col, "Red");
			font_print(110, 200, (sel_y == 2) ? sel_col : nor_col, "Green");
			font_print(110, 216, (sel_y == 3) ? sel_col : nor_col, "Blue");

			box(172, 190, 172 + 6*31 + 1, 202, (sel_y == 1) ? sel_col : nor_col);
			box(172, 206, 172 + 6*31 + 1, 218, (sel_y == 2) ? sel_col : nor_col);
			box(172, 222, 172 + 6*31 + 1, 234, (sel_y == 3) ? sel_col : nor_col);

			boxfill(172 + 1, 191, 172 + 6*pal->r, 201, COLOR_RED);
			boxfill(172 + 1, 207, 172 + 6*pal->g, 217, COLOR_GREEN);
			boxfill(172 + 1, 223, 172 + 6*pal->b, 233, COLOR_BLUE);

			switch (sel_y)
			{
			case 1:
				if (pal->r > 0)  font_print(156, 185, sel_col, "\x0b");
				if (pal->r < 31) font_print(360, 186, sel_col, "\x0c");
				break;

			case 2:
				if (pal->g > 0)  font_print(156, 200, sel_col, "\x0b");
				if (pal->g < 31) font_print(360, 201, sel_col, "\x0c");
				break;

			case 3:
				if (pal->b > 0)  font_print(156, 216, sel_col, "\x0b");
				if (pal->b < 31) font_print(360, 217, sel_col, "\x0c");
				break;
			}
		}

		draw_battery_status(1);
		ui_show_popup();
		video_flip_screen(1);

		if (pad_pressed_memory(PSP_CTRL_RTRIGGER) && pad_pressed_memory(PSP_CTRL_CIRCLE))
		{
			char path[MAX_PATH];

			sprintf(path, "%ssnap/menu4.png", launchDir);
			save_png(path);
		}
		else if (pad_pressed_memory(PSP_CTRL_CROSS))
		{
			break;
		}
		else if (pad_pressed_memory(PSP_CTRL_TRIANGLE))
		{
			bg_brightness = 100;
			set_ui_color(&logo_pal,    31,31,31);
			set_ui_color(&title_pal,   25,25,31);
			set_ui_color(&infobar_pal, 28,28,28);
			set_ui_color(&select_pal,  31,31,31);
			set_ui_color(&normal_pal,  25,25,25);
			set_ui_color(&bg1_pal,      8, 8, 8);
			set_ui_color(&bg2_pal,     15,15,15);
			set_ui_color(&bg3_pal,     12,12,12);
			set_ui_color(&filesel1_pal, 0, 0,15);
			set_ui_color(&filesel2_pal, 0, 0, 0);

			load_background();
		}
		else if (pad_pressed_memory(PSP_CTRL_DOWN))
		{
			sel_y++;
			if (sel == 0)
			{
				if (sel_y > 1) sel_y = 1;
			}
			else
			{
				if (sel_y > 3) sel_y = 3;
			}
		}
		else if (pad_pressed_memory(PSP_CTRL_UP))
		{
			sel_y--;
			if (sel_y < 0) sel_y = 0;
		}
		else if (pad_pressed_memory(PSP_CTRL_LEFT))
		{
			if (sel_y == 0)
			{
				sel--;
				if (sel < 0) sel = COLOR_ITEMS - 1;
			}
			else if (sel == 0)
			{
				if (bg_brightness >= 5)
				{
					bg_brightness -= 5;
					load_background();
				}
			}
			else
			{
				switch (sel_y)
				{
				case 1: if (pal->r > 0) pal->r--; break;
				case 2: if (pal->g > 0) pal->g--; break;
				case 3: if (pal->b > 0) pal->b--; break;
				}
				if (sel == 1 || sel == 6) load_background();
			}
		}
		else if (pad_pressed_memory(PSP_CTRL_RIGHT))
		{
			if (sel_y == 0)
			{
				sel++;
				if (sel >= COLOR_ITEMS) sel = 0;
			}
			else if (sel == 0)
			{
				if (bg_brightness <= 95)
				{
					bg_brightness += 5;
					load_background();
				}
			}
			else
			{
				switch (sel_y)
				{
				case 1: if (pal->r < 31) pal->r++; break;
				case 2: if (pal->g < 31) pal->g++; break;
				case 3: if (pal->b < 31) pal->b++; break;
				}
				if (sel == 1 || sel == 6) load_background();
			}
		}

		pad_update();

   		if (get_app_status()) break;
	}

	pad_wait_clear();
}
