diff options
author | Ian C <ianc@noddybox.co.uk> | 2007-02-16 01:10:41 +0000 |
---|---|---|
committer | Ian C <ianc@noddybox.co.uk> | 2007-02-16 01:10:41 +0000 |
commit | b369f37c6244b5d56742b56f745219fb2544efe2 (patch) | |
tree | a838093b033d302e6c7f64e7e255594d490d093a /source | |
parent | 284d8dec91155107f04ad4e2c02338bcb6263abc (diff) |
Some hi-res support. Added new config page and averaging touchscreen reads.
In process of writing file selector.
Diffstat (limited to 'source')
-rw-r--r-- | source/config.c | 130 | ||||
-rw-r--r-- | source/framebuffer.c | 15 | ||||
-rw-r--r-- | source/gui.c | 428 | ||||
-rw-r--r-- | source/keyboard.c | 48 | ||||
-rw-r--r-- | source/main.c | 21 | ||||
-rw-r--r-- | source/touchwrap.c | 55 | ||||
-rw-r--r-- | source/zx81.c | 71 |
7 files changed, 698 insertions, 70 deletions
diff --git a/source/config.c b/source/config.c new file mode 100644 index 0000000..b2abec8 --- /dev/null +++ b/source/config.c @@ -0,0 +1,130 @@ +/* + ds81 - Nintendo DS ZX81 emulator. + + Copyright (C) 2006 Ian Cowburn <ianc@noddybox.co.uk> + + 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 <nds.h> +#include <stdio.h> +#include <string.h> + +#include "config.h" + +/* ---------------------------------------- PRIVATE DATA +*/ +const char *conf_filename = "DS81.CFG"; + +const char *conf_entry[DS81_NUM_CONFIG_ITEMS]= +{ + "sticky_shift", + "average_touchscreen" +}; + + +/* ---------------------------------------- GLOBAL DATA +*/ +int DS81_Config[DS81_NUM_CONFIG_ITEMS]= +{ + TRUE, + FALSE +}; + + +/* ---------------------------------------- PUBLIC INTERFACES +*/ +int LoadConfig(void) +{ + FILE *fp = NULL; + +#ifndef DS81_DISABLE_FAT + fp=fopen(conf_filename,"r"); +#endif + + if (fp) + { + char line[80]; + + while(fgets(line, sizeof line, fp)) + { + char *p; + + if ((p = strchr(line, '='))) + { + int f; + + for(f=0;f<DS81_NUM_CONFIG_ITEMS;f++) + { + if (strncmp(line, conf_entry[f], + strlen(conf_entry[f])) == 0) + { + DS81_Config[f] = (*(p+1) == '1'); + } + } + + } + } + + fclose(fp); + + return TRUE; + } + + return FALSE; +} + +int SaveConfig(void) +{ + FILE *fp = NULL; + +#ifndef DS81_DISABLE_FAT + fp=fopen(conf_filename,"w"); +#endif + + if (fp) + { + int f; + + for(f=0;f<DS81_NUM_CONFIG_ITEMS;f++) + { + fprintf(fp,"%s=%d\n",conf_entry[f],DS81_Config[f]); + } + + fclose(fp); + + return TRUE; + } + + return FALSE; +} + +const char *ConfigDesc(DS81_ConfigItem item) +{ + switch(item) + { + case DS81_STICKY_SHIFT: + return "STICKY SHIFT"; + + case DS81_AVERAGE_TOUCHSCREEN: + return "AVERAGE TOUCHSCREEN"; + + default: + return "UNKNOWN"; + } +} + diff --git a/source/framebuffer.c b/source/framebuffer.c index ef66235..691862e 100644 --- a/source/framebuffer.c +++ b/source/framebuffer.c @@ -21,6 +21,8 @@ */ #include <nds.h> +#include <stdio.h> +#include <stdarg.h> #include <string.h> /* ---------------------------------------- STATIC DATA @@ -183,6 +185,19 @@ void FB_Centre(const char *text, int y, int colour, int paper) } +void FB_printf(int x, int y, int colour, int paper, const char *format, ...) +{ + char buff[80]; + va_list va; + + va_start(va,format); + vsnprintf(buff,sizeof buff,format,va); + va_end(va); + + FB_Print(buff,x,y,colour,paper); +} + + void FB_HLine(int x1, int x2, int y, int colour) { uint16 *line; diff --git a/source/gui.c b/source/gui.c index 713ad02..7e55b97 100644 --- a/source/gui.c +++ b/source/gui.c @@ -20,10 +20,160 @@ $Id$ */ -#include <nds.h> +#include <stdlib.h> +#include <stdio.h> #include <string.h> +#include <nds.h> + +#include <sys/dir.h> #include "framebuffer.h" +#include "config.h" + + +/* ---------------------------------------- PRIVATE INTERFACES - PATH HANDLING +*/ +#define FSEL_FILENAME_LEN 20 +#define FSEL_LINES 15 +#define FSEL_MAX_FILES 512 + +#define FSEL_LIST_Y 12 +#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) + { + char *p; + + p = strrchr(path,'/'); + + if (p && p!=path) + { + *p = 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 == f1->is_dir) + { + return strcmp(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 (strcmp(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 @@ -189,3 +339,279 @@ void GUI_Alert(int fatal, const char *text) } } } + + +void GUI_Config(void) +{ + int sel; + DS81_ConfigItem f; + bool done; + bool save; + + sel = 0; + done = false; + save = false; + + FB_Clear(); + + FB_Centre("Up/Down to select",140,FB_RGB(31,31,0),-1); + FB_Centre("A to toggle",150,FB_RGB(31,31,0),-1); + FB_Centre("Or use touchscreen",160,FB_RGB(31,31,0),-1); + FB_Centre("START to finish",170,FB_RGB(31,31,0),-1); + +#ifndef DS81_DISABLE_FAT + FB_Centre("SELECT to save to \\DS81.CFG",180,FB_RGB(31,31,0),-1); +#endif + + for(f=0;f<DS81_NUM_CONFIG_ITEMS;f++) + { + FB_Print(ConfigDesc(f),14,20+f*14,FB_RGB(31,31,31),-1); + } + + while(!done) + { + uint32 key=0; + + for(f=0;f<DS81_NUM_CONFIG_ITEMS;f++) + { + FB_FillBox(2,20+f*14-1,10,10, + DS81_Config[f] ? FB_RGB(31,31,31):FB_RGB(0,0,0)); + + FB_Box(2,20+f*14-1,10,10,FB_RGB(18,18,18)); + } + + FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,FB_RGB(18,18,31)); + + do + { + swiWaitForVBlank(); + } while(!(key=keysDownRepeat())); + + FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,FB_RGB(0,0,0)); + + if (key & KEY_START) + { + done=true; + } +#ifndef DS81_DISABLE_FAT + else if (key & KEY_SELECT) + { + done=true; + save=true; + } +#endif + else if (key & KEY_A) + { + DS81_Config[sel] = !DS81_Config[sel]; + } + else if ((key & KEY_UP) && sel) + { + sel--; + } + else if ((key & KEY_DOWN) && sel<DS81_NUM_CONFIG_ITEMS-1) + { + sel++; + } + else if (key & KEY_TOUCH) + { + touchPosition tp = touchReadXY(); + int nsel; + + nsel = (tp.py-18)/14; + + if (nsel>=0 && nsel<DS81_NUM_CONFIG_ITEMS) + { + sel = nsel; + DS81_Config[sel] = !DS81_Config[sel]; + } + } + } + + if (save) + { + SaveConfig(); + } +} + + +bool GUI_FileSelect(char pwd[], char selected_file[], const char *filter) +{ + int no; + int sel; + int top; + int bar_size; + double bar_step; + bool done; + bool ret; + int pen; + int paper; + int off; + int f; + + CheckPath(pwd); + + FB_Clear(); + + FB_printf(0,0,FB_RGB(0,0,0),FB_RGB(22,22,22),"%-31.31s",pwd); + + no = LoadDir(pwd,filter); + + sel = 0; + top = 0; + done = false; + ret = false; + + 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; + } + + while(!done) + { + uint32 key=0; + + for (f=0;f<FSEL_LINES;f++) + { + off = f + top; + + if (off<no) + { + if (off == sel) + { + pen = FB_RGB(0,0,0); + paper = FB_RGB(31,31,31); + } + else + { + pen = FB_RGB(31,31,31); + paper = FB_RGB(0,0,0); + } + + FB_printf(8,FSEL_LIST_Y+f*8,pen,paper, + "%-*s %s", + FSEL_FILENAME_LEN, + fsel[off].name, + fsel[off].is_dir ? "DIR" : " "); + } + else + { + FB_printf(8,FSEL_LIST_Y+f*8,FB_RGB(31,31,31),FB_RGB(0,0,0), + "%-*s %s", + FSEL_FILENAME_LEN, + off==0 ? "No Files!" : "", + ""); + } + } + + FB_FillBox(240,FSEL_LIST_Y,16,FSEL_LIST_H,FB_RGB(10,10,10)); + FB_FillBox(240,FSEL_LIST_Y+top*bar_step,16,bar_size,FB_RGB(31,31,31)); + + do + { + swiWaitForVBlank(); + } while(!(key=keysDownRepeat())); + + if (key & KEY_UP) + { + if (sel) + { + sel--; + + if (sel<top) + { + top--; + } + } + } + else if (key & KEY_DOWN) + { + if (sel < (no-1)) + { + 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) + { + if (fsel[sel].is_dir) + { + AddPath(pwd,fsel[sel].name); + + 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); + } + } + else if (key & KEY_START) + { + done=true; + } + } + + while (keysHeld()); + + return ret; +} diff --git a/source/keyboard.c b/source/keyboard.c index cb6a932..37ae4ef 100644 --- a/source/keyboard.c +++ b/source/keyboard.c @@ -24,6 +24,7 @@ #include "keyboard.h" #include "framebuffer.h" +#include "touchwrap.h" #include "keyb_bin.h" /* ---------------------------------------- STATIC DATA @@ -166,36 +167,39 @@ static int GetEvent(SoftKeyEvent *ev, int map) */ if (keys & KEY_TOUCH) { - touchPosition tp=touchReadXY(); + touchPosition tp; - if (tp.py<21 || tp.py>165) + if (AllowTouch(&tp)) { - key_state[SK_CONFIG].new_state = TRUE; - } - else - { - SoftKey press; - - press = LocatePress(&tp); - - if (press != NUM_SOFT_KEYS) + if (tp.py<21 || tp.py>165) + { + key_state[SK_CONFIG].new_state = TRUE; + } + else { - key_state[press].handled = TRUE; + SoftKey press; + + press = LocatePress(&tp); - if (key_state[press].is_sticky) + if (press != NUM_SOFT_KEYS) { - if (last != press) + key_state[press].handled = TRUE; + + if (key_state[press].is_sticky) { - key_state[press].new_state = - !key_state[press].state; + if (last != press) + { + key_state[press].new_state = + !key_state[press].state; + } + } + else + { + key_state[press].new_state = TRUE; } - } - else - { - key_state[press].new_state = TRUE; - } - last = press; + last = press; + } } } } diff --git a/source/main.c b/source/main.c index aed05f5..f2b0e70 100644 --- a/source/main.c +++ b/source/main.c @@ -32,6 +32,7 @@ #include "z80.h" #include "zx81.h" #include "tapes.h" +#include "config.h" #include "splashimg_bin.h" #include "rom_font_bin.h" @@ -42,8 +43,7 @@ static const char *main_menu[]= { "Reset ZX81", "Select Tape", - "Sticky Shift On", - "Sticky Shift Off", + "Configure", "Map Joypad to Keys", "Cancel", NULL @@ -53,8 +53,7 @@ typedef enum { MenuReset, MenuSelectTape, - MenuStickyOn, - MenuStickyOff, + MenuConfigure, MenuMapJoypad, } MenuOpt; @@ -301,9 +300,11 @@ int main(int argc, char *argv[]) Splash(); + LoadConfig(); + SK_DisplayKeyboard(BG_GFX_SUB); - SK_SetSticky(SK_SHIFT,1); + SK_SetSticky(SK_SHIFT,DS81_Config[DS81_STICKY_SHIFT]); while(1) { @@ -329,12 +330,10 @@ int main(int argc, char *argv[]) SelectTape(); break; - case MenuStickyOn: - SK_SetSticky(SK_SHIFT,1); - break; - - case MenuStickyOff: - SK_SetSticky(SK_SHIFT,0); + case MenuConfigure: + GUI_Config(); + SK_SetSticky(SK_SHIFT, + DS81_Config[DS81_STICKY_SHIFT]); break; case MenuMapJoypad: diff --git a/source/touchwrap.c b/source/touchwrap.c new file mode 100644 index 0000000..4fa373b --- /dev/null +++ b/source/touchwrap.c @@ -0,0 +1,55 @@ +/* + ds81 - Nintendo DS ZX81 emulator. + + Copyright (C) 2006 Ian Cowburn <ianc@noddybox.co.uk> + + 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 <nds.h> +#include <stdlib.h> + +#include "touchwrap.h" +#include "config.h" + +/* ---------------------------------------- PUBLIC INTERFACES +*/ +int AllowTouch(touchPosition *tp) +{ + static touchPosition last; + int16 dx; + int16 dy; + int res; + + *tp = touchReadXY(); + + if (DS81_Config[DS81_AVERAGE_TOUCHSCREEN]) + { + dx = last.px - tp->px; + dy = last.py - tp->py; + + res = (abs(dx) < 5 && abs(dy) < 5); + } + else + { + res = TRUE; + } + + last = *tp; + + return res; +} diff --git a/source/zx81.c b/source/zx81.c index 9a053b5..7964ed1 100644 --- a/source/zx81.c +++ b/source/zx81.c @@ -41,9 +41,6 @@ #define FALSE 0 #endif -#define MAX_FNAME_LEN 30 - - /* ---------------------------------------- STATICS */ #define ROMLEN 0x2000 @@ -99,6 +96,8 @@ static int enable_filesystem; static const Z80Byte *tape_image; static int tape_len; +static char last_dir[FILENAME_MAX] = "/"; + /* GFX vars */ static uint16 *txt_screen; @@ -259,58 +258,58 @@ static Z80Byte FromASCII(char c) */ static FILE *OpenTapeFile(Z80Word addr) { + static const char zx_chars[] = "\"#$:?()><=+-*/;,." + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; FILE *fp; - char fn[MAX_FNAME_LEN]; + char fn[FILENAME_MAX]; int f; int done; - f=0; - done=FALSE; + fp = NULL; + f = 0; + done = FALSE; - while(f<(MAX_FNAME_LEN-3) && !done) + while(f<(FILENAME_MAX-3) && !done) { int ch; - ch=mem[addr++]; + ch = mem[addr++]; if (ch&0x80) { - done=TRUE; - ch&=0x7f; + done = TRUE; + ch &= 0x7f; } - switch(ch) + if (ch>=11 && ch<=63) { - case 22: - fn[f++]='-'; - break; - - case 27: - fn[f++]='.'; - - default: - if (ch>=28 && ch<=37) - { - fn[f++]='0'+(ch-28); - } - else if (ch>=38 && ch<=63) - { - fn[f++]='A'+(ch-38); - } - break; + fn[f++] = zx_chars[ch-11]; } } - fn[f++]='.'; - fn[f++]='P'; - fn[f]=0; + if (fn[0] == '*') + { + if (GUI_FileSelect(last_dir,fn,".P")) + { + fp = fopen(fn,"rb"); + } - if (!(fp=fopen(fn,"rb"))) + SK_DisplayKeyboard(BG_GFX_SUB); + } + else { - char full_fn[MAX_FNAME_LEN+11]="\\ZX81SNAP\\"; + fn[f++] = '.'; + fn[f++] = 'P'; + fn[f] = 0; - strcat(full_fn,fn); - fp=fopen(full_fn,"rb"); + if (!(fp = fopen(fn,"rb"))) + { + char full_fn[FILENAME_MAX+11] = "/ZX81SNAP/"; + + strcat(full_fn,fn); + fp = fopen(full_fn,"rb"); + } } return fp; @@ -378,7 +377,7 @@ static void DrawScreen_HIRES(Z80 *z80) bmp = bmp_screen; table = z80->I << 8; - /* scr is increment in both loops so that it can skip of the end-of-line + /* scr is increment in both loops so that it can skip the end-of-line character */ for(y=0; y<192; y++) |