3 * Copyright (C) 2006 Exophase <exophase@gmail.com>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public Licens e as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 #include "gp2x/cpuctrl.h"
37 // Blatantly stolen and trimmed from MZX (megazeux.sourceforge.net)
41 #define FILE_LIST_ROWS ((int)((SDL_SCREEN_HEIGHT - 40) / FONT_HEIGHT))
42 #define FILE_LIST_POSITION 5
43 #define DIR_LIST_POSITION 260
47 #define FILE_LIST_ROWS 25
48 #define FILE_LIST_POSITION 5
49 #define DIR_LIST_POSITION 360
55 #define color16(red, green, blue) \
56 (blue << 11) | (green << 5) | red \
60 #define color16(red, green, blue) \
61 (red << 11) | (green << 5) | blue \
67 #define COLOR_BG color16(0, 0, 0)
71 #define COLOR_BG color16(2, 8, 10)
75 #define COLOR_ROM_INFO color16(22, 36, 26)
76 #define COLOR_ACTIVE_ITEM color16(31, 63, 31)
77 #define COLOR_INACTIVE_ITEM color16(13, 40, 18)
78 #define COLOR_FRAMESKIP_BAR color16(15, 31, 31)
79 #define COLOR_HELP_TEXT color16(16, 40, 24)
82 #define get_clock_speed() \
83 clock_speed = (clock_speed_number + 1) * 33
84 #define get_clock_speed_number() \
85 clock_speed_number = (clock_speed / 33) - 1
86 #elif defined(WIZ_BUILD)
87 #define get_clock_speed() \
88 clock_speed = 300 + (clock_speed_number * 3333) / 100
89 #define get_clock_speed_number() \
90 clock_speed_number = (clock_speed - 300) / 33
91 #elif defined(GP2X_BUILD)
92 #define get_clock_speed() \
93 clock_speed = 150 + clock_speed_number * 10
94 #define get_clock_speed_number() \
95 clock_speed_number = (clock_speed - 150) / 10
97 #define get_clock_speed() 0
98 #define get_clock_speed_number() 0
103 default_clock_speed = 533;
104 #elif defined(GP2X_BUILD)
105 default_clock_speed = 200;
107 default_clock_speed = 333;
109 int sort_function(const void *dest_str_ptr, const void *src_str_ptr)
111 char *dest_str = *((char **)dest_str_ptr);
112 char *src_str = *((char **)src_str_ptr);
114 if(src_str[0] == '.')
117 if(dest_str[0] == '.')
120 return strcasecmp(dest_str, src_str);
123 s32 load_file(u8 **wildcards, u8 *result)
126 struct dirent *current_file;
127 struct stat file_info;
128 u8 current_dir_name[MAX_PATH];
129 u8 current_dir_short[81];
130 u32 current_dir_length;
131 u32 total_filenames_allocated;
132 u32 total_dirnames_allocated;
138 u32 file_name_length;
140 u32 chosen_file, chosen_dir;
141 u32 dialog_result = 1;
142 s32 return_value = 1;
143 u32 current_file_selection;
144 u32 current_file_scroll_value;
145 u32 current_dir_selection;
146 u32 current_dir_scroll_value;
147 u32 current_file_in_scroll;
148 u32 current_dir_in_scroll;
149 u32 current_file_number, current_dir_number;
150 u32 current_column = 0;
153 gui_action_type gui_action;
155 while(return_value == 1)
157 current_file_selection = 0;
158 current_file_scroll_value = 0;
159 current_dir_selection = 0;
160 current_dir_scroll_value = 0;
161 current_file_in_scroll = 0;
162 current_dir_in_scroll = 0;
164 total_filenames_allocated = 32;
165 total_dirnames_allocated = 32;
166 file_list = (u8 **)malloc(sizeof(u8 *) * 32);
167 dir_list = (u8 **)malloc(sizeof(u8 *) * 32);
168 memset(file_list, 0, sizeof(u8 *) * 32);
169 memset(dir_list, 0, sizeof(u8 *) * 32);
176 getcwd(current_dir_name, MAX_PATH);
178 current_dir = opendir(current_dir_name);
183 current_file = readdir(current_dir);
189 file_name = current_file->d_name;
190 file_name_length = strlen(file_name);
192 if((stat(file_name, &file_info) >= 0) &&
193 ((file_name[0] != '.') || (file_name[1] == '.')))
195 if(S_ISDIR(file_info.st_mode))
198 (u8 *)malloc(file_name_length + 1);
200 sprintf(dir_list[num_dirs], "%s", file_name);
206 // Must match one of the wildcards, also ignore the .
207 if(file_name_length >= 4)
209 if(file_name[file_name_length - 4] == '.')
210 ext_pos = file_name_length - 4;
213 if(file_name[file_name_length - 3] == '.')
214 ext_pos = file_name_length - 3;
219 for(i = 0; wildcards[i] != NULL; i++)
221 if(!strcasecmp((file_name + ext_pos),
224 file_list[num_files] =
225 (u8 *)malloc(file_name_length + 1);
227 sprintf(file_list[num_files], "%s", file_name);
237 if(num_files == total_filenames_allocated)
239 file_list = (u8 **)realloc(file_list, sizeof(u8 *) *
240 total_filenames_allocated * 2);
241 memset(file_list + total_filenames_allocated, 0,
242 sizeof(u8 *) * total_filenames_allocated);
243 total_filenames_allocated *= 2;
246 if(num_dirs == total_dirnames_allocated)
248 dir_list = (u8 **)realloc(dir_list, sizeof(u8 *) *
249 total_dirnames_allocated * 2);
250 memset(dir_list + total_dirnames_allocated, 0,
251 sizeof(u8 *) * total_dirnames_allocated);
252 total_dirnames_allocated *= 2;
255 } while(current_file);
257 qsort((void *)file_list, num_files, sizeof(u8 *), sort_function);
258 qsort((void *)dir_list, num_dirs, sizeof(u8 *), sort_function);
260 closedir(current_dir);
262 current_dir_length = strlen(current_dir_name);
264 if(current_dir_length > 80)
268 snprintf(current_dir_short, 80,
269 "...%s", current_dir_name + current_dir_length - 77);
271 memcpy(current_dir_short, "...", 3);
272 memcpy(current_dir_short + 3,
273 current_dir_name + current_dir_length - 77, 77);
274 current_dir_short[80] = 0;
280 snprintf(current_dir_short, 80, "%s", current_dir_name);
282 memcpy(current_dir_short, current_dir_name,
283 current_dir_length + 1);
292 clear_screen(COLOR_BG);
300 print_string(current_dir_short, COLOR_ACTIVE_ITEM, COLOR_BG, 0, 0);
302 print_string("Press X to return to the main menu.",
303 COLOR_HELP_TEXT, COLOR_BG, 20, 220);
305 print_string("Press X to return to the main menu.",
306 COLOR_HELP_TEXT, COLOR_BG, 20, 260);
309 for(i = 0, current_file_number = i + current_file_scroll_value;
310 i < FILE_LIST_ROWS; i++, current_file_number++)
312 if(current_file_number < num_files)
314 if((current_file_number == current_file_selection) &&
315 (current_column == 0))
317 print_string(file_list[current_file_number], COLOR_ACTIVE_ITEM,
318 COLOR_BG, FILE_LIST_POSITION, ((i + 1) * 10));
322 print_string(file_list[current_file_number], COLOR_INACTIVE_ITEM,
323 COLOR_BG, FILE_LIST_POSITION, ((i + 1) * 10));
328 for(i = 0, current_dir_number = i + current_dir_scroll_value;
329 i < FILE_LIST_ROWS; i++, current_dir_number++)
331 if(current_dir_number < num_dirs)
333 if((current_dir_number == current_dir_selection) &&
334 (current_column == 1))
336 print_string(dir_list[current_dir_number], COLOR_ACTIVE_ITEM,
337 COLOR_BG, DIR_LIST_POSITION, ((i + 1) * 10));
341 print_string(dir_list[current_dir_number], COLOR_INACTIVE_ITEM,
342 COLOR_BG, DIR_LIST_POSITION, ((i + 1) * 10));
347 gui_action = get_gui_input();
352 if(current_column == 0)
354 if(current_file_selection < (num_files - 1))
356 current_file_selection++;
357 if(current_file_in_scroll == (FILE_LIST_ROWS - 1))
359 clear_screen(COLOR_BG);
360 current_file_scroll_value++;
364 current_file_in_scroll++;
370 if(current_dir_selection < (num_dirs - 1))
372 current_dir_selection++;
373 if(current_dir_in_scroll == (FILE_LIST_ROWS - 1))
375 clear_screen(COLOR_BG);
376 current_dir_scroll_value++;
380 current_dir_in_scroll++;
388 if(current_column == 0)
390 if(current_file_selection)
392 current_file_selection--;
393 if(current_file_in_scroll == 0)
395 clear_screen(COLOR_BG);
396 current_file_scroll_value--;
400 current_file_in_scroll--;
406 if(current_dir_selection)
408 current_dir_selection--;
409 if(current_dir_in_scroll == 0)
411 clear_screen(COLOR_BG);
412 current_dir_scroll_value--;
416 current_dir_in_scroll--;
423 if(current_column == 0)
431 if(current_column == 1)
439 if(current_column == 1)
442 chdir(dir_list[current_dir_selection]);
450 strcpy(result, file_list[current_file_selection]);
457 if(!strcmp(current_dir_name, "ms0:/PSP"))
472 for(i = 0; i < num_files; i++)
478 for(i = 0; i < num_dirs; i++)
485 clear_screen(COLOR_BG);
492 NUMBER_SELECTION_OPTION = 0x01,
493 STRING_SELECTION_OPTION = 0x02,
494 SUBMENU_OPTION = 0x04,
496 } menu_option_type_enum;
500 void (* init_function)();
501 void (* passive_function)();
502 struct _menu_option_type *options;
506 struct _menu_option_type
508 void (* action_function)();
509 void (* passive_function)();
510 struct _menu_type *sub_menu;
511 char *display_string;
517 menu_option_type_enum option_type;
520 typedef struct _menu_option_type menu_option_type;
521 typedef struct _menu_type menu_type;
523 #define make_menu(name, init_function, passive_function) \
524 menu_type name##_menu = \
529 sizeof(name##_options) / sizeof(menu_option_type) \
532 #define gamepad_config_option(display_string, number) \
535 menu_fix_gamepad_help, \
537 display_string ": %s", \
538 gamepad_config_buttons, \
539 gamepad_config_map + gamepad_config_line_to_button[number], \
540 sizeof(gamepad_config_buttons) / sizeof(gamepad_config_buttons[0]), \
541 gamepad_help[gamepad_config_map[ \
542 gamepad_config_line_to_button[number]]], \
544 STRING_SELECTION_OPTION \
547 #define analog_config_option(display_string, number) \
550 menu_fix_gamepad_help, \
552 display_string ": %s", \
553 gamepad_config_buttons, \
554 gamepad_config_map + number + 12, \
555 sizeof(gamepad_config_buttons) / sizeof(gamepad_config_buttons[0]), \
556 gamepad_help[gamepad_config_map[number + 12]], \
558 STRING_SELECTION_OPTION \
561 #define cheat_option(number) \
566 cheat_format_str[number], \
567 enable_disable_options, \
568 &(cheats[number].cheat_active), \
570 "Activate/deactivate this cheat code.", \
572 STRING_SELECTION_OPTION \
575 #define action_option(action_function, passive_function, display_string, \
576 help_string, line_number) \
590 #define submenu_option(sub_menu, display_string, help_string, line_number) \
598 sizeof(sub_menu) / sizeof(menu_option_type), \
604 #define selection_option(passive_function, display_string, options, \
605 option_ptr, num_options, help_string, line_number, type) \
619 #define action_selection_option(action_function, passive_function, \
620 display_string, options, option_ptr, num_options, help_string, line_number, \
632 type | ACTION_OPTION \
636 #define string_selection_option(passive_function, display_string, options, \
637 option_ptr, num_options, help_string, line_number) \
638 selection_option(passive_function, display_string ": %s", options, \
639 option_ptr, num_options, help_string, line_number, STRING_SELECTION_OPTION)\
641 #define numeric_selection_option(passive_function, display_string, \
642 option_ptr, num_options, help_string, line_number) \
643 selection_option(passive_function, display_string ": %d", NULL, option_ptr, \
644 num_options, help_string, line_number, NUMBER_SELECTION_OPTION) \
646 #define string_selection_action_option(action_function, passive_function, \
647 display_string, options, option_ptr, num_options, help_string, line_number) \
648 action_selection_option(action_function, passive_function, \
649 display_string ": %s", options, option_ptr, num_options, help_string, \
650 line_number, STRING_SELECTION_OPTION) \
652 #define numeric_selection_action_option(action_function, passive_function, \
653 display_string, option_ptr, num_options, help_string, line_number) \
654 action_selection_option(action_function, passive_function, \
655 display_string ": %d", NULL, option_ptr, num_options, help_string, \
656 line_number, NUMBER_SELECTION_OPTION) \
658 #define numeric_selection_action_hide_option(action_function, \
659 passive_function, display_string, option_ptr, num_options, help_string, \
661 action_selection_option(action_function, passive_function, \
662 display_string, NULL, option_ptr, num_options, help_string, \
663 line_number, NUMBER_SELECTION_OPTION) \
666 #define GAMEPAD_MENU_WIDTH 15
670 u32 gamepad_config_line_to_button[] =
671 { 8, 6, 7, 9, 1, 2, 3, 0, 4, 5, 11, 10 };
677 u32 gamepad_config_line_to_button[] =
678 { 0, 2, 1, 3, 8, 9, 10, 11, 6, 7, 4, 5, 14 };
683 s32 load_game_config_file()
685 u8 game_config_filename[512];
688 change_ext(gamepak_filename, game_config_filename, ".cfg");
690 file_open(game_config_file, game_config_filename, read);
692 if(file_check_valid(game_config_file))
694 u32 file_size = file_length(game_config_filename, game_config_file);
696 // Sanity check: File size must be the right size
699 u32 file_options[file_size / 4];
701 file_read_array(game_config_file, file_options);
702 current_frameskip_type = file_options[0] % 3;
703 frameskip_value = file_options[1];
704 random_skip = file_options[2] % 2;
705 clock_speed = file_options[3];
708 if(clock_speed > 900)
710 #elif defined(GP2X_BUILD)
711 if(clock_speed >= 300)
714 if(clock_speed > 333)
721 if(frameskip_value < 0)
724 if(frameskip_value > 99)
725 frameskip_value = 99;
727 for(i = 0; i < 10; i++)
729 cheats[i].cheat_active = file_options[3 + i] % 2;
730 cheats[i].cheat_name[0] = 0;
733 file_close(game_config_file);
741 current_frameskip_type = auto_frameskip;
747 clock_speed = default_clock_speed;
749 for(i = 0; i < 10; i++)
751 cheats[i].cheat_active = 0;
752 cheats[i].cheat_name[0] = 0;
758 s32 load_config_file()
762 #if (defined(PSP_BUILD) || defined(ARM_ARCH)) && !defined(_WIN32_WCE)
763 sprintf(config_path, "%s/%s", main_path, GPSP_CONFIG_FILENAME);
765 sprintf(config_path, "%s\\%s", main_path, GPSP_CONFIG_FILENAME);
768 file_open(config_file, config_path, read);
770 if(file_check_valid(config_file))
772 u32 file_size = file_length(config_path, config_file);
774 // Sanity check: File size must be the right size
777 u32 file_options[file_size / 4];
779 s32 menu_button = -1;
780 file_read_array(config_file, file_options);
782 screen_scale = file_options[0] % 3;
783 screen_filter = file_options[1] % 2;
784 global_enable_audio = file_options[2] % 2;
787 audio_buffer_size_number = file_options[3] % 10;
789 audio_buffer_size_number = file_options[3] % 11;
792 update_backup_flag = file_options[4] % 2;
793 global_enable_analog = file_options[5] % 2;
794 analog_sensitivity_level = file_options[6] % 8;
797 scePowerSetClockFrequency(clock_speed, clock_speed, clock_speed / 2);
800 // Sanity check: Make sure there's a MENU or FRAMESKIP
801 // key, if not assign to triangle
804 for(i = 0; i < 16; i++)
806 gamepad_config_map[i] = file_options[7 + i] %
807 (BUTTON_ID_NONE + 1);
809 if(gamepad_config_map[i] == BUTTON_ID_MENU)
815 if(menu_button == -1)
817 gamepad_config_map[0] = BUTTON_ID_MENU;
821 file_close(config_file);
830 s32 save_game_config_file()
832 u8 game_config_filename[512];
835 change_ext(gamepak_filename, game_config_filename, ".cfg");
837 file_open(game_config_file, game_config_filename, write);
839 if(file_check_valid(game_config_file))
841 u32 file_options[14];
843 file_options[0] = current_frameskip_type;
844 file_options[1] = frameskip_value;
845 file_options[2] = random_skip;
846 file_options[3] = clock_speed;
848 for(i = 0; i < 10; i++)
850 file_options[4 + i] = cheats[i].cheat_active;
853 file_write_array(game_config_file, file_options);
855 file_close(game_config_file);
863 s32 save_config_file()
867 #if (defined(PSP_BUILD) || defined(ARM_ARCH)) && !defined(_WIN32_WCE)
868 sprintf(config_path, "%s/%s", main_path, GPSP_CONFIG_FILENAME);
870 sprintf(config_path, "%s\\%s", main_path, GPSP_CONFIG_FILENAME);
873 file_open(config_file, config_path, write);
875 save_game_config_file();
877 if(file_check_valid(config_file))
879 u32 file_options[23];
882 file_options[0] = screen_scale;
883 file_options[1] = screen_filter;
884 file_options[2] = global_enable_audio;
885 file_options[3] = audio_buffer_size_number;
886 file_options[4] = update_backup_flag;
887 file_options[5] = global_enable_analog;
888 file_options[6] = analog_sensitivity_level;
891 for(i = 0; i < 16; i++)
893 file_options[7 + i] = gamepad_config_map[i];
897 file_write_array(config_file, file_options);
899 file_close(config_file);
916 u32 savestate_slot = 0;
918 void get_savestate_snapshot(u8 *savestate_filename)
920 u16 snapshot_buffer[240 * 160];
921 u8 savestate_timestamp_string[80];
923 file_open(savestate_file, savestate_filename, read);
925 if(file_check_valid(savestate_file))
927 u8 weekday_strings[7][11] =
929 "Sunday", "Monday", "Tuesday", "Wednesday",
930 "Thursday", "Friday", "Saturday"
932 time_t savestate_time_flat;
933 struct tm *current_time;
934 file_read_array(savestate_file, snapshot_buffer);
935 file_read_variable(savestate_file, savestate_time_flat);
937 file_close(savestate_file);
939 current_time = localtime(&savestate_time_flat);
940 sprintf(savestate_timestamp_string,
941 "%s %02d/%02d/%04d %02d:%02d:%02d ",
942 weekday_strings[current_time->tm_wday], current_time->tm_mon + 1,
943 current_time->tm_mday, current_time->tm_year + 1900,
944 current_time->tm_hour, current_time->tm_min, current_time->tm_sec);
946 savestate_timestamp_string[40] = 0;
947 print_string(savestate_timestamp_string, COLOR_HELP_TEXT, COLOR_BG,
952 memset(snapshot_buffer, 0, 240 * 160 * 2);
953 print_string_ext("No savestate exists for this slot.",
954 0xFFFF, 0x0000, 15, 75, snapshot_buffer, 240, 0);
955 print_string("---------- --/--/---- --:--:-- ", COLOR_HELP_TEXT,
960 blit_to_screen(snapshot_buffer, 240, 160, 230, 40);
964 void get_savestate_filename(u32 slot, u8 *name_buffer)
966 u8 savestate_ext[16];
968 sprintf(savestate_ext, "%d.svs", slot);
969 change_ext(gamepak_filename, name_buffer, savestate_ext);
971 get_savestate_snapshot(name_buffer);
974 void get_savestate_filename_noshot(u32 slot, u8 *name_buffer)
976 u8 savestate_ext[16];
978 sprintf(savestate_ext, "%d.svs", slot);
979 change_ext(gamepak_filename, name_buffer, savestate_ext);
985 invalidate_all_cache();
989 u32 menu(u16 *original_screen)
991 u32 clock_speed_number;
992 static u32 clock_speed_old = default_clock_speed;
994 u32 _current_option = 0;
995 gui_action_type gui_action;
996 menu_enum _current_menu = MAIN_MENU;
999 u32 return_value = 0;
1001 u8 savestate_ext[16];
1002 u8 current_savestate_filename[512];
1004 u8 cheat_format_str[10][41];
1006 menu_type *current_menu;
1007 menu_option_type *current_option;
1008 menu_option_type *display_option;
1009 u32 current_option_num;
1011 auto void choose_menu();
1012 auto void clear_help();
1014 u8 *gamepad_help[] =
1016 "Up button on GBA d-pad.",
1017 "Down button on GBA d-pad.",
1018 "Left button on GBA d-pad.",
1019 "Right button on GBA d-pad.",
1022 "Left shoulder button on GBA.",
1023 "Right shoulder button on GBA.",
1024 "Start button on GBA.",
1025 "Select button on GBA.",
1026 "Brings up the options menu.",
1027 "Toggles fastforward on/off.",
1028 "Loads the game state from the current slot.",
1029 "Saves the game state to the current slot.",
1030 "Rapidly press/release the A button on GBA.",
1031 "Rapidly press/release the B button on GBA.",
1032 "Rapidly press/release the L shoulder on GBA.",
1033 "Rapidly press/release the R shoulder on GBA.",
1034 "Increases the volume.",
1035 "Decreases the volume.",
1036 "Displays virtual/drawn frames per second.",
1055 u8 *file_ext[] = { ".gba", ".bin", ".zip", NULL };
1056 u8 load_filename[512];
1057 save_game_config_file();
1058 if(load_file(file_ext, load_filename) != -1)
1060 if(load_gamepak(load_filename) == -1)
1067 reg[CHANGED_PC_STATUS] = 1;
1071 choose_menu(current_menu);
1080 reg[CHANGED_PC_STATUS] = 1;
1086 void menu_change_state()
1088 get_savestate_filename(savestate_slot, current_savestate_filename);
1091 void menu_save_state()
1095 get_savestate_filename_noshot(savestate_slot,
1096 current_savestate_filename);
1097 save_state(current_savestate_filename, original_screen);
1099 menu_change_state();
1102 void menu_load_state()
1106 load_state(current_savestate_filename);
1112 void menu_load_state_file()
1114 u8 *file_ext[] = { ".svs", NULL };
1115 u8 load_filename[512];
1116 if(load_file(file_ext, load_filename) != -1)
1118 load_state(load_filename);
1124 choose_menu(current_menu);
1128 void menu_fix_gamepad_help()
1132 current_option->help_string =
1133 gamepad_help[gamepad_config_map[
1134 gamepad_config_line_to_button[current_option_num]]];
1138 void submenu_graphics_sound()
1143 void submenu_cheats_misc()
1148 void submenu_gamepad()
1153 void submenu_analog()
1158 void submenu_savestate()
1160 print_string("Savestate options:", COLOR_ACTIVE_ITEM, COLOR_BG, 10, 70);
1161 menu_change_state();
1166 strncpy(print_buffer, gamepak_filename, 80);
1167 print_string(print_buffer, COLOR_ROM_INFO, COLOR_BG, 10, 10);
1168 sprintf(print_buffer, "%s %s %s", gamepak_title,
1169 gamepak_code, gamepak_maker);
1170 print_string(print_buffer, COLOR_ROM_INFO, COLOR_BG, 10, 20);
1172 get_savestate_filename_noshot(savestate_slot,
1173 current_savestate_filename);
1176 u8 *yes_no_options[] = { "no", "yes" };
1177 u8 *enable_disable_options[] = { "disabled", "enabled" };
1179 u8 *scale_options[] =
1182 "unscaled 3:2", "scaled 3:2 (slower)"
1184 "unscaled 3:2", "scaled 3:2", "fullscreen"
1191 u8 *frameskip_options[] = { "automatic", "manual", "off" };
1192 u8 *frameskip_variation_options[] = { "uniform", "random" };
1195 u8 *audio_buffer_options[] =
1197 "16 bytes", "32 bytes", "64 bytes",
1198 "128 bytes", "256 bytes", "512 bytes", "1024 bytes", "2048 bytes",
1199 "4096 bytes", "8192 bytes", "16284 bytes"
1202 u8 *audio_buffer_options[] =
1204 "3072 bytes", "4096 bytes", "5120 bytes", "6144 bytes", "7168 bytes",
1205 "8192 bytes", "9216 bytes", "10240 bytes", "11264 bytes", "12288 bytes"
1210 u8 *update_backup_options[] = { "Exit only", "Automatic" };
1213 u8 *clock_speed_options[] =
1215 "300MHz", "333MHz", "366MHz", "400MHz", "433MHz",
1216 "466MHz", "500MHz", "533MHz", "566MHz", "600MHz",
1217 "633MHz", "666MHz", "700MHz", "733MHz", "766MHz",
1218 "800MHz", "833MHz", "866MHz", "900MHz"
1220 #elif defined(GP2X_BUILD)
1221 u8 *clock_speed_options[] =
1223 "150MHz", "160MHz", "170MHz", "180MHz", "190MHz",
1224 "200MHz", "210MHz", "220MHz", "230MHz", "240MHz",
1225 "250MHz", "260MHz", "270MHz", "280MHz", "290MHz"
1228 u8 *clock_speed_options[] =
1230 "33MHz", "66MHz", "100MHz", "133MHz", "166MHz", "200MHz", "233MHz",
1231 "266MHz", "300MHz", "333MHz"
1235 u8 *gamepad_config_buttons[] =
1261 // Marker for help information, don't go past this mark (except \n)------*
1262 menu_option_type graphics_sound_options[] =
1264 string_selection_option(NULL, "Display scaling", scale_options,
1265 (u32 *)(&screen_scale),
1272 "Determines how the GBA screen is resized in relation to the entire\n"
1273 "screen. Select unscaled 3:2 for GBA resolution, scaled 3:2 for GBA\n"
1274 "aspect ratio scaled to fill the height of the PSP screen, and\n"
1275 "fullscreen to fill the entire PSP screen."
1279 string_selection_option(NULL, "Screen filtering", yes_no_options,
1280 (u32 *)(&screen_filter), 2,
1281 "Determines whether or not bilinear filtering should be used when\n"
1282 "scaling the screen. Selecting this will produce a more even and\n"
1283 "smooth image, at the cost of being blurry and having less vibrant\n"
1286 string_selection_option(NULL, "Frameskip type", frameskip_options,
1287 (u32 *)(¤t_frameskip_type), 3,
1289 "Determines what kind of frameskipping to use.\n"
1290 "Frameskipping may improve emulation speed of many games.\n"
1292 "Off: Do not skip any frames.\n"
1293 "Auto: Skip up to N frames (see next opt) as needed.\n"
1294 "Manual: Always render only 1 out of N + 1 frames."
1296 numeric_selection_option(NULL, "Frameskip value", &frameskip_value, 100,
1298 "For auto frameskip, determines the maximum number of frames that\n"
1299 "are allowed to be skipped consecutively.\n"
1300 "For manual frameskip, determines the number of frames that will\n"
1301 "always be skipped."
1304 string_selection_option(NULL, "Framskip variation",
1305 frameskip_variation_options, &random_skip, 2,
1307 "If objects in the game flicker at a regular rate certain manual\n"
1308 "frameskip values may cause them to normally disappear. Change this\n"
1309 "value to 'random' to avoid this. Do not use otherwise, as it tends to\n"
1310 "make the image quality worse, especially in high motion games."
1313 string_selection_option(NULL, "Audio output", yes_no_options,
1314 &global_enable_audio, 2,
1315 "Select 'no' to turn off all audio output. This will\n"
1316 "not result in a significant change in performance.", 9),
1318 string_selection_option(NULL, "Audio buffer", audio_buffer_options,
1319 &audio_buffer_size_number, 11,
1321 string_selection_option(NULL, "Audio buffer", audio_buffer_options,
1322 &audio_buffer_size_number, 10,
1326 "Set the size (in bytes) of the audio buffer. Larger values may result\n"
1327 "in slightly better performance at the cost of latency; the lowest\n"
1328 "value will give the most responsive audio.\n"
1329 "This option requires gpSP to be restarted before it will take effect.",
1331 "Set the size (in bytes) of the audio buffer.\n"
1332 "This option requires gpSP restart to take effect.",
1335 submenu_option(NULL, "Back", "Return to the main menu.", 12)
1338 make_menu(graphics_sound, submenu_graphics_sound, NULL);
1340 menu_option_type cheats_misc_options[] =
1352 string_selection_option(NULL, "Clock speed",
1353 clock_speed_options, &clock_speed_number,
1354 sizeof(clock_speed_options) / sizeof(clock_speed_options[0]),
1355 "Change the clock speed of the device. Higher clock\n"
1356 "speed will yield better performance, but will drain\n"
1357 "battery life further.", 11),
1358 string_selection_option(NULL, "Update backup",
1359 update_backup_options, &update_backup_flag, 2,
1361 "Determines when in-game save files should be\n"
1362 "written back to SD card.",
1364 "Determines when in-game save files should be written back to\n"
1365 "memstick. If set to 'automatic' writebacks will occur shortly after\n"
1366 "the game's backup is altered. On 'exit only' it will only be written\n"
1367 "back when you exit from this menu (NOT from using the home button).\n"
1368 "Use the latter with extreme care.",
1371 submenu_option(NULL, "Back", "Return to the main menu.", 14)
1374 make_menu(cheats_misc, submenu_cheats_misc, NULL);
1376 menu_option_type savestate_options[] =
1378 numeric_selection_action_hide_option(menu_load_state, menu_change_state,
1379 "Load savestate from current slot", &savestate_slot, 10,
1380 "Select to load the game state from the current slot\n"
1382 "Press left + right to change the current slot.", 6),
1383 numeric_selection_action_hide_option(menu_save_state, menu_change_state,
1384 "Save savestate to current slot", &savestate_slot, 10,
1385 "Select to save the game state to the current slot\n"
1387 "Press left + right to change the current slot.", 7),
1388 numeric_selection_action_hide_option(menu_load_state_file,
1390 "Load savestate from file", &savestate_slot, 10,
1391 "Restore gameplay from a savestate file.\n"
1392 "Note: The same file used to save the state must be\n"
1394 numeric_selection_option(menu_change_state,
1395 "Current savestate slot", &savestate_slot, 10,
1396 "Change the current savestate slot.\n", 11),
1397 submenu_option(NULL, "Back", "Return to the main menu.", 13)
1400 make_menu(savestate, submenu_savestate, NULL);
1404 menu_option_type gamepad_config_options[] =
1406 gamepad_config_option("D-pad up ", 0),
1407 gamepad_config_option("D-pad down ", 1),
1408 gamepad_config_option("D-pad left ", 2),
1409 gamepad_config_option("D-pad right ", 3),
1410 gamepad_config_option("Circle ", 4),
1411 gamepad_config_option("Cross ", 5),
1412 gamepad_config_option("Square ", 6),
1413 gamepad_config_option("Triangle ", 7),
1414 gamepad_config_option("Left Trigger ", 8),
1415 gamepad_config_option("Right Trigger", 9),
1416 gamepad_config_option("Start ", 10),
1417 gamepad_config_option("Select ", 11),
1418 submenu_option(NULL, "Back", "Return to the main menu.", 13)
1422 menu_option_type analog_config_options[] =
1424 analog_config_option("Analog up ", 0),
1425 analog_config_option("Analog down ", 1),
1426 analog_config_option("Analog left ", 2),
1427 analog_config_option("Analog right", 3),
1428 string_selection_option(NULL, "Enable analog", yes_no_options,
1429 &global_enable_analog, 2,
1430 "Select 'no' to block analog input entirely.", 7),
1431 numeric_selection_option(NULL, "Analog sensitivity",
1432 &analog_sensitivity_level, 10,
1433 "Determine sensitivity/responsiveness of the analog input.\n"
1434 "Lower numbers are less sensitive.", 8),
1435 submenu_option(NULL, "Back", "Return to the main menu.", 11)
1442 menu_option_type gamepad_config_options[] =
1444 gamepad_config_option("D-pad up ", 0),
1445 gamepad_config_option("D-pad down ", 1),
1446 gamepad_config_option("D-pad left ", 2),
1447 gamepad_config_option("D-pad right ", 3),
1448 gamepad_config_option("A ", 4),
1449 gamepad_config_option("B ", 5),
1450 gamepad_config_option("X ", 6),
1451 gamepad_config_option("Y ", 7),
1452 gamepad_config_option("Left Trigger ", 8),
1453 gamepad_config_option("Right Trigger", 9),
1455 gamepad_config_option("Menu ", 10),
1457 gamepad_config_option("Start ", 10),
1459 gamepad_config_option("Select ", 11),
1461 gamepad_config_option("Stick Push ", 12),
1463 submenu_option(NULL, "Back", "Return to the main menu.", 14)
1467 menu_option_type analog_config_options[] =
1469 submenu_option(NULL, "Back", "Return to the main menu.", 11)
1476 menu_option_type gamepad_config_options[] =
1478 submenu_option(NULL, "Back", "Return to the main menu.", 13)
1481 menu_option_type analog_config_options[] =
1483 submenu_option(NULL, "Back", "Return to the main menu.", 11)
1488 make_menu(gamepad_config, submenu_gamepad, NULL);
1489 make_menu(analog_config, submenu_analog, NULL);
1491 menu_option_type main_options[] =
1493 submenu_option(&graphics_sound_menu, "Graphics and Sound options",
1494 "Select to set display parameters and frameskip\n"
1495 "behavior, audio on/off, buffer size, and filtering.", 0),
1496 numeric_selection_action_option(menu_load_state, NULL,
1497 "Load state from slot", &savestate_slot, 10,
1498 "Select to load the game state from the current slot\n"
1499 "for this game, if it exists.\n"
1500 "Press left + right to change the current slot.", 2),
1501 numeric_selection_action_option(menu_save_state, NULL,
1502 "Save state to slot", &savestate_slot, 10,
1503 "Select to save the game state to the current slot\n"
1504 "for this game. See the extended menu for more info.\n"
1505 "Press left + right to change the current slot.", 3),
1506 submenu_option(&savestate_menu, "Savestate options",
1507 "Select to enter a menu for loading, saving, and\n"
1508 "viewing the currently active savestate for this game\n"
1509 "(or to load a savestate file from another game)", 4),
1510 submenu_option(&gamepad_config_menu, "Configure gamepad input",
1511 "Select to change the in-game behavior of buttons\n"
1514 submenu_option(&analog_config_menu, "Configure analog input",
1515 "Select to change the in-game behavior of the PSP analog nub.", 7),
1517 submenu_option(&cheats_misc_menu, "Cheats and Miscellaneous options",
1518 "Select to manage cheats, set backup behavior,\n"
1519 "and set device clock speed.", 9),
1520 action_option(menu_load, NULL, "Load new game",
1521 "Select to load a new game\n"
1522 "(will exit a game if currently playing).", 11),
1523 action_option(menu_restart, NULL, "Restart game",
1524 "Select to reset the GBA with the current game\n"
1526 action_option(menu_exit, NULL, "Return to game",
1527 "Select to exit this menu and resume gameplay.", 13),
1528 action_option(menu_quit, NULL, "Exit gpSP",
1529 "Select to exit gpSP and return to the menu.", 15)
1532 make_menu(main, submenu_main, NULL);
1534 void choose_menu(menu_type *new_menu)
1536 if(new_menu == NULL)
1537 new_menu = &main_menu;
1539 clear_screen(COLOR_BG);
1542 blit_to_screen(original_screen, 240, 160, 230, 40);
1545 current_menu = new_menu;
1546 current_option = new_menu->options;
1547 current_option_num = 0;
1548 if(current_menu->init_function)
1549 current_menu->init_function();
1554 for(i = 0; i < 6; i++)
1556 print_string_pad(" ", COLOR_BG, COLOR_BG, 8, 210 + (i * 10), 70);
1560 get_clock_speed_number();
1561 if (clock_speed_number < 0 || clock_speed_number >=
1562 sizeof(clock_speed_options) / sizeof(clock_speed_options[0]))
1564 clock_speed = default_clock_speed;
1565 get_clock_speed_number();
1568 video_resolution_large();
1571 SDL_LockMutex(sound_mutex);
1576 SDL_UnlockMutex(sound_mutex);
1579 if(gamepak_filename[0] == 0)
1582 memset(original_screen, 0x00, 240 * 160 * 2);
1583 print_string_ext("No game loaded yet.", 0xFFFF, 0x0000,
1584 60, 75,original_screen, 240, 0);
1587 choose_menu(&main_menu);
1589 for(i = 0; i < 10; i++)
1593 sprintf(cheat_format_str[i], "cheat %d (none loaded)", i);
1597 sprintf(cheat_format_str[i], "cheat %d (%s): %%s", i,
1598 cheats[i].cheat_name);
1602 current_menu->init_function();
1606 display_option = current_menu->options;
1608 for(i = 0; i < current_menu->num_options; i++, display_option++)
1610 if(display_option->option_type & NUMBER_SELECTION_OPTION)
1612 sprintf(line_buffer, display_option->display_string,
1613 *(display_option->current_option));
1617 if(display_option->option_type & STRING_SELECTION_OPTION)
1619 sprintf(line_buffer, display_option->display_string,
1620 ((u32 *)display_option->options)[*(display_option->current_option)]);
1624 strcpy(line_buffer, display_option->display_string);
1627 if(display_option == current_option)
1629 print_string_pad(line_buffer, COLOR_ACTIVE_ITEM, COLOR_BG, 10,
1630 (display_option->line_number * 10) + 40, 36);
1634 print_string_pad(line_buffer, COLOR_INACTIVE_ITEM, COLOR_BG, 10,
1635 (display_option->line_number * 10) + 40, 36);
1639 print_string(current_option->help_string, COLOR_HELP_TEXT,
1644 gui_action = get_gui_input();
1649 current_option_num = (current_option_num + 1) %
1650 current_menu->num_options;
1652 current_option = current_menu->options + current_option_num;
1657 if(current_option_num)
1658 current_option_num--;
1660 current_option_num = current_menu->num_options - 1;
1662 current_option = current_menu->options + current_option_num;
1667 if(current_option->option_type & (NUMBER_SELECTION_OPTION |
1668 STRING_SELECTION_OPTION))
1670 *(current_option->current_option) =
1671 (*current_option->current_option + 1) %
1672 current_option->num_options;
1674 if(current_option->passive_function)
1675 current_option->passive_function();
1680 if(current_option->option_type & (NUMBER_SELECTION_OPTION |
1681 STRING_SELECTION_OPTION))
1683 u32 current_option_val = *(current_option->current_option);
1685 if(current_option_val)
1686 current_option_val--;
1688 current_option_val = current_option->num_options - 1;
1690 *(current_option->current_option) = current_option_val;
1692 if(current_option->passive_function)
1693 current_option->passive_function();
1698 if(current_menu == &main_menu)
1701 choose_menu(&main_menu);
1705 if(current_option->option_type & ACTION_OPTION)
1706 current_option->action_function();
1708 if(current_option->option_type & SUBMENU_OPTION)
1709 choose_menu(current_option->sub_menu);
1714 set_gba_resolution(screen_scale);
1715 video_resolution_small();
1718 if (clock_speed != clock_speed_old)
1720 printf("about to set CPU clock to %iMHz\n", clock_speed);
1722 scePowerSetClockFrequency(clock_speed, clock_speed, clock_speed / 2);
1723 #elif defined(GP2X_BUILD)
1724 set_FCLK(clock_speed);
1726 clock_speed_old = clock_speed;
1731 return return_value;