Merge pull request #10 from irixxxx/master

improved directory handling for menu, basic PSP support
This commit is contained in:
notaz 2021-01-18 19:12:19 +02:00 committed by GitHub
commit 76e45c3489
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 44 deletions

View file

@ -41,7 +41,15 @@ int plat_is_dir(const char *path)
return 0; return 0;
} }
static int plat_get_data_dir(char *dst, int len) int plat_get_data_dir(char *dst, int len)
{
if (len > 1)
strcpy(dst, "/");
else *dst = 0;
return strlen(dst);
}
static int plat_get_exe_dir(char *dst, int len)
{ {
#ifdef PICO_DATA_DIR #ifdef PICO_DATA_DIR
memcpy(dst, PICO_DATA_DIR, sizeof PICO_DATA_DIR); memcpy(dst, PICO_DATA_DIR, sizeof PICO_DATA_DIR);
@ -65,7 +73,7 @@ static int plat_get_data_dir(char *dst, int len)
int plat_get_skin_dir(char *dst, int len) int plat_get_skin_dir(char *dst, int len)
{ {
int ret = plat_get_data_dir(dst, len); int ret = plat_get_exe_dir(dst, len);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -90,7 +98,7 @@ int plat_get_root_dir(char *dst, int len)
return ret; return ret;
} }
#endif #endif
return plat_get_data_dir(dst, len); return plat_get_exe_dir(dst, len);
} }
#ifdef __GP2X__ #ifdef __GP2X__

86
menu.c
View file

@ -31,13 +31,21 @@
static char static_buff[64]; static char static_buff[64];
static int menu_error_time = 0; static int menu_error_time = 0;
char menu_error_msg[64] = { 0, }; char menu_error_msg[64] = { 0, };
// g_menuscreen is the current output buffer the menu is rendered to.
void *g_menuscreen_ptr; void *g_menuscreen_ptr;
void *g_menubg_src_ptr; // g_menubg is the menu background and has the same w/h as g_menuscreen, but
// pp=w. It is filled on menu entry from file or from g_menubg_src if available.
void *g_menubg_ptr; void *g_menubg_ptr;
// g_menubg_src points to a buffer containing a bg image. This is usually either
// the emulator screen buffer or the host frame buffer.
void *g_menubg_src_ptr;
int g_menuscreen_w; int g_menuscreen_w;
int g_menuscreen_h; int g_menuscreen_h;
int g_menuscreen_pp; int g_menuscreen_pp;
int g_menubg_src_w;
int g_menubg_src_h;
int g_menubg_src_pp;
int g_autostateld_opt; int g_autostateld_opt;
@ -879,7 +887,6 @@ static void draw_dirlist(char *curdir, struct dirent **namelist,
max_cnt = g_menuscreen_h / me_sfont_h; max_cnt = g_menuscreen_h / me_sfont_h;
start = max_cnt / 2 - sel; start = max_cnt / 2 - sel;
n--; // exclude current dir (".")
menu_draw_begin(1, 1); menu_draw_begin(1, 1);
@ -896,12 +903,12 @@ static void draw_dirlist(char *curdir, struct dirent **namelist,
pos = start + i; pos = start + i;
if (pos < 0) continue; if (pos < 0) continue;
if (pos >= max_cnt) break; if (pos >= max_cnt) break;
if (namelist[i+1]->d_type == DT_DIR) { if (namelist[i]->d_type == DT_DIR) {
smalltext_out16(x, pos * me_sfont_h, "/", 0xfff6); smalltext_out16(x, pos * me_sfont_h, "/", 0xfff6);
smalltext_out16(x + me_sfont_w, pos * me_sfont_h, namelist[i+1]->d_name, 0xfff6); smalltext_out16(x + me_sfont_w, pos * me_sfont_h, namelist[i]->d_name, 0xfff6);
} else { } else {
unsigned short color = fname2color(namelist[i+1]->d_name); unsigned short color = fname2color(namelist[i]->d_name);
smalltext_out16(x, pos * me_sfont_h, namelist[i+1]->d_name, color); smalltext_out16(x, pos * me_sfont_h, namelist[i]->d_name, color);
} }
} }
smalltext_out16(5, max_cnt/2 * me_sfont_h, ">", 0xffff); smalltext_out16(5, max_cnt/2 * me_sfont_h, ">", 0xffff);
@ -934,10 +941,15 @@ static int scandir_cmp(const void *p1, const void *p2)
{ {
const struct dirent **d1 = (const struct dirent **)p1; const struct dirent **d1 = (const struct dirent **)p1;
const struct dirent **d2 = (const struct dirent **)p2; const struct dirent **d2 = (const struct dirent **)p2;
const char *p;
if ((p = (*d1)->d_name)[0] == '.' && p[1] == '.' && p[2] == 0)
return -1; // ".." first
if ((p = (*d2)->d_name)[0] == '.' && p[1] == '.' && p[2] == 0)
return 1;
if ((*d1)->d_type == (*d2)->d_type) if ((*d1)->d_type == (*d2)->d_type)
return alphasort(d1, d2); return alphasort(d1, d2);
if ((*d1)->d_type == DT_DIR) if ((*d1)->d_type == DT_DIR)
return -1; // put before return -1; // directories before files/links
if ((*d2)->d_type == DT_DIR) if ((*d2)->d_type == DT_DIR)
return 1; return 1;
@ -957,7 +969,8 @@ static int scandir_filter(const struct dirent *ent)
switch (ent->d_type) { switch (ent->d_type) {
case DT_DIR: case DT_DIR:
return 1; // leave out useless reference to current directory
return strcmp(ent->d_name, ".") != 0;
case DT_LNK: case DT_LNK:
case DT_UNKNOWN: case DT_UNKNOWN:
// could be a dir, deal with it later.. // could be a dir, deal with it later..
@ -1006,7 +1019,6 @@ static const char *menu_loop_romsel(char *curr_path, int len,
int n = 0, inp = 0, sel = 0, show_help = 0; int n = 0, inp = 0, sel = 0, show_help = 0;
char *curr_path_restore = NULL; char *curr_path_restore = NULL;
const char *ret = NULL; const char *ret = NULL;
int changed;
char cinp; char cinp;
int r, i; int r, i;
@ -1040,13 +1052,10 @@ rescan:
n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp); n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp);
if (n < 0) { if (n < 0) {
char *t;
lprintf("menu_loop_romsel failed, dir: %s\n", curr_path); lprintf("menu_loop_romsel failed, dir: %s\n", curr_path);
// try root // try data root
t = getcwd(curr_path, len); plat_get_data_dir(curr_path, len);
if (t == NULL)
plat_get_root_dir(curr_path, len);
n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp); n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp);
if (n < 0) { if (n < 0) {
// oops, we failed // oops, we failed
@ -1056,43 +1065,40 @@ rescan:
} }
// try to resolve DT_UNKNOWN and symlinks // try to resolve DT_UNKNOWN and symlinks
changed = 0;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
struct stat st; struct stat st;
char *slash;
if (namelist[i]->d_type == DT_REG || namelist[i]->d_type == DT_DIR) if (namelist[i]->d_type == DT_REG || namelist[i]->d_type == DT_DIR)
continue; continue;
r = strlen(curr_path);
slash = (r && curr_path[r-1] == '/') ? "" : "/";
snprintf(rom_fname_reload, sizeof(rom_fname_reload), snprintf(rom_fname_reload, sizeof(rom_fname_reload),
"%s/%s", curr_path, namelist[i]->d_name); "%s%s%s", curr_path, slash, namelist[i]->d_name);
r = stat(rom_fname_reload, &st); r = stat(rom_fname_reload, &st);
if (r == 0) if (r == 0)
{ {
if (S_ISREG(st.st_mode)) { if (S_ISREG(st.st_mode))
namelist[i]->d_type = DT_REG; namelist[i]->d_type = DT_REG;
changed = 1; else if (S_ISDIR(st.st_mode))
}
else if (S_ISDIR(st.st_mode)) {
namelist[i]->d_type = DT_DIR; namelist[i]->d_type = DT_DIR;
changed = 1;
}
} }
} }
if (!g_menu_filter_off && extra_filter != NULL) if (!g_menu_filter_off && extra_filter != NULL)
n = extra_filter(namelist, n, curr_path); n = extra_filter(namelist, n, curr_path);
if (n > 1 && changed) if (n > 1)
qsort(namelist, n, sizeof(namelist[0]), scandir_cmp); qsort(namelist, n, sizeof(namelist[0]), scandir_cmp);
// try to find selected file // try to find selected file
// note: we don't show '.' so sel is namelist index - 1
sel = 0; sel = 0;
if (sel_fname[0] != 0) { if (sel_fname[0] != 0) {
for (i = 1; i < n; i++) { for (i = 0; i < n; i++) {
char *dname = namelist[i]->d_name; char *dname = namelist[i]->d_name;
if (dname[0] == sel_fname[0] && strcmp(dname, sel_fname) == 0) { if (dname[0] == sel_fname[0] && strcmp(dname, sel_fname) == 0) {
sel = i - 1; sel = i;
break; break;
} }
} }
@ -1112,52 +1118,54 @@ rescan:
if (inp & PBTN_MA3) { if (inp & PBTN_MA3) {
g_menu_filter_off = !g_menu_filter_off; g_menu_filter_off = !g_menu_filter_off;
snprintf(sel_fname, sizeof(sel_fname), "%s", snprintf(sel_fname, sizeof(sel_fname), "%s",
namelist[sel+1]->d_name); namelist[sel]->d_name);
goto rescan; goto rescan;
} }
if (inp & PBTN_UP ) { sel--; if (sel < 0) sel = n-2; } if (inp & PBTN_UP ) { sel--; if (sel < 0) sel = n-1; }
if (inp & PBTN_DOWN) { sel++; if (sel > n-2) sel = 0; } if (inp & PBTN_DOWN) { sel++; if (sel > n-1) sel = 0; }
if (inp & PBTN_LEFT) { sel-=10; if (sel < 0) sel = 0; } if (inp & PBTN_LEFT) { sel-=10; if (sel < 0) sel = 0; }
if (inp & PBTN_L) { sel-=24; if (sel < 0) sel = 0; } if (inp & PBTN_L) { sel-=24; if (sel < 0) sel = 0; }
if (inp & PBTN_RIGHT) { sel+=10; if (sel > n-2) sel = n-2; } if (inp & PBTN_RIGHT) { sel+=10; if (sel > n-1) sel = n-1; }
if (inp & PBTN_R) { sel+=24; if (sel > n-2) sel = n-2; } if (inp & PBTN_R) { sel+=24; if (sel > n-1) sel = n-1; }
if ((inp & PBTN_MOK) || (inp & (PBTN_MENU|PBTN_MA2)) == (PBTN_MENU|PBTN_MA2)) if ((inp & PBTN_MOK) || (inp & (PBTN_MENU|PBTN_MA2)) == (PBTN_MENU|PBTN_MA2))
{ {
if (namelist[sel+1]->d_type == DT_REG) if (namelist[sel]->d_type == DT_REG)
{ {
int l = strlen(curr_path);
char *slash = l && curr_path[l-1] == '/' ? "" : "/";
snprintf(rom_fname_reload, sizeof(rom_fname_reload), snprintf(rom_fname_reload, sizeof(rom_fname_reload),
"%s/%s", curr_path, namelist[sel+1]->d_name); "%s%s%s", curr_path, slash, namelist[sel]->d_name);
if (inp & PBTN_MOK) { // return sel if (inp & PBTN_MOK) { // return sel
ret = rom_fname_reload; ret = rom_fname_reload;
break; break;
} }
do_delete(rom_fname_reload, namelist[sel+1]->d_name); do_delete(rom_fname_reload, namelist[sel]->d_name);
goto rescan; goto rescan;
} }
else if (namelist[sel+1]->d_type == DT_DIR) else if (namelist[sel]->d_type == DT_DIR)
{ {
int newlen; int newlen;
char *p, *newdir; char *p, *newdir;
if (!(inp & PBTN_MOK)) if (!(inp & PBTN_MOK))
continue; continue;
newlen = strlen(curr_path) + strlen(namelist[sel+1]->d_name) + 2; newlen = strlen(curr_path) + strlen(namelist[sel]->d_name) + 2;
newdir = malloc(newlen); newdir = malloc(newlen);
if (newdir == NULL) if (newdir == NULL)
break; break;
if (strcmp(namelist[sel+1]->d_name, "..") == 0) { if (strcmp(namelist[sel]->d_name, "..") == 0) {
char *start = curr_path; char *start = curr_path;
p = start + strlen(start) - 1; p = start + strlen(start) - 1;
while (*p == '/' && p > start) p--; while (*p == '/' && p > start) p--;
while (*p != '/' && p > start) p--; while (*p != '/' && p > start) p--;
if (p <= start) strcpy(newdir, "/"); if (p <= start) plat_get_data_dir(newdir, newlen);
else { strncpy(newdir, start, p-start); newdir[p-start] = 0; } else { strncpy(newdir, start, p-start); newdir[p-start] = 0; }
} else { } else {
strcpy(newdir, curr_path); strcpy(newdir, curr_path);
p = newdir + strlen(newdir) - 1; p = newdir + strlen(newdir) - 1;
while (*p == '/' && p >= newdir) *p-- = 0; while (*p == '/' && p >= newdir) *p-- = 0;
strcat(newdir, "/"); strcat(newdir, "/");
strcat(newdir, namelist[sel+1]->d_name); strcat(newdir, namelist[sel]->d_name);
} }
ret = menu_loop_romsel(newdir, newlen, filter_exts, extra_filter); ret = menu_loop_romsel(newdir, newlen, filter_exts, extra_filter);
free(newdir); free(newdir);

8
menu.h
View file

@ -112,12 +112,16 @@ typedef struct
extern me_bind_action me_ctrl_actions[]; extern me_bind_action me_ctrl_actions[];
extern me_bind_action emuctrl_actions[]; // platform code extern me_bind_action emuctrl_actions[]; // platform code
extern void *g_menubg_src_ptr;
extern void *g_menubg_ptr;
extern void *g_menuscreen_ptr; extern void *g_menuscreen_ptr;
extern void *g_menubg_ptr;
extern void *g_menubg_src_ptr;
extern int g_menuscreen_w; extern int g_menuscreen_w;
extern int g_menuscreen_h; extern int g_menuscreen_h;
extern int g_menuscreen_pp; // pitch (in pixels) extern int g_menuscreen_pp; // pitch (in pixels)
extern int g_menubg_src_w;
extern int g_menubg_src_h;
extern int g_menubg_src_pp;
extern int g_autostateld_opt; extern int g_autostateld_opt;

3
plat.h
View file

@ -107,6 +107,9 @@ int plat_get_root_dir(char *dst, int len);
/* return the dir/ where skin files are found */ /* return the dir/ where skin files are found */
int plat_get_skin_dir(char *dst, int len); int plat_get_skin_dir(char *dst, int len);
/* return the top level dir for image files */
int plat_get_data_dir(char *dst, int len);
int plat_is_dir(const char *path); int plat_is_dir(const char *path);
int plat_wait_event(int *fds_hnds, int count, int timeout_ms); int plat_wait_event(int *fds_hnds, int count, int timeout_ms);
void plat_sleep_ms(int ms); void plat_sleep_ms(int ms);

13
posix.h
View file

@ -17,6 +17,19 @@
#define DT_DIR 0 #define DT_DIR 0
#endif #endif
#elif defined(__PSP__)
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
/* map PSP names to posix. needs special scandir() function to mask rwx bits */
#define d_type d_stat.st_attr
#define DT_LNK FIO_SO_IFLNK
#define DT_DIR FIO_SO_IFDIR
#define DT_REG FIO_SO_IFREG
#define DT_UNKNOWN 0
#else #else
#error "must provide posix" #error "must provide posix"