📄 gui.c
字号:
/* gameplaySP * * Copyright (C) 2006 Exophase <exophase@gmail.com> * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public Licens e as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include <sys/stat.h>#include <unistd.h>#include <ctype.h>#include <dirent.h>#include "common.h"#define MAX_PATH 1024// Blatantly stolen and trimmed from MZX (megazeux.sourceforge.net)#define FILE_LIST_ROWS 25#define FILE_LIST_POSITION 5#define DIR_LIST_POSITION 360#ifdef PSP_BUILD#define color16(red, green, blue) \ (blue << 11) | (green << 5) | red \#else#define color16(red, green, blue) \ (red << 11) | (green << 5) | blue \#endif#define COLOR_BG color16(2, 8, 10)#define COLOR_ROM_INFO color16(22, 36, 26)#define COLOR_ACTIVE_ITEM color16(31, 63, 31)#define COLOR_INACTIVE_ITEM color16(13, 40, 18)#define COLOR_FRAMESKIP_BAR color16(15, 31, 31)#define COLOR_HELP_TEXT color16(16, 40, 24)int sort_function(const void *dest_str_ptr, const void *src_str_ptr){ char *dest_str = *((char **)dest_str_ptr); char *src_str = *((char **)src_str_ptr); if(src_str[0] == '.') return 1; if(dest_str[0] == '.') return -1; return strcasecmp(dest_str, src_str);}s32 load_file(u8 **wildcards, u8 *result){ DIR *current_dir; struct dirent *current_file; struct stat file_info; u8 current_dir_name[MAX_PATH]; u8 current_dir_short[81]; u32 current_dir_length; u32 total_filenames_allocated; u32 total_dirnames_allocated; u8 **file_list; u8 **dir_list; u32 num_files; u32 num_dirs; u8 *file_name; u32 file_name_length; u32 ext_pos = -1; u32 chosen_file, chosen_dir; u32 dialog_result = 1; s32 return_value = 1; u32 current_file_selection; u32 current_file_scroll_value; u32 current_dir_selection; u32 current_dir_scroll_value; u32 current_file_in_scroll; u32 current_dir_in_scroll; u32 current_file_number, current_dir_number; u32 current_column = 0; u32 repeat; u32 i; gui_action_type gui_action; while(return_value == 1) { current_file_selection = 0; current_file_scroll_value = 0; current_dir_selection = 0; current_dir_scroll_value = 0; current_file_in_scroll = 0; current_dir_in_scroll = 0; total_filenames_allocated = 32; total_dirnames_allocated = 32; file_list = (u8 **)malloc(sizeof(u8 *) * 32); dir_list = (u8 **)malloc(sizeof(u8 *) * 32); memset(file_list, 0, sizeof(u8 *) * 32); memset(dir_list, 0, sizeof(u8 *) * 32); num_files = 0; num_dirs = 0; chosen_file = 0; chosen_dir = 0; getcwd(current_dir_name, MAX_PATH); current_dir = opendir(current_dir_name); do { if(current_dir) current_file = readdir(current_dir); else current_file = NULL; if(current_file) { file_name = current_file->d_name; file_name_length = strlen(file_name); if((stat(file_name, &file_info) >= 0) && ((file_name[0] != '.') || (file_name[1] == '.'))) { if(S_ISDIR(file_info.st_mode)) { dir_list[num_dirs] = (u8 *)malloc(file_name_length + 1); strcpy(dir_list[num_dirs], file_name); num_dirs++; } else { // Must match one of the wildcards, also ignore the . if(file_name_length >= 4) { if(file_name[file_name_length - 4] == '.') ext_pos = file_name_length - 4; else if(file_name[file_name_length - 3] == '.') ext_pos = file_name_length - 3; else ext_pos = 0; for(i = 0; wildcards[i] != NULL; i++) { if(!strcasecmp((file_name + ext_pos), wildcards[i])) { file_list[num_files] = (u8 *)malloc(file_name_length + 1); strcpy(file_list[num_files], file_name); num_files++; break; } } } } } if(num_files == total_filenames_allocated) { file_list = (u8 **)realloc(file_list, sizeof(u8 *) * total_filenames_allocated * 2); memset(file_list + total_filenames_allocated, 0, sizeof(u8 *) * total_filenames_allocated); total_filenames_allocated *= 2; } if(num_dirs == total_dirnames_allocated) { dir_list = (u8 **)realloc(dir_list, sizeof(u8 *) * total_dirnames_allocated * 2); memset(dir_list + total_dirnames_allocated, 0, sizeof(u8 *) * total_dirnames_allocated); total_dirnames_allocated *= 2; } } } while(current_file); qsort((void *)file_list, num_files, sizeof(u8 *), sort_function); qsort((void *)dir_list, num_dirs, sizeof(u8 *), sort_function); closedir(current_dir); current_dir_length = strlen(current_dir_name); if(current_dir_length > 80) { memcpy(current_dir_short, "...", 3); memcpy(current_dir_short + 3, current_dir_name + current_dir_length - 77, 77); current_dir_short[80] = 0; } else { memcpy(current_dir_short, current_dir_name, current_dir_length + 1); } repeat = 1; if(num_files == 0) current_column = 1; clear_screen(COLOR_BG); u8 print_buffer[81]; while(repeat) { flip_screen(); print_string(current_dir_short, COLOR_ACTIVE_ITEM, COLOR_BG, 0, 0); print_string("Press X to return to the main menu.", COLOR_HELP_TEXT, COLOR_BG, 20, 260); for(i = 0, current_file_number = i + current_file_scroll_value; i < FILE_LIST_ROWS; i++, current_file_number++) { if(current_file_number < num_files) { if((current_file_number == current_file_selection) && (current_column == 0)) { print_string(file_list[current_file_number], COLOR_ACTIVE_ITEM, COLOR_BG, FILE_LIST_POSITION, ((i + 1) * 10)); } else { print_string(file_list[current_file_number], COLOR_INACTIVE_ITEM, COLOR_BG, FILE_LIST_POSITION, ((i + 1) * 10)); } } } for(i = 0, current_dir_number = i + current_dir_scroll_value; i < FILE_LIST_ROWS; i++, current_dir_number++) { if(current_dir_number < num_dirs) { if((current_dir_number == current_dir_selection) && (current_column == 1)) { print_string(dir_list[current_dir_number], COLOR_ACTIVE_ITEM, COLOR_BG, DIR_LIST_POSITION, ((i + 1) * 10)); } else { print_string(dir_list[current_dir_number], COLOR_INACTIVE_ITEM, COLOR_BG, DIR_LIST_POSITION, ((i + 1) * 10)); } } } gui_action = get_gui_input(); switch(gui_action) { case CURSOR_DOWN: if(current_column == 0) { if(current_file_selection < (num_files - 1)) { current_file_selection++; if(current_file_in_scroll == (FILE_LIST_ROWS - 1)) { clear_screen(COLOR_BG); current_file_scroll_value++; } else { current_file_in_scroll++; } } } else { if(current_dir_selection < (num_dirs - 1)) { current_dir_selection++; if(current_dir_in_scroll == (FILE_LIST_ROWS - 1)) { clear_screen(COLOR_BG); current_dir_scroll_value++; } else { current_dir_in_scroll++; } } } break; case CURSOR_UP: if(current_column == 0) { if(current_file_selection) { current_file_selection--; if(current_file_in_scroll == 0) { clear_screen(COLOR_BG); current_file_scroll_value--; } else { current_file_in_scroll--; } } } else { if(current_dir_selection) { current_dir_selection--; if(current_dir_in_scroll == 0) { clear_screen(COLOR_BG); current_dir_scroll_value--; } else { current_dir_in_scroll--; } } } break; case CURSOR_RIGHT: if(current_column == 0) { if(num_dirs != 0) current_column = 1; } break; case CURSOR_LEFT: if(current_column == 1) { if(num_files != 0) current_column = 0; } break; case CURSOR_SELECT: if(current_column == 1) { repeat = 0; chdir(dir_list[current_dir_selection]); } else { if(num_files != 0) { repeat = 0; return_value = 0; strcpy(result, file_list[current_file_selection]); } } break; case CURSOR_BACK:#ifdef PSP_BUILD if(!strcmp(current_dir_name, "ms0:/PSP")) break;#endif repeat = 0; chdir(".."); break; case CURSOR_EXIT: return_value = -1; repeat = 0; break; } } for(i = 0; i < num_files; i++) { free(file_list[i]); } free(file_list); for(i = 0; i < num_dirs; i++) { free(dir_list[i]); } free(dir_list); } clear_screen(COLOR_BG); return return_value;}typedef enum{ NUMBER_SELECTION_OPTION = 0x01, STRING_SELECTION_OPTION = 0x02, SUBMENU_OPTION = 0x04, ACTION_OPTION = 0x08} menu_option_type_enum;struct _menu_type{ void (* init_function)(); void (* passive_function)(); struct _menu_option_type *options; u32 num_options;};struct _menu_option_type{ void (* action_function)(); void (* passive_function)(); struct _menu_type *sub_menu; char *display_string; void *options; u32 *current_option; u32 num_options; char *help_string; u32 line_number; menu_option_type_enum option_type;};typedef struct _menu_option_type menu_option_type;typedef struct _menu_type menu_type;#define make_menu(name, init_function, passive_function) \ menu_type name##_menu = \ { \ init_function, \ passive_function, \ name##_options, \ sizeof(name##_options) / sizeof(menu_option_type) \ } \#define gamepad_config_option(display_string, number) \{ \ NULL, \ menu_fix_gamepad_help, \ NULL, \ display_string ": %s", \ gamepad_config_buttons, \ gamepad_config_map + gamepad_config_line_to_psp_button[number], \ sizeof(gamepad_config_buttons) / sizeof(gamepad_config_buttons[0]), \ gamepad_help[gamepad_config_map[ \ gamepad_config_line_to_psp_button[number]]], \ number, \ STRING_SELECTION_OPTION \} \#define analog_config_option(display_string, number) \{ \ NULL, \ menu_fix_gamepad_help, \ NULL, \ display_string ": %s", \ gamepad_config_buttons, \ gamepad_config_map + number + 12, \ sizeof(gamepad_config_buttons) / sizeof(gamepad_config_buttons[0]), \ gamepad_help[gamepad_config_map[number + 12]], \ number + 2, \ STRING_SELECTION_OPTION \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -