diff options
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++) | 
