+static void draw_selection(int x, int y, int w)\r
+{\r
+ int i, h;\r
+ unsigned short *dst, *dest;\r
+\r
+ text_out16_(x, y, (void *)1, (menu_sel_color < 0) ? menu_text_color : menu_sel_color);\r
+\r
+ if (menu_sel_color < 0) return; // no selection hilight\r
+\r
+ if (y > 0) y--;\r
+ dest = (unsigned short *)gp2x_screen + x + y*320 + 14;\r
+ for (h = 11; h > 0; h--)\r
+ {\r
+ dst = dest;\r
+ for (i = w; i > 0; i--)\r
+ *dst++ = menu_sel_color;\r
+ dest += 320;\r
+ }\r
+}\r
+\r
+static void menu_flip(void)\r
+{\r
+ gp2x_video_flush_cache();\r
+ gp2x_video_flip2();\r
+}\r
+\r
+\r
+typedef enum\r
+{\r
+ MB_NONE = 1, /* no auto processing */\r
+ MB_ONOFF, /* ON/OFF setting */\r
+ MB_RANGE, /* [min-max] setting */\r
+} menu_behavior;\r
+\r
+typedef enum\r
+{\r
+ MA_NONE = 1,\r
+ MA_MAIN_RESUME_GAME,\r
+ MA_MAIN_SAVE_STATE,\r
+ MA_MAIN_LOAD_STATE,\r
+ MA_MAIN_RESET_GAME,\r
+ MA_MAIN_LOAD_ROM,\r
+ MA_MAIN_OPTIONS,\r
+ MA_MAIN_CONTROLS,\r
+ MA_MAIN_CREDITS,\r
+ MA_MAIN_PATCHES,\r
+ MA_MAIN_EXIT,\r
+ MA_OPT_RENDERER,\r
+ MA_OPT_SCALING,\r
+ MA_OPT_ACC_TIMING,\r
+ MA_OPT_ACC_SPRITES,\r
+ MA_OPT_SHOW_FPS,\r
+ MA_OPT_FRAMESKIP,\r
+ MA_OPT_ENABLE_SOUND,\r
+ MA_OPT_SOUND_QUALITY,\r
+ MA_OPT_ARM940_SOUND,\r
+ MA_OPT_6BUTTON_PAD,\r
+ MA_OPT_REGION,\r
+ MA_OPT_SRAM_STATES,\r
+ MA_OPT_CONFIRM_STATES,\r
+ MA_OPT_SAVE_SLOT,\r
+ MA_OPT_CPU_CLOCKS,\r
+ MA_OPT_SCD_OPTS,\r
+ MA_OPT_ADV_OPTS,\r
+ MA_OPT_SAVECFG,\r
+ MA_OPT_SAVECFG_GAME,\r
+ MA_OPT_LOADCFG,\r
+ MA_OPT2_GAMMA,\r
+ MA_OPT2_A_SN_GAMMA,\r
+ MA_OPT2_VSYNC,\r
+ MA_OPT2_ENABLE_Z80,\r
+ MA_OPT2_ENABLE_YM2612,\r
+ MA_OPT2_ENABLE_SN76496,\r
+ MA_OPT2_GZIP_STATES,\r
+ MA_OPT2_NO_LAST_ROM,\r
+ MA_OPT2_RAMTIMINGS,\r
+ MA_OPT2_SQUIDGEHACK,\r
+ MA_OPT2_DONE,\r
+ MA_CDOPT_TESTBIOS_USA,\r
+ MA_CDOPT_TESTBIOS_EUR,\r
+ MA_CDOPT_TESTBIOS_JAP,\r
+ MA_CDOPT_LEDS,\r
+ MA_CDOPT_CDDA,\r
+ MA_CDOPT_PCM,\r
+ MA_CDOPT_READAHEAD,\r
+ MA_CDOPT_SAVERAM,\r
+ MA_CDOPT_SCALEROT_CHIP,\r
+ MA_CDOPT_BETTER_SYNC,\r
+ MA_CDOPT_DONE,\r
+} menu_id;\r
+\r
+typedef struct\r
+{\r
+ char *name;\r
+ menu_behavior beh;\r
+ menu_id id;\r
+ void *var; /* for on-off settings */\r
+ int mask;\r
+ signed char min; /* for ranged integer settings, to be sign-extended */\r
+ signed char max;\r
+ char enabled;\r
+} menu_entry;\r
+\r
+static int me_id2offset(const menu_entry *entries, int count, menu_id id)\r
+{\r
+ int i;\r
+ for (i = 0; i < count; i++)\r
+ {\r
+ if (entries[i].id == id) return i;\r
+ }\r
+\r
+ printf("%s: id %i not found\n", __FUNCTION__, id);\r
+ return 0;\r
+}\r
+\r
+static void me_enable(menu_entry *entries, int count, menu_id id, int enable)\r
+{\r
+ int i = me_id2offset(entries, count, id);\r
+ entries[i].enabled = enable;\r
+}\r
+\r
+static int me_count_enabled(const menu_entry *entries, int count)\r
+{\r
+ int i, ret = 0;\r
+\r
+ for (i = 0; i < count; i++)\r
+ {\r
+ if (entries[i].enabled) ret++;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+static menu_id me_index2id(const menu_entry *entries, int count, int index)\r
+{\r
+ int i;\r
+\r
+ for (i = 0; i < count; i++)\r
+ {\r
+ if (entries[i].enabled)\r
+ {\r
+ if (index == 0) break;\r
+ index--;\r
+ }\r
+ }\r
+ if (i >= count) i = count - 1;\r
+ return entries[i].id;\r
+}\r
+\r
+typedef void (me_draw_custom_f)(const menu_entry *entry, int x, int y, void *param);\r
+\r
+static void me_draw(const menu_entry *entries, int count, int x, int y, me_draw_custom_f *cust_draw, void *param)\r
+{\r
+ int i, y1 = y;\r
+\r
+ for (i = 0; i < count; i++)\r
+ {\r
+ if (!entries[i].enabled) continue;\r
+ if (entries[i].name == NULL)\r
+ {\r
+ if (cust_draw != NULL)\r
+ cust_draw(&entries[i], x, y1, param);\r
+ y1 += 10;\r
+ continue;\r
+ }\r
+ text_out16(x, y1, entries[i].name);\r
+ if (entries[i].beh == MB_ONOFF)\r
+ text_out16(x + 27*8, y1, (*(int *)entries[i].var & entries[i].mask) ? "ON" : "OFF");\r
+ else if (entries[i].beh == MB_RANGE)\r
+ text_out16(x + 27*8, y1, "%i", *(int *)entries[i].var);\r
+ y1 += 10;\r
+ }\r
+}\r
+\r
+static int me_process(menu_entry *entries, int count, menu_id id, int is_next)\r
+{\r
+ int i = me_id2offset(entries, count, id);\r
+ menu_entry *entry = &entries[i];\r
+ switch (entry->beh)\r
+ {\r
+ case MB_ONOFF:\r
+ *(int *)entry->var ^= entry->mask;\r
+ return 1;\r
+ case MB_RANGE:\r
+ *(int *)entry->var += is_next ? 1 : -1;\r
+ if (*(int *)entry->var < (int)entry->min) *(int *)entry->var = (int)entry->min;\r
+ if (*(int *)entry->var > (int)entry->max) *(int *)entry->var = (int)entry->max;\r
+ return 1;\r
+ default:\r
+ return 0;\r
+ }\r
+}\r
+\r
+\r
+static int parse_hex_color(char *buff)\r
+{\r
+ char *endp = buff;\r
+ int t = (int) strtoul(buff, &endp, 16);\r
+ if (endp != buff) return ((t>>8)&0xf800) | ((t>>5)&0x07e0) | ((t>>3)&0x1f);\r
+ return -1;\r
+}\r
+\r
+void menu_init(void)\r
+{\r
+ int c, l;\r
+ unsigned char *fd = menu_font_data;\r
+ char buff[256];\r
+ FILE *f;\r
+\r
+ // generate default font from fontdata8x8\r
+ memset(menu_font_data, 0, sizeof(menu_font_data));\r
+ for (c = 0; c < 256; c++)\r
+ {\r
+ for (l = 0; l < 8; l++)\r
+ {\r
+ unsigned char fd8x8 = fontdata8x8[c*8+l];\r
+ if (fd8x8&0x80) *fd |= 0xf0;\r
+ if (fd8x8&0x40) *fd |= 0x0f; fd++;\r
+ if (fd8x8&0x20) *fd |= 0xf0;\r
+ if (fd8x8&0x10) *fd |= 0x0f; fd++;\r
+ if (fd8x8&0x08) *fd |= 0xf0;\r
+ if (fd8x8&0x04) *fd |= 0x0f; fd++;\r
+ if (fd8x8&0x02) *fd |= 0xf0;\r
+ if (fd8x8&0x01) *fd |= 0x0f; fd++;\r
+ }\r
+ fd += 8*2/2; // 2 empty lines\r
+ }\r
+\r
+ // load custom font and selector (stored as 1st symbol in font table)\r
+ readpng(menu_font_data, "skin/font.png", READPNG_FONT);\r
+ memcpy(menu_font_data, menu_font_data + ((int)'>')*4*10, 4*10); // default selector symbol is '>'\r
+ readpng(menu_font_data, "skin/selector.png", READPNG_SELECTOR);\r
+\r
+ // load custom colors\r
+ f = fopen("skin/skin.txt", "r");\r
+ if (f != NULL)\r
+ {\r
+ printf("found skin.txt\n");\r
+ while (!feof(f))\r
+ {\r
+ fgets(buff, sizeof(buff), f);\r
+ if (buff[0] == '#' || buff[0] == '/') continue; // comment\r
+ if (buff[0] == '\r' || buff[0] == '\n') continue; // empty line\r
+ if (strncmp(buff, "text_color=", 11) == 0)\r
+ {\r
+ int tmp = parse_hex_color(buff+11);\r
+ if (tmp >= 0) menu_text_color = tmp;\r
+ else printf("skin.txt: parse error for text_color\n");\r
+ }\r
+ else if (strncmp(buff, "selection_color=", 16) == 0)\r
+ {\r
+ int tmp = parse_hex_color(buff+16);\r
+ if (tmp >= 0) menu_sel_color = tmp;\r
+ else printf("skin.txt: parse error for selection_color\n");\r
+ }\r
+ else\r
+ printf("skin.txt: parse error: %s\n", buff);\r
+ }\r
+ fclose(f);\r
+ }\r
+}\r