From 6701f6a9d4f979cc1eadb673e767b5c46cd2a9c8 Mon Sep 17 00:00:00 2001 From: Ian C Date: Tue, 10 Apr 2007 23:59:35 +0000 Subject: Initial import --- arm9/source/gui.c | 714 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 714 insertions(+) create mode 100644 arm9/source/gui.c (limited to 'arm9/source/gui.c') diff --git a/arm9/source/gui.c b/arm9/source/gui.c new file mode 100644 index 0000000..11096d3 --- /dev/null +++ b/arm9/source/gui.c @@ -0,0 +1,714 @@ +/* + ds48 - Nintendo DS ZX Spectrum emulator. + + Copyright (C) 2007 Ian Cowburn + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + $Id$ +*/ + +#include +#include +#include +#include + +#include + +#include "framebuffer.h" +#include "config.h" + + +/* ---------------------------------------- PRIVATE INTERFACES - PATH HANDLING +*/ +#define FSEL_FILENAME_LEN 20 +#define FSEL_LINES 16 +#define FSEL_MAX_FILES 512 + +#define FSEL_LIST_Y 10 +#define FSEL_LIST_H FSEL_LINES*8 + +typedef struct +{ + char name[FSEL_FILENAME_LEN+1]; + int is_dir; + int size; +} FSEL_File; + +static FSEL_File fsel[FSEL_MAX_FILES]; + + +static void CheckPath(char *path) +{ + size_t l; + + l = strlen(path); + + if (l == 1) + { + path[0] = '/'; + } + else + { + if (path[l-1] != '/') + { + path[l] = '/'; + path[l+1] = 0; + } + } +} + + +static void AddPath(char *path, const char *dir) +{ + if (strcmp(dir,"..") == 0) + { + size_t l; + + l = strlen(path); + + if (l > 1) + { + path[--l] = 0; + + while(l && path[l] != '/') + { + path[l--] = 0; + } + } + } + else + { + strcat(path,dir); + strcat(path,"/"); + } +} + + + + +static int SortFiles(const void *a, const void *b) +{ + const FSEL_File *f1; + const FSEL_File *f2; + + f1 = (const FSEL_File *)a; + f2 = (const FSEL_File *)b; + + if (f1->is_dir == f2->is_dir) + { + return strcasecmp(f1->name, f2->name); + } + else if (f1->is_dir) + { + return -1; + } + else + { + return 1; + } +} + + +static int ValidFilename(const char *name, int is_dir, const char *filter) +{ + size_t l; + size_t f; + + l = strlen(name); + + if (l > FSEL_FILENAME_LEN) + return 0; + + if (strcmp(name,".") == 0) + return 0; + + if (is_dir || !filter) + return 1; + + f = strlen(filter); + + if (l > f) + { + if (strcasecmp(name+l-f,filter) == 0) + { + return 1; + } + } + + return 0; +} + + +static int LoadDir(const char *path, const char *filter) +{ + DIR_ITER *dir; + struct stat st; + char name[FILENAME_MAX]; + int no = 0; + + if ((dir = diropen(path))) + { + while(no < FSEL_MAX_FILES && dirnext(dir,name,&st) == 0) + { + if (ValidFilename(name, (st.st_mode & S_IFDIR), filter)) + { + strcpy(fsel[no].name,name); + fsel[no].is_dir = (st.st_mode & S_IFDIR); + fsel[no].size = (int)st.st_size; + no++; + } + } + + dirclose(dir); + + qsort(fsel,no,sizeof fsel[0],SortFiles); + } + + return no; +} + + +/* ---------------------------------------- PUBLIC INTERFACES +*/ +int GUI_Menu(const char *opts[]) +{ + int x,y; + int h; + int w; + int no; + int sel; + int f; + int done; + int defer; + + w=0; + h=0; + sel=0; + done=FALSE; + defer=FALSE; + + for(no=0;opts[no];no++) + { + h+=16; + + if (strlen(opts[no])>w) + { + w=strlen(opts[no]); + } + } + + w=w*8+16; + + x=SCREEN_WIDTH/2-w/2; + y=SCREEN_HEIGHT/2-h/2; + + while(!done) + { + uint32 key=0; + + FB_FillBox(x,y,w,h,COL_BLACK); + FB_Box(x,y,w,h,COL_WHITE); + FB_FillBox(x+1,y+sel*16+1,w-2,14,COL_GUISELECT); + + for(f=0;f=x && tp.px<(w+w) && tp.py>=y && tp.py<(y+h)) + { + defer=TRUE; + sel=(tp.py-y)/16; + } + } + } + } + + return sel; +} + + +void GUI_Alert(int fatal, const char *text) +{ + char line[80]; + int h; + const char *p; + char *d; + + h=40; + p=text; + + while(*p) + { + if (*p++=='\n') + { + h+=8; + } + } + + FB_FillBox(0,0,SCREEN_WIDTH,h,COL_BLACK); + FB_Box(1,1,SCREEN_WIDTH-2,h-2,COL_WHITE); + + p=text; + h=4; + d=line; + + while(*p) + { + if (*p=='\n') + { + *d++=0; + p++; + FB_Centre(line,h,COL_WHITE,COL_TRANSPARENT); + h+=8; + d=line; + } + else + { + *d++=*p++; + } + } + + if (d>line) + { + *d=0; + FB_Centre(line,h,COL_WHITE,COL_TRANSPARENT); + h+=8; + } + + if (!fatal) + { + FB_Centre("PRESS ANY BUTTON OR SCREEN",h+16,COL_YELLOW,COL_TRANSPARENT); + + while(!keysDown()) + { + swiWaitForVBlank(); + } + + while(keysHeld()) + { + swiWaitForVBlank(); + } + } + else + { + FB_Centre("PLEASE RESET YOUR CONSOLE",h+16,COL_YELLOW,COL_TRANSPARENT); + + while(1) + { + swiWaitForVBlank(); + } + } +} + + +void GUI_Config(void) +{ + int sel; + DS48_ConfigItem f; + int done; + int save; + + sel = 0; + done = FALSE; + save = FALSE; + + FB_Clear(); + + FB_Centre("Up/Down to select",140,COL_YELLOW,COL_TRANSPARENT); + FB_Centre("A to toggle",150,COL_YELLOW,COL_TRANSPARENT); + FB_Centre("Or use touchscreen",160,COL_YELLOW,COL_TRANSPARENT); + FB_Centre("START to finish",170,COL_YELLOW,COL_TRANSPARENT); + +#ifndef DS48_DISABLE_FAT + FB_Centre("SELECT to finish and save",180,COL_YELLOW,COL_TRANSPARENT); +#endif + + for(f=0;f=0 && nsel (no - FSEL_LINES)) + { + new_top = no - FSEL_LINES; + } + + if (new_top < 0) + { + new_top = 0; + } + + if (new_top != top) + { + top = new_top; + sel = top; + drag_start = tp.py; + } + } + else + { + drag = FALSE; + } + } + + if (!drag) + { + int activate = FALSE; + + do + { + swiWaitForVBlank(); + } while(!(key=keysDownRepeat())); + + if (key & KEY_TOUCH) + { + touchPosition tp; + + tp = touchReadXY(); + + if (tp.py >= FSEL_LIST_Y && tp.py <= (FSEL_LIST_Y+FSEL_LIST_H)) + { + if (tp.px > 239) + { + drag = TRUE; + drag_start = tp.py; + } + else + { + int new_sel; + + new_sel = top + (tp.py - FSEL_LIST_Y)/8; + + if (new_sel < no) + { + if (new_sel == sel) + { + activate = TRUE; + } + else + { + sel = new_sel; + } + } + } + } + } + else if (key & KEY_UP) + { + if (sel) + { + sel--; + + if (sel= (top+FSEL_LINES)) + { + top++; + } + } + } + else if (key & KEY_L) + { + if (sel) + { + sel-=FSEL_LINES; + + if (sel < 0) + { + sel = 0; + } + + top = sel; + } + } + else if (key & KEY_R) + { + if (sel < (no-1)) + { + sel+=FSEL_LINES; + + if (sel > (no-1)) + { + sel = no-1; + } + + top = sel - FSEL_LINES + 1; + + if (top < 0) + { + top = 0; + } + } + } + else if (key & KEY_A) + { + activate = TRUE; + } + else if (key & KEY_B) + { + done = TRUE; + } + + if (activate) + { + if (fsel[sel].is_dir) + { + AddPath(pwd,fsel[sel].name); + + FB_printf(0,0,COL_BLACK,COL_LIGHTGREY,"%-32.32s",pwd); + + no = LoadDir(pwd,filter); + + sel = 0; + top = 0; + + if (no<=FSEL_LINES) + { + bar_step = 0; + bar_size = FSEL_LIST_H; + } + else + { + bar_step = FSEL_LIST_H/(double)no; + bar_size = bar_step*FSEL_LINES; + } + } + else + { + done = TRUE; + ret = TRUE; + + strcpy(selected_file,pwd); + strcat(selected_file,fsel[sel].name); + } + } + } + } + + while (keysHeld()); + + return ret; +} -- cgit v1.2.3