From b2b95d2e0d1fd5e52d03c2152605b09b024c1d0e Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 10 May 2007 22:31:19 +0000 Subject: [PATCH] partially working menu git-svn-id: file:///home/notaz/opt/svn/fceu@127 be3aeb3a-fb24-0410-a615-afba39da0efa --- Makefile.gp2x | 6 +- bench.txt | 1 + drivers/common/args.c | 29 +- drivers/common/args.h | 2 +- drivers/gp2x/asmutils.h | 1 + drivers/gp2x/asmutils.s | 12 + drivers/gp2x/cpuctrl.c | 156 +++++ drivers/gp2x/cpuctrl.h | 16 + drivers/gp2x/dface.h | 1 + drivers/gp2x/fonts.c | 218 +++++++ drivers/gp2x/fonts.h | 4 + drivers/gp2x/gp2x-sound.c | 19 +- drivers/gp2x/gp2x-video.c | 93 +-- drivers/gp2x/gp2x.c | 214 +++---- drivers/gp2x/gp2x.h | 46 +- drivers/gp2x/input.c | 13 +- drivers/gp2x/main.c | 102 +++- drivers/gp2x/main.h | 2 + drivers/gp2x/menu.c | 1091 +++++++++++++++++++++++++++++++++++ drivers/gp2x/menu.h | 5 + drivers/gp2x/minimal.c | 857 +++++++++++---------------- drivers/gp2x/minimal.h | 115 +--- drivers/gp2x/minimal_940t.h | 96 --- drivers/gp2x/throttle.c | 12 +- drivers/gp2x/usbjoy.c | 424 ++++++++++++++ drivers/gp2x/usbjoy.h | 241 ++++++++ fce.c | 6 +- 27 files changed, 2766 insertions(+), 1016 deletions(-) create mode 100644 drivers/gp2x/cpuctrl.c create mode 100644 drivers/gp2x/cpuctrl.h create mode 100644 drivers/gp2x/fonts.c create mode 100644 drivers/gp2x/fonts.h create mode 100644 drivers/gp2x/menu.c create mode 100644 drivers/gp2x/menu.h delete mode 100644 drivers/gp2x/minimal_940t.h create mode 100644 drivers/gp2x/usbjoy.c create mode 100644 drivers/gp2x/usbjoy.h diff --git a/Makefile.gp2x b/Makefile.gp2x index 137b353..a86f8c5 100644 --- a/Makefile.gp2x +++ b/Makefile.gp2x @@ -28,10 +28,10 @@ gpfce: fceu include zlib/Makefile -OBJDRIVER = ${B}minimal.o ${B}squidgehack.o ${B}asmutils.o ${B}gp2x.o ${B}main.o ${B}throttle.o \ - ${B}unix-netplay.o ${B}gp2x-sound.o ${B}gp2x-video.o ${B}lnx-joystick.o \ +OBJDRIVER = ${B}minimal.o ${B}cpuctrl.o ${B}squidgehack.o ${B}asmutils.o ${B}gp2x.o ${B}main.o ${B}throttle.o \ + ${B}unix-netplay.o ${B}gp2x-sound.o ${B}gp2x-video.o ${B}lnx-joystick.o ${B}usbjoy.o ${B}menu.o ${B}fonts.o \ drivers/common/cheat.o drivers/common/config.o drivers/common/args.o drivers/common/vidblit.o ${UNZIPOBJS} ppu.o movie.o -LDRIVER += -L /mnt/sd/lib -L/mnt/sd/gp2x/usr/lib -lm -lz -static -Wl,-Map=fceu.map +LDRIVER += -L /mnt/sd/lib -L/mnt/sd/gp2x/usr/lib -lm -lz -static -Wl,-Map=fceu.map ifeq ($(asm_6502),1) TFLAGS += -DASM_6502 diff --git a/bench.txt b/bench.txt index 1121918..b4605c5 100644 --- a/bench.txt +++ b/bench.txt @@ -17,4 +17,5 @@ v03+merge smb 95-96 bm 86-87 kage 82-83 +grad 72-73 diff --git a/drivers/common/args.c b/drivers/common/args.c index 7c6c8fe..964d931 100644 --- a/drivers/common/args.c +++ b/drivers/common/args.c @@ -33,15 +33,15 @@ #include "../../types.h" #include "args.h" -void ParseEA(int x, int argc, char *argv[], ARGPSTRUCT *argsps) +static int ParseEA(int x, int argc, char *argv[], ARGPSTRUCT *argsps) { - int y=0; + int y=0,ret=0; do { if(!argsps[y].name) { - ParseEA(x,argc,argv,(void *)argsps[y].var); + ret = ParseEA(x,argc,argv,(void *)argsps[y].var); y++; continue; } @@ -50,7 +50,7 @@ void ParseEA(int x, int argc, char *argv[], ARGPSTRUCT *argsps) if(argsps[y].subs) { if((x+1)>=argc) - break; + return 0; if(argsps[y].substype&0x8000) { *(int *)argsps[y].subs&=~(argsps[y].substype&(~0x8000)); @@ -69,23 +69,34 @@ void ParseEA(int x, int argc, char *argv[], ARGPSTRUCT *argsps) free(*(char **)argsps[y].subs); if(!( *(char **)argsps[y].subs=malloc(strlen(argv[x+1])+1) )) break; - } + } strcpy(*(char **)argsps[y].subs,argv[x+1]); break; } + ret=2; } - if(argsps[y].var) + else if(argsps[y].var) + { *argsps[y].var=1; + ret=1; + } } y++; } while(argsps[y].var || argsps[y].subs); + return ret; } -void ParseArguments(int argc, char *argv[], ARGPSTRUCT *argsps) +/* returns 1 if last arg was usccessfully parsed */ +int ParseArguments(int argc, char *argv[], ARGPSTRUCT *argsps) { - int x; + int x, ret=0; for(x=0;x +#include +#include "cpuctrl.h" + + +/* system registers */ +static struct +{ + unsigned short SYSCLKENREG,SYSCSETREG,FPLLVSETREG,DUALINT920,DUALINT940,DUALCTRL940,MEMTIMEX0,MEMTIMEX1; +} +system_reg; + +static unsigned short dispclockdiv; + +static volatile unsigned short *MEM_REG; + +#define SYS_CLK_FREQ 7372800 + + +void cpuctrl_init(void) +{ + extern volatile unsigned short *gp2x_memregs; /* from minimal library rlyeh */ + MEM_REG=&gp2x_memregs[0]; + system_reg.SYSCSETREG=MEM_REG[0x91c>>1]; + system_reg.FPLLVSETREG=MEM_REG[0x912>>1]; + system_reg.SYSCLKENREG=MEM_REG[0x904>>1]; + system_reg.DUALINT920=MEM_REG[0x3B40>>1]; + system_reg.DUALINT940=MEM_REG[0x3B42>>1]; + system_reg.DUALCTRL940=MEM_REG[0x3B48>>1]; + system_reg.MEMTIMEX0=MEM_REG[0x3802>>1]; + system_reg.MEMTIMEX1=MEM_REG[0x3804>>1]; + dispclockdiv=MEM_REG[0x924>>1]; +} + + +void cpuctrl_deinit(void) +{ + MEM_REG[0x91c>>1]=system_reg.SYSCSETREG; + MEM_REG[0x910>>1]=system_reg.FPLLVSETREG; + MEM_REG[0x3B40>>1]=system_reg.DUALINT920; + MEM_REG[0x3B42>>1]=system_reg.DUALINT940; + MEM_REG[0x3B48>>1]=system_reg.DUALCTRL940; + MEM_REG[0x904>>1]=system_reg.SYSCLKENREG; + MEM_REG[0x924>>1]=dispclockdiv; + MEM_REG[0x3802>>1]=system_reg.MEMTIMEX0; + MEM_REG[0x3804>>1]=system_reg.MEMTIMEX1 /*| 0x9000*/; +} + + +void set_display_clock_div(unsigned div) +{ + div=((div & 63) | 64)<<8; + MEM_REG[0x924>>1]=(MEM_REG[0x924>>1] & ~(255<<8)) | div; +} + + +void set_FCLK(unsigned MHZ) +{ + unsigned v; + unsigned mdiv,pdiv=3,scale=0; + MHZ*=1000000; + mdiv=(MHZ*pdiv)/SYS_CLK_FREQ; + mdiv=((mdiv-8)<<8) & 0xff00; + pdiv=((pdiv-2)<<2) & 0xfc; + scale&=3; + v=mdiv | pdiv | scale; + MEM_REG[0x910>>1]=v; +} + + +void set_920_Div(unsigned short div) +{ + unsigned short v; + v = MEM_REG[0x91c>>1] & (~0x3); + MEM_REG[0x91c>>1] = (div & 0x7) | v; +} + + +void set_DCLK_Div( unsigned short div ) +{ + unsigned short v; + v = (unsigned short)( MEM_REG[0x91c>>1] & (~(0x7 << 6)) ); + MEM_REG[0x91c>>1] = ((div & 0x7) << 6) | v; +} + +/* +void Disable_940(void) +{ + MEM_REG[0x3B42>>1]; + MEM_REG[0x3B42>>1]=0; + MEM_REG[0x3B46>>1]=0xffff; + MEM_REG[0x3B48>>1]|= (1 << 7); + MEM_REG[0x904>>1]&=0xfffe; +} +*/ + +void set_RAM_Timings(int tRC, int tRAS, int tWR, int tMRD, int tRFC, int tRP, int tRCD) +{ + tRC -= 1; tRAS -= 1; tWR -= 1; tMRD -= 1; tRFC -= 1; tRP -= 1; tRCD -= 1; // ??? + MEM_REG[0x3802>>1] = ((tMRD & 0xF) << 12) | ((tRFC & 0xF) << 8) | ((tRP & 0xF) << 4) | (tRCD & 0xF); + MEM_REG[0x3804>>1] = /*0x9000 |*/ ((tRC & 0xF) << 8) | ((tRAS & 0xF) << 4) | (tWR & 0xF); +} + + +/* +void gp2x_video_wait_vsync(void) +{ + MEM_REG[0x2846>>1]=(MEM_REG[0x2846>>1] | 0x20) & ~2; + while(!(MEM_REG[0x2846>>1] & 2)); +} +*/ + +void set_gamma(int g100) +{ + float gamma = (float) g100 / 100; + int i; + //printf ("set gamma = %f\r\n",gamma); + gamma = 1/gamma; + + //enable gamma + MEM_REG[0x2880>>1]&=~(1<<12); + + MEM_REG[0x295C>>1]=0; + for(i=0; i<256; i++) + { + unsigned char g; + unsigned short s; + g =(unsigned char)(255.0*pow(i/255.0,gamma)); + s = (g<<8) | g; + MEM_REG[0x295E>>1]= s; + MEM_REG[0x295E>>1]= g; + } +} + diff --git a/drivers/gp2x/cpuctrl.h b/drivers/gp2x/cpuctrl.h new file mode 100644 index 0000000..5b482a5 --- /dev/null +++ b/drivers/gp2x/cpuctrl.h @@ -0,0 +1,16 @@ +#ifndef __CPUCTRL_H__ +#define __CPUCTRL_H__ + +extern void cpuctrl_init(void); /* call this at first */ +extern void save_system_regs(void); /* save some registers */ +extern void cpuctrl_deinit(void); +extern void set_display_clock_div(unsigned div); +extern void set_FCLK(unsigned MHZ); /* adjust the clock frequency (in Mhz units) */ +extern void set_920_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */ +extern void set_DCLK_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */ +//extern void Disable_940(void); /* 940t down */ +//extern void gp2x_video_wait_vsync(void); +extern void set_RAM_Timings(int tRC, int tRAS, int tWR, int tMRD, int tRFC, int tRP, int tRCD); +extern void set_gamma(int g100); + +#endif diff --git a/drivers/gp2x/dface.h b/drivers/gp2x/dface.h index c4d2bfb..f2c569e 100644 --- a/drivers/gp2x/dface.h +++ b/drivers/gp2x/dface.h @@ -7,6 +7,7 @@ void GetBaseDirectory(char *BaseDirectory); int InitSound(void); void WriteSound(int16 *Buffer, int Count); + void KillSound(void); void SilenceSound(int s); /* DOS and SDL */ diff --git a/drivers/gp2x/fonts.c b/drivers/gp2x/fonts.c new file mode 100644 index 0000000..ea65481 --- /dev/null +++ b/drivers/gp2x/fonts.c @@ -0,0 +1,218 @@ +unsigned char fontdata8x8[64*16] = +{ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3C,0x42,0x99,0xBD,0xBD,0x99,0x42,0x3C,0x3C,0x42,0x81,0x81,0x81,0x81,0x42,0x3C, + 0xFE,0x82,0x8A,0xD2,0xA2,0x82,0xFE,0x00,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x64,0x74,0x7C,0x38,0x00,0x00, + 0x80,0xC0,0xF0,0xFC,0xF0,0xC0,0x80,0x00,0x01,0x03,0x0F,0x3F,0x0F,0x03,0x01,0x00, + 0x18,0x3C,0x7E,0x18,0x7E,0x3C,0x18,0x00,0xEE,0xEE,0xEE,0xCC,0x00,0xCC,0xCC,0x00, + 0x00,0x00,0x30,0x68,0x78,0x30,0x00,0x00,0x00,0x38,0x64,0x74,0x7C,0x38,0x00,0x00, + 0x3C,0x66,0x7A,0x7A,0x7E,0x7E,0x3C,0x00,0x0E,0x3E,0x3A,0x22,0x26,0x6E,0xE4,0x40, + 0x18,0x3C,0x7E,0x3C,0x3C,0x3C,0x3C,0x00,0x3C,0x3C,0x3C,0x3C,0x7E,0x3C,0x18,0x00, + 0x08,0x7C,0x7E,0x7E,0x7C,0x08,0x00,0x00,0x10,0x3E,0x7E,0x7E,0x3E,0x10,0x00,0x00, + 0x58,0x2A,0xDC,0xC8,0xDC,0x2A,0x58,0x00,0x24,0x66,0xFF,0xFF,0x66,0x24,0x00,0x00, + 0x00,0x10,0x10,0x38,0x38,0x7C,0xFE,0x00,0xFE,0x7C,0x38,0x38,0x10,0x10,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x18,0x00,0x18,0x18,0x00, + 0x6C,0x6C,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x7C,0x28,0x7C,0x28,0x00,0x00, + 0x10,0x38,0x60,0x38,0x0C,0x78,0x10,0x00,0x40,0xA4,0x48,0x10,0x24,0x4A,0x04,0x00, + 0x18,0x34,0x18,0x3A,0x6C,0x66,0x3A,0x00,0x18,0x18,0x20,0x00,0x00,0x00,0x00,0x00, + 0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x00,0x0C,0x06,0x06,0x06,0x06,0x06,0x0C,0x00, + 0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00, + 0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x00,0x00, + 0x38,0x4C,0xC6,0xC6,0xC6,0x64,0x38,0x00,0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00, + 0x7C,0xC6,0x0E,0x3C,0x78,0xE0,0xFE,0x00,0x7E,0x0C,0x18,0x3C,0x06,0xC6,0x7C,0x00, + 0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x00,0xFC,0xC0,0xFC,0x06,0x06,0xC6,0x7C,0x00, + 0x3C,0x60,0xC0,0xFC,0xC6,0xC6,0x7C,0x00,0xFE,0xC6,0x0C,0x18,0x30,0x30,0x30,0x00, + 0x78,0xC4,0xE4,0x78,0x86,0x86,0x7C,0x00,0x7C,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, + 0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x18,0x18,0x30, + 0x1C,0x38,0x70,0xE0,0x70,0x38,0x1C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, + 0x70,0x38,0x1C,0x0E,0x1C,0x38,0x70,0x00,0x7C,0xC6,0xC6,0x1C,0x18,0x00,0x18,0x00, + 0x3C,0x42,0x99,0xA1,0xA5,0x99,0x42,0x3C,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00, + 0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00,0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00, + 0xF8,0xCC,0xC6,0xC6,0xC6,0xCC,0xF8,0x00,0xFE,0xC0,0xC0,0xFC,0xC0,0xC0,0xFE,0x00, + 0xFE,0xC0,0xC0,0xFC,0xC0,0xC0,0xC0,0x00,0x3E,0x60,0xC0,0xCE,0xC6,0x66,0x3E,0x00, + 0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x7E,0x00, + 0x06,0x06,0x06,0x06,0xC6,0xC6,0x7C,0x00,0xC6,0xCC,0xD8,0xF0,0xF8,0xDC,0xCE,0x00, + 0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0x00, + 0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, + 0xFC,0xC6,0xC6,0xC6,0xFC,0xC0,0xC0,0x00,0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x7A,0x00, + 0xFC,0xC6,0xC6,0xCE,0xF8,0xDC,0xCE,0x00,0x78,0xCC,0xC0,0x7C,0x06,0xC6,0x7C,0x00, + 0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, + 0xC6,0xC6,0xC6,0xEE,0x7C,0x38,0x10,0x00,0xC6,0xC6,0xD6,0xFE,0xFE,0xEE,0xC6,0x00, + 0xC6,0xEE,0x3C,0x38,0x7C,0xEE,0xC6,0x00,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00, + 0xFE,0x0E,0x1C,0x38,0x70,0xE0,0xFE,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00, + 0x60,0x60,0x30,0x18,0x0C,0x06,0x06,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00, + 0x18,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, + 0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x3E,0x66,0x66,0x3C,0x00, + 0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x00, + 0x06,0x3E,0x66,0x66,0x66,0x66,0x3E,0x00,0x00,0x3C,0x66,0x66,0x7E,0x60,0x3C,0x00, + 0x1C,0x30,0x78,0x30,0x30,0x30,0x30,0x00,0x00,0x3E,0x66,0x66,0x66,0x3E,0x06,0x3C, + 0x60,0x7C,0x76,0x66,0x66,0x66,0x66,0x00,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x00, + 0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x38,0x60,0x60,0x66,0x6C,0x78,0x6C,0x66,0x00, + 0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0xEC,0xFE,0xFE,0xFE,0xD6,0xC6,0x00, + 0x00,0x7C,0x76,0x66,0x66,0x66,0x66,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00, + 0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60,0x00,0x3E,0x66,0x66,0x66,0x3E,0x06,0x06, + 0x00,0x7E,0x70,0x60,0x60,0x60,0x60,0x00,0x00,0x3C,0x60,0x3C,0x06,0x66,0x3C,0x00, + 0x30,0x78,0x30,0x30,0x30,0x30,0x1C,0x00,0x00,0x66,0x66,0x66,0x66,0x6E,0x3E,0x00, + 0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0xC6,0xD6,0xFE,0xFE,0x7C,0x6C,0x00, + 0x00,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,0x00,0x66,0x66,0x66,0x66,0x3E,0x06,0x3C, + 0x00,0x7E,0x0C,0x18,0x30,0x60,0x7E,0x00,0x0E,0x18,0x0C,0x38,0x0C,0x18,0x0E,0x00, + 0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x70,0x18,0x30,0x1C,0x30,0x18,0x70,0x00, + 0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x10,0x28,0x10,0x54,0xAA,0x44,0x00,0x00, +}; + + +/* The font is generated from Xorg clR5x8.bdf */ +/* +COMMENT Copyright 1989 Dale Schumacher, dal@syntel.mn.org +COMMENT 399 Beacon Ave. +COMMENT St. Paul, MN 55104-3527 +COMMENT +COMMENT Permission to use, copy, modify, and distribute this software and +COMMENT its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notice appear in all +COMMENT copies and that both that copyright notice and this permission +COMMENT notice appear in supporting documentation, and that the name of +COMMENT Dale Schumacher not be used in advertising or publicity pertaining to +COMMENT distribution of the software without specific, written prior +COMMENT permission. Dale Schumacher makes no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT +*/ +unsigned char fontdata6x8[256][8] = { +{ 0x7c>>2, 0x44>>2, 0x7c>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0xff>>2, 0x7c>>2, }, +{ 0x00>>2, 0x00>>2, 0x10>>2, 0x28>>2, 0x44>>2, 0x7c>>2, 0x44>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x78>>2, 0x44>>2, 0x78>>2, 0x44>>2, 0x78>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x38>>2, 0x44>>2, 0x40>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x78>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x78>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x7c>>2, 0x40>>2, 0x78>>2, 0x40>>2, 0x7c>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x7c>>2, 0x40>>2, 0x78>>2, 0x40>>2, 0x40>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x3c>>2, 0x40>>2, 0x4c>>2, 0x44>>2, 0x3c>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x44>>2, 0x7c>>2, 0x44>>2, 0x44>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x38>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x38>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x1c>>2, 0x04>>2, 0x04>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x48>>2, 0x50>>2, 0x60>>2, 0x50>>2, 0x48>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x40>>2, 0x40>>2, 0x40>>2, 0x40>>2, 0x7c>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x6c>>2, 0x54>>2, 0x54>>2, 0x44>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x64>>2, 0x54>>2, 0x4c>>2, 0x44>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x38>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x78>>2, 0x44>>2, 0x78>>2, 0x40>>2, 0x40>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x38>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x38>>2, 0x0c>>2, }, +{ 0x00>>2, 0x00>>2, 0x78>>2, 0x44>>2, 0x78>>2, 0x50>>2, 0x4c>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x3c>>2, 0x40>>2, 0x38>>2, 0x04>>2, 0x78>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x7c>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x44>>2, 0x28>>2, 0x28>>2, 0x10>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x54>>2, 0x54>>2, 0x6c>>2, 0x44>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x28>>2, 0x10>>2, 0x28>>2, 0x44>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x28>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x7c>>2, 0x08>>2, 0x10>>2, 0x20>>2, 0x7c>>2, 0x00>>2, }, +{ 0xe0>>2, 0x80>>2, 0xe0>>2, 0x8c>>2, 0xf0>>2, 0x10>>2, 0x10>>2, 0x0c>>2, }, +{ 0x00>>2, 0x10>>2, 0x38>>2, 0x7c>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x00>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x7c>>2, 0x38>>2, 0x10>>2, 0x00>>2, }, +{ 0x00>>2, 0x10>>2, 0x18>>2, 0xfc>>2, 0x18>>2, 0x10>>2, 0x00>>2, 0x00>>2, }, +{ 0x00>>2, 0x20>>2, 0x60>>2, 0xfc>>2, 0x60>>2, 0x20>>2, 0x00>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, }, +{ 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x00>>2, 0x10>>2, 0x00>>2, }, +{ 0x28>>2, 0x28>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, }, +{ 0x00>>2, 0x28>>2, 0x7c>>2, 0x28>>2, 0x7c>>2, 0x28>>2, 0x00>>2, 0x00>>2, }, +{ 0x10>>2, 0x3c>>2, 0x50>>2, 0x38>>2, 0x14>>2, 0x78>>2, 0x10>>2, 0x00>>2, }, +{ 0x60>>2, 0x64>>2, 0x08>>2, 0x10>>2, 0x20>>2, 0x4c>>2, 0x0c>>2, 0x00>>2, }, +{ 0x38>>2, 0x40>>2, 0x40>>2, 0x20>>2, 0x54>>2, 0x48>>2, 0x34>>2, 0x00>>2, }, +{ 0x10>>2, 0x20>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, }, +{ 0x04>>2, 0x08>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x08>>2, 0x04>>2, 0x00>>2, }, +{ 0x40>>2, 0x20>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x20>>2, 0x40>>2, 0x00>>2, }, +{ 0x00>>2, 0x10>>2, 0x54>>2, 0x38>>2, 0x54>>2, 0x10>>2, 0x00>>2, 0x00>>2, }, +{ 0x00>>2, 0x10>>2, 0x10>>2, 0x7c>>2, 0x10>>2, 0x10>>2, 0x00>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x10>>2, 0x10>>2, 0x20>>2, }, +{ 0x00>>2, 0x00>>2, 0x00>>2, 0x7c>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x04>>2, 0x04>>2, 0x08>>2, 0x08>>2, 0x10>>2, 0x10>>2, 0x20>>2, 0x20>>2, }, +{ 0x38>>2, 0x44>>2, 0x4c>>2, 0x54>>2, 0x64>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x10>>2, 0x30>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x38>>2, 0x44>>2, 0x04>>2, 0x08>>2, 0x10>>2, 0x20>>2, 0x7c>>2, 0x00>>2, }, +{ 0x38>>2, 0x44>>2, 0x04>>2, 0x18>>2, 0x04>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x18>>2, 0x18>>2, 0x28>>2, 0x28>>2, 0x7c>>2, 0x08>>2, 0x1c>>2, 0x00>>2, }, +{ 0x7c>>2, 0x40>>2, 0x78>>2, 0x04>>2, 0x04>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x18>>2, 0x20>>2, 0x40>>2, 0x78>>2, 0x44>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x7c>>2, 0x44>>2, 0x04>>2, 0x08>>2, 0x08>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x38>>2, 0x44>>2, 0x44>>2, 0x38>>2, 0x44>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x38>>2, 0x44>>2, 0x44>>2, 0x3c>>2, 0x04>>2, 0x08>>2, 0x30>>2, 0x00>>2, }, +{ 0x00>>2, 0x10>>2, 0x10>>2, 0x00>>2, 0x00>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x00>>2, 0x10>>2, 0x10>>2, 0x00>>2, 0x00>>2, 0x10>>2, 0x10>>2, 0x20>>2, }, +{ 0x00>>2, 0x0c>>2, 0x30>>2, 0xc0>>2, 0x30>>2, 0x0c>>2, 0x00>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x7c>>2, 0x00>>2, 0x7c>>2, 0x00>>2, 0x00>>2, 0x00>>2, }, +{ 0x00>>2, 0xc0>>2, 0x30>>2, 0x0c>>2, 0x30>>2, 0xc0>>2, 0x00>>2, 0x00>>2, }, +{ 0x38>>2, 0x44>>2, 0x04>>2, 0x08>>2, 0x10>>2, 0x00>>2, 0x10>>2, 0x00>>2, }, +{ 0x38>>2, 0x44>>2, 0x5c>>2, 0x5c>>2, 0x58>>2, 0x40>>2, 0x38>>2, 0x00>>2, }, +{ 0x10>>2, 0x28>>2, 0x44>>2, 0x44>>2, 0x7c>>2, 0x44>>2, 0x44>>2, 0x00>>2, }, +{ 0x78>>2, 0x44>>2, 0x44>>2, 0x78>>2, 0x44>>2, 0x44>>2, 0x78>>2, 0x00>>2, }, +{ 0x38>>2, 0x44>>2, 0x40>>2, 0x40>>2, 0x40>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x70>>2, 0x48>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x48>>2, 0x70>>2, 0x00>>2, }, +{ 0x7c>>2, 0x40>>2, 0x40>>2, 0x78>>2, 0x40>>2, 0x40>>2, 0x7c>>2, 0x00>>2, }, +{ 0x7c>>2, 0x40>>2, 0x40>>2, 0x78>>2, 0x40>>2, 0x40>>2, 0x40>>2, 0x00>>2, }, +{ 0x38>>2, 0x44>>2, 0x40>>2, 0x4c>>2, 0x44>>2, 0x44>>2, 0x3c>>2, 0x00>>2, }, +{ 0x44>>2, 0x44>>2, 0x44>>2, 0x7c>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x00>>2, }, +{ 0x7c>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x7c>>2, 0x00>>2, }, +{ 0x1c>>2, 0x04>>2, 0x04>>2, 0x04>>2, 0x44>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x44>>2, 0x48>>2, 0x50>>2, 0x60>>2, 0x50>>2, 0x48>>2, 0x44>>2, 0x00>>2, }, +{ 0x40>>2, 0x40>>2, 0x40>>2, 0x40>>2, 0x40>>2, 0x40>>2, 0x7c>>2, 0x00>>2, }, +{ 0x44>>2, 0x6c>>2, 0x54>>2, 0x54>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x00>>2, }, +{ 0x44>>2, 0x64>>2, 0x64>>2, 0x54>>2, 0x4c>>2, 0x4c>>2, 0x44>>2, 0x00>>2, }, +{ 0x38>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x78>>2, 0x44>>2, 0x44>>2, 0x78>>2, 0x40>>2, 0x40>>2, 0x40>>2, 0x00>>2, }, +{ 0x38>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x38>>2, 0x0c>>2, }, +{ 0x78>>2, 0x44>>2, 0x44>>2, 0x78>>2, 0x50>>2, 0x48>>2, 0x44>>2, 0x00>>2, }, +{ 0x38>>2, 0x44>>2, 0x40>>2, 0x38>>2, 0x04>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x7c>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x44>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x44>>2, 0x44>>2, 0x44>>2, 0x28>>2, 0x28>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x44>>2, 0x44>>2, 0x44>>2, 0x54>>2, 0x54>>2, 0x6c>>2, 0x44>>2, 0x00>>2, }, +{ 0x44>>2, 0x44>>2, 0x28>>2, 0x10>>2, 0x28>>2, 0x44>>2, 0x44>>2, 0x00>>2, }, +{ 0x44>>2, 0x44>>2, 0x28>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x7c>>2, 0x04>>2, 0x08>>2, 0x10>>2, 0x20>>2, 0x40>>2, 0x7c>>2, 0x00>>2, }, +{ 0x1c>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x1c>>2, 0x00>>2, }, +{ 0x20>>2, 0x20>>2, 0x10>>2, 0x10>>2, 0x08>>2, 0x08>>2, 0x04>>2, 0x04>>2, }, +{ 0x70>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x70>>2, 0x00>>2, }, +{ 0x10>>2, 0x28>>2, 0x44>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0xfc>>2, 0x00>>2, }, +{ 0x10>>2, 0x08>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x3c>>2, 0x44>>2, 0x44>>2, 0x4c>>2, 0x34>>2, 0x00>>2, }, +{ 0x40>>2, 0x40>>2, 0x78>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x78>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x3c>>2, 0x40>>2, 0x40>>2, 0x40>>2, 0x3c>>2, 0x00>>2, }, +{ 0x04>>2, 0x04>>2, 0x3c>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x3c>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x38>>2, 0x44>>2, 0x7c>>2, 0x40>>2, 0x38>>2, 0x00>>2, }, +{ 0x1c>>2, 0x20>>2, 0x78>>2, 0x20>>2, 0x20>>2, 0x20>>2, 0x20>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x3c>>2, 0x44>>2, 0x44>>2, 0x3c>>2, 0x04>>2, 0x38>>2, }, +{ 0x40>>2, 0x40>>2, 0x78>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x00>>2, }, +{ 0x10>>2, 0x00>>2, 0x30>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x38>>2, 0x00>>2, }, +{ 0x08>>2, 0x00>>2, 0x38>>2, 0x08>>2, 0x08>>2, 0x08>>2, 0x08>>2, 0x70>>2, }, +{ 0x40>>2, 0x40>>2, 0x48>>2, 0x50>>2, 0x60>>2, 0x50>>2, 0x48>>2, 0x00>>2, }, +{ 0x30>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x38>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x68>>2, 0x54>>2, 0x54>>2, 0x54>>2, 0x44>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x58>>2, 0x64>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x38>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x38>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x78>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x78>>2, 0x40>>2, }, +{ 0x00>>2, 0x00>>2, 0x3c>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x3c>>2, 0x04>>2, }, +{ 0x00>>2, 0x00>>2, 0x58>>2, 0x60>>2, 0x40>>2, 0x40>>2, 0x40>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x3c>>2, 0x40>>2, 0x38>>2, 0x04>>2, 0x78>>2, 0x00>>2, }, +{ 0x10>>2, 0x10>>2, 0x7c>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x0c>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x4c>>2, 0x34>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x6c>>2, 0x28>>2, 0x28>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x54>>2, 0x54>>2, 0x54>>2, 0x28>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x28>>2, 0x10>>2, 0x28>>2, 0x44>>2, 0x00>>2, }, +{ 0x00>>2, 0x00>>2, 0x44>>2, 0x44>>2, 0x44>>2, 0x3c>>2, 0x04>>2, 0x38>>2, }, +{ 0x00>>2, 0x00>>2, 0x7c>>2, 0x08>>2, 0x10>>2, 0x20>>2, 0x7c>>2, 0x00>>2, }, +{ 0x04>>2, 0x08>>2, 0x08>>2, 0x10>>2, 0x08>>2, 0x08>>2, 0x04>>2, 0x00>>2, }, +{ 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x10>>2, 0x00>>2, }, +{ 0x40>>2, 0x20>>2, 0x20>>2, 0x10>>2, 0x20>>2, 0x20>>2, 0x40>>2, 0x00>>2, }, +{ 0x20>>2, 0x54>>2, 0x08>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, 0x00>>2, }, +{ 0x00>>2, 0x10>>2, 0x10>>2, 0x28>>2, 0x28>>2, 0x44>>2, 0x7c>>2, 0x00>>2, }, +}; + diff --git a/drivers/gp2x/fonts.h b/drivers/gp2x/fonts.h new file mode 100644 index 0000000..dbbdd4c --- /dev/null +++ b/drivers/gp2x/fonts.h @@ -0,0 +1,4 @@ + +extern unsigned char fontdata8x8[64*16]; +extern unsigned char fontdata6x8[256-32][8]; + diff --git a/drivers/gp2x/gp2x-sound.c b/drivers/gp2x/gp2x-sound.c index 30934bc..20af608 100644 --- a/drivers/gp2x/gp2x-sound.c +++ b/drivers/gp2x/gp2x-sound.c @@ -16,37 +16,22 @@ */ #include -#include -#include -#include -#include -#include -#include +#include "../../driver.h" #include "gp2x.h" #include "minimal.h" #include "throttle.h" extern int soundvol; -extern unsigned long gp2x_dev[8]; -// always have this call -INLINE void gp2x_sound_frame(void *blah, void *buff, int samples) -{ -} void WriteSound(int16 *Buffer, int Count) { - write(gp2x_dev[3], Buffer, Count<<1); + gp2x_sound_write(Buffer, Count<<1); SpeedThrottle(); } -void* gp2x_write_sound(void* blah) -{ - return NULL; -} - void SilenceSound(int n) { soundvol=0; diff --git a/drivers/gp2x/gp2x-video.c b/drivers/gp2x/gp2x-video.c index 03d4abc..d74023a 100644 --- a/drivers/gp2x/gp2x-video.c +++ b/drivers/gp2x/gp2x-video.c @@ -21,88 +21,24 @@ #include "../../video.h" +#include "main.h" #include "gp2x.h" #include "minimal.h" +#include "fonts.h" extern int showfps; static char fps_str[32]; static int framesEmulated, framesRendered; +int gp2x_palette[256]; + int scaled_display=0; int paletterefresh; #define FPS_COLOR 1 -static unsigned char fontdata8x8[] = -{ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x3C,0x42,0x99,0xBD,0xBD,0x99,0x42,0x3C,0x3C,0x42,0x81,0x81,0x81,0x81,0x42,0x3C, - 0xFE,0x82,0x8A,0xD2,0xA2,0x82,0xFE,0x00,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x64,0x74,0x7C,0x38,0x00,0x00, - 0x80,0xC0,0xF0,0xFC,0xF0,0xC0,0x80,0x00,0x01,0x03,0x0F,0x3F,0x0F,0x03,0x01,0x00, - 0x18,0x3C,0x7E,0x18,0x7E,0x3C,0x18,0x00,0xEE,0xEE,0xEE,0xCC,0x00,0xCC,0xCC,0x00, - 0x00,0x00,0x30,0x68,0x78,0x30,0x00,0x00,0x00,0x38,0x64,0x74,0x7C,0x38,0x00,0x00, - 0x3C,0x66,0x7A,0x7A,0x7E,0x7E,0x3C,0x00,0x0E,0x3E,0x3A,0x22,0x26,0x6E,0xE4,0x40, - 0x18,0x3C,0x7E,0x3C,0x3C,0x3C,0x3C,0x00,0x3C,0x3C,0x3C,0x3C,0x7E,0x3C,0x18,0x00, - 0x08,0x7C,0x7E,0x7E,0x7C,0x08,0x00,0x00,0x10,0x3E,0x7E,0x7E,0x3E,0x10,0x00,0x00, - 0x58,0x2A,0xDC,0xC8,0xDC,0x2A,0x58,0x00,0x24,0x66,0xFF,0xFF,0x66,0x24,0x00,0x00, - 0x00,0x10,0x10,0x38,0x38,0x7C,0xFE,0x00,0xFE,0x7C,0x38,0x38,0x10,0x10,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x18,0x00,0x18,0x18,0x00, - 0x6C,0x6C,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x7C,0x28,0x7C,0x28,0x00,0x00, - 0x10,0x38,0x60,0x38,0x0C,0x78,0x10,0x00,0x40,0xA4,0x48,0x10,0x24,0x4A,0x04,0x00, - 0x18,0x34,0x18,0x3A,0x6C,0x66,0x3A,0x00,0x18,0x18,0x20,0x00,0x00,0x00,0x00,0x00, - 0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x00,0x0C,0x06,0x06,0x06,0x06,0x06,0x0C,0x00, - 0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00, - 0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x00,0x00, - 0x38,0x4C,0xC6,0xC6,0xC6,0x64,0x38,0x00,0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00, - 0x7C,0xC6,0x0E,0x3C,0x78,0xE0,0xFE,0x00,0x7E,0x0C,0x18,0x3C,0x06,0xC6,0x7C,0x00, - 0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x00,0xFC,0xC0,0xFC,0x06,0x06,0xC6,0x7C,0x00, - 0x3C,0x60,0xC0,0xFC,0xC6,0xC6,0x7C,0x00,0xFE,0xC6,0x0C,0x18,0x30,0x30,0x30,0x00, - 0x78,0xC4,0xE4,0x78,0x86,0x86,0x7C,0x00,0x7C,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, - 0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x18,0x18,0x30, - 0x1C,0x38,0x70,0xE0,0x70,0x38,0x1C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, - 0x70,0x38,0x1C,0x0E,0x1C,0x38,0x70,0x00,0x7C,0xC6,0xC6,0x1C,0x18,0x00,0x18,0x00, - 0x3C,0x42,0x99,0xA1,0xA5,0x99,0x42,0x3C,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00, - 0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00,0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00, - 0xF8,0xCC,0xC6,0xC6,0xC6,0xCC,0xF8,0x00,0xFE,0xC0,0xC0,0xFC,0xC0,0xC0,0xFE,0x00, - 0xFE,0xC0,0xC0,0xFC,0xC0,0xC0,0xC0,0x00,0x3E,0x60,0xC0,0xCE,0xC6,0x66,0x3E,0x00, - 0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x7E,0x00, - 0x06,0x06,0x06,0x06,0xC6,0xC6,0x7C,0x00,0xC6,0xCC,0xD8,0xF0,0xF8,0xDC,0xCE,0x00, - 0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0x00, - 0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, - 0xFC,0xC6,0xC6,0xC6,0xFC,0xC0,0xC0,0x00,0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x7A,0x00, - 0xFC,0xC6,0xC6,0xCE,0xF8,0xDC,0xCE,0x00,0x78,0xCC,0xC0,0x7C,0x06,0xC6,0x7C,0x00, - 0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, - 0xC6,0xC6,0xC6,0xEE,0x7C,0x38,0x10,0x00,0xC6,0xC6,0xD6,0xFE,0xFE,0xEE,0xC6,0x00, - 0xC6,0xEE,0x3C,0x38,0x7C,0xEE,0xC6,0x00,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00, - 0xFE,0x0E,0x1C,0x38,0x70,0xE0,0xFE,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00, - 0x60,0x60,0x30,0x18,0x0C,0x06,0x06,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00, - 0x18,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, - 0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x3E,0x66,0x66,0x3C,0x00, - 0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x00, - 0x06,0x3E,0x66,0x66,0x66,0x66,0x3E,0x00,0x00,0x3C,0x66,0x66,0x7E,0x60,0x3C,0x00, - 0x1C,0x30,0x78,0x30,0x30,0x30,0x30,0x00,0x00,0x3E,0x66,0x66,0x66,0x3E,0x06,0x3C, - 0x60,0x7C,0x76,0x66,0x66,0x66,0x66,0x00,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x00, - 0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x38,0x60,0x60,0x66,0x6C,0x78,0x6C,0x66,0x00, - 0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0xEC,0xFE,0xFE,0xFE,0xD6,0xC6,0x00, - 0x00,0x7C,0x76,0x66,0x66,0x66,0x66,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00, - 0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60,0x00,0x3E,0x66,0x66,0x66,0x3E,0x06,0x06, - 0x00,0x7E,0x70,0x60,0x60,0x60,0x60,0x00,0x00,0x3C,0x60,0x3C,0x06,0x66,0x3C,0x00, - 0x30,0x78,0x30,0x30,0x30,0x30,0x1C,0x00,0x00,0x66,0x66,0x66,0x66,0x6E,0x3E,0x00, - 0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0xC6,0xD6,0xFE,0xFE,0x7C,0x6C,0x00, - 0x00,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,0x00,0x66,0x66,0x66,0x66,0x3E,0x06,0x3C, - 0x00,0x7E,0x0C,0x18,0x30,0x60,0x7E,0x00,0x0E,0x18,0x0C,0x38,0x0C,0x18,0x0E,0x00, - 0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x70,0x18,0x30,0x1C,0x30,0x18,0x70,0x00, - 0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x10,0x28,0x10,0x54,0xAA,0x44,0x00,0x00, -}; - static void gp2x_text(unsigned char *screen, int x, int y, char *text, int color, int flip) { int i,l,slen; @@ -135,10 +71,10 @@ void CleanSurface(void) int c=4; while (c--) { - memset (gp2x_screen8, 0, 320*240); + memset(gp2x_screen, 0, 320*240); gp2x_video_flip(); } - XBuf = gp2x_screen8; + XBuf = gp2x_screen; } @@ -157,7 +93,7 @@ int InitVideo(void) srendline=0; erendline=239; - XBuf = gp2x_screen8; + XBuf = gp2x_screen; return 1; } @@ -169,8 +105,8 @@ void ToggleFS(void) void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b) { - gp2x_video_color8(index, r, g, b); - gp2x_video_setpalette(); + gp2x_palette[index] = (r << 16) | (g << 8) | b; + gp2x_video_setpalette(gp2x_palette, index + 1); paletterefresh = 1; } @@ -178,9 +114,10 @@ void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b) void FCEUD_GetPalette(uint8 index, uint8 * r, uint8 * g, uint8 * b) { - *r = (uint8) gp2x_palette[(index << 1) + 1]; - *g = (uint8) (gp2x_palette[(index << 1) + 0] >> 8); - *b = (uint8) gp2x_palette[(index << 1) + 0]; + int pix = gp2x_palette[index]; + *r = (uint8) (pix >> 16); + *g = (uint8) (pix >> 8); + *b = (uint8) pix; } @@ -242,9 +179,9 @@ void BlitScreen(uint8 *buf) framesRendered++; - printFps(gp2x_screen8); + printFps(gp2x_screen); gp2x_video_flip(); - XBuf = gp2x_screen8; + XBuf = gp2x_screen; } diff --git a/drivers/gp2x/gp2x.c b/drivers/gp2x/gp2x.c index fc70dd1..e7c3a0e 100644 --- a/drivers/gp2x/gp2x.c +++ b/drivers/gp2x/gp2x.c @@ -2,98 +2,72 @@ #include #include +#include "../../driver.h" +#include "../common/config.h" +#include "../common/args.h" #include "gp2x.h" #include "gp2x-video.h" #ifdef NETWORK #include "unix-netplay.h" #endif + #include "minimal.h" +#include "cpuctrl.h" +#include "squidgehack.h" int CLImain(int argc, char *argv[]); -extern void SetVideoScaling(int, int, int); //#define SOUND_RATE 44100 #define SOUND_RATE 22050 -#define GP2X_PORT_VERSION "0.3" +#define GP2X_PORT_VERSION "0.4" DSETTINGS Settings; CFGSTRUCT DriverConfig[]={ - AC(_xscale), - AC(_yscale), - AC(_xscalefs), - AC(_yscalefs), - AC(_efx), - AC(_efxfs), - AC(_sound), - #ifdef DSPSOUND - AC(_f8bit), - #else - AC(_ebufsize), - AC(_lbufsize), - #endif - AC(_fullscreen), - AC(_xres), - AC(_yres), - ACA(joyBMap), - ACA(joyAMap), - ACA(joy), - //ACS(_fshack), + AC(Settings.sound), + ACA(Settings.joyBMap), + ACA(Settings.joyAMap), + ACA(Settings.joy), + AC(Settings.showfps), + AC(Settings.scaling), + AC(Settings.frameskip), + AC(Settings.sstate_confirm), + AC(Settings.region_force), + AC(Settings.cpuclock), + AC(Settings.mmuhack), + AC(Settings.ramtimings), + // TODO ENDCFGSTRUCT }; -//-fshack x Set the environment variable SDL_VIDEODRIVER to \"x\" when -// entering full screen mode and x is not \"0\". char *DriverUsage= -"-xres x Set horizontal resolution to x for full screen mode.\n\ --yres x Set vertical resolution to x for full screen mode.\n\ --xscale(fs) x Multiply width by x.\n\ --yscale(fs) x Multiply height by x.\n\ --efx(fs) x Enable scanlines effect if x is non zero. yscale must be >=2\n\ - and preferably a multiple of 2.\n\ --fs x Select full screen mode if x is non zero.\n\ --joyx y Use joystick y as virtual joystick x.\n\ +"-joyx y Use joystick y as virtual joystick x.\n\ -sound x Sound.\n\ 0 = Disabled.\n\ Otherwise, x = playback rate.\n\ +-showfps x Display fps counter if x is nonzero\n\ +-mmuhack x Enable squidge's MMU hack if x is nonzero (GP2X).\n\ +-ramtimings x Enable RAM overclocking if x is nonzero (GP2X).\n\ " -#ifdef DSPSOUND -"-f8bit x Force 8-bit sound.\n\ - 0 = Disabled.\n\ - 1 = Enabled.\n\ -" -#else -"-lbufsize x Internal FCE Ultra sound buffer size. Size = 2^x samples.\n\ --ebufsize x External SDL sound buffer size. Size = 2^x samples.\n\ -" -#endif +#ifdef NETWORK "-connect s Connect to server 's' for TCP/IP network play.\n\ -server Be a host/server for TCP/IP network play.\n\ --netport x Use TCP/IP port x for network play."; +-netport x Use TCP/IP port x for network play." +#endif +; #ifdef NETWORK static int docheckie[2]={0,0}; #endif ARGPSTRUCT DriverArgs[]={ - {"-joy1",0,&joy[0],0},{"-joy2",0,&joy[1],0}, - {"-joy3",0,&joy[2],0},{"-joy4",0,&joy[3],0}, - {"-xscale",0,&_xscale,0}, - {"-yscale",0,&_yscale,0}, - {"-efx",0,&_efx,0}, - {"-xscalefs",0,&_xscalefs,0}, - {"-yscalefs",0,&_yscalefs,0}, - {"-efxfs",0,&_efxfs,0}, - {"-xres",0,&_xres,0}, - {"-yres",0,&_yres,0}, - {"-fs",0,&_fullscreen,0}, - //{"-fshack",0,&_fshack,0x4001}, - {"-sound",0,&_sound,0}, - #ifdef DSPSOUND - {"-f8bit",0,&_f8bit,0}, - #else - {"-lbufsize",0,&_lbufsize,0}, - {"-ebufsize",0,&_ebufsize,0}, - #endif + {"-joy1",0,&Settings.joy[0],0},{"-joy2",0,&Settings.joy[1],0}, + {"-joy3",0,&Settings.joy[2],0},{"-joy4",0,&Settings.joy[3],0}, + {"-sound",0,&Settings.sound,0}, + {"-showfps",0,&Settings.showfps,0}, + {"-mmuhack",0,&Settings.mmuhack,0}, + {"-ramtimings",0,&Settings.ramtimings,0}, + {"-menu",0,&ext_menu,0x4001}, + {"-menustate",0,&ext_state,0x4001}, #ifdef NETWORK {"-connect",&docheckie[0],&netplayhost,0x4001}, {"-server",&docheckie[1],0,0}, @@ -104,56 +78,24 @@ ARGPSTRUCT DriverArgs[]={ - - void GetBaseDirectory(char *BaseDirectory) { - char *ol; - - ol="/mnt/sd/roms/nes"; - BaseDirectory[0]=0; - if(ol) - { - strncpy(BaseDirectory,ol,2047); - BaseDirectory[2047]=0; - strcat(BaseDirectory,"/fceultra"); - } + strcpy(BaseDirectory, "fceultra"); } static void SetDefaults(void) { - _xres=320; - _yres=240; - _fullscreen=0; - _sound=SOUND_RATE; // 48000 wrong - #ifdef DSPSOUND - _f8bit=0; - #else - _lbufsize=10; - _ebufsize=8; - #endif - _xscale=_yscale=_xscalefs=_yscalefs=1; - _efx=_efxfs=0; - //_fshack=_fshacksave=0; - memset(joy,0,sizeof(joy)); + memset(&Settings,0,sizeof(Settings)); + Settings.cpuclock = 150; + Settings.frameskip = -1; // auto + Settings.mmuhack = 1; + Settings.sound=SOUND_RATE; } void DoDriverArgs(void) { int x; - #ifdef BROKEN - if(_fshack) - { - if(_fshack[0]=='0') - if(_fshack[1]==0) - { - free(_fshack); - _fshack=0; - } - } - #endif - #ifdef NETWORK if(docheckie[0]) netplay=2; @@ -165,17 +107,20 @@ void DoDriverArgs(void) #endif for(x=0;x<4;x++) - if(!joy[x]) + if(!Settings.joy[x]) { - memset(joyBMap[x],0,sizeof(joyBMap[0])); - memset(joyAMap[x],0,sizeof(joyAMap[0])); + memset(Settings.joyBMap[x],0,sizeof(Settings.joyBMap[0])); + memset(Settings.joyAMap[x],0,sizeof(Settings.joyAMap[0])); } } + int InitMouse(void) { return(0); } + void KillMouse(void){} + void GetMouseData(uint32 *d) { } @@ -200,13 +145,14 @@ char *GetKeyboard(void) return NULL; } -#include "unix-basedir.h" -extern int showfps; -extern int swapbuttons; +extern int swapbuttons; // TODO: rm char **g_argv; + +// TODO: cleanup int main(int argc, char *argv[]) { + int ret; g_argv = argv; puts("Starting GPFCE - Port version " GP2X_PORT_VERSION " (" __DATE__ ")"); @@ -214,42 +160,42 @@ int main(int argc, char *argv[]) puts("Ported by Zheng Zhu"); puts("Additional optimization/misc work by notaz\n"); - // stereo - //gp2x_init (1000, 8, SOUND_RATE, 16, 1, 60); - - // mono 44khz - //gp2x_init (1000, 8, SOUND_RATE<<1, 16, 0, 60); - // mono 22khz - gp2x_init (1000, 8, SOUND_RATE, 16, 0, 60); + gp2x_init(); + cpuctrl_init(); // unscale the screen, in case this is bad. - SetVideoScaling(320, 320, 240); + gp2x_video_changemode(8); + gp2x_video_RGB_setscaling(0, 320, 240); SetDefaults(); - int ret=CLImain(argc,argv); + + ret = CLImain(argc,argv); // unscale the screen, in case this is bad. - SetVideoScaling(320, 320, 240); + gp2x_video_RGB_setscaling(0, 320, 240); + cpuctrl_deinit(); gp2x_deinit(); - // make sure sound thread has exited cleanly - printf("Exiting main(). terminated"); - if (showfps && swapbuttons) - { - execl("./selector","./selector","./gpfce_showfps_swapbuttons_config",NULL); - } - else if (showfps) - { - execl("./selector","./selector","./gpfce_showfps_config",NULL); - } - else if (swapbuttons) - { - execl("./selector","./selector","./gpfce_swapbuttons_config",NULL); - } - else - { - execl("./selector","./selector","./gpfce_config",NULL); - } + return(ret?0:-1); } + +int mmuhack_status = 0; + +/* optional GP2X stuff to be done after config is loaded */ +void gp2x_opt_setup(void) +{ + if (Settings.mmuhack) { + int ret = mmuhack(); + printf("squidge hack code finished and returned %i\n", ret); fflush(stdout); + mmuhack_status = ret; + } + if (Settings.ramtimings) { + printf("setting RAM timings.. "); fflush(stdout); + // craigix: --trc 6 --tras 4 --twr 1 --tmrd 1 --trfc 1 --trp 2 --trcd 2 + set_RAM_Timings(6, 4, 1, 1, 1, 2, 2); + printf("done.\n"); fflush(stdout); + } +} + diff --git a/drivers/gp2x/gp2x.h b/drivers/gp2x/gp2x.h index 7882e5b..799e0cb 100644 --- a/drivers/gp2x/gp2x.h +++ b/drivers/gp2x/gp2x.h @@ -1,46 +1,20 @@ -#include "../../driver.h" -#include "../common/args.h" -#include "../common/config.h" -#include "main.h" - typedef struct { - int xres; - int yres; - int xscale,yscale; - int xscalefs,yscalefs; - int efx,efxfs; - int fullscreen; int sound; - #ifdef DSPSOUND - int f8bit; - #else - int lbufsize,ebufsize; - #endif int joy[4]; int joyAMap[4][2]; int joyBMap[4][4]; - char *fshack; - char *fshacksave; + // gp2x specific + int showfps; + int scaling; // unscaled=0, hw_hor, hw_hor_vert, sw_hor + int frameskip; // -1 ~ auto, >=0 ~ count + int sstate_confirm; + int region_force; // 0 ~ off, 1 ~ PAL, 2 ~ NTSC + int cpuclock; + int mmuhack; + int ramtimings; } DSETTINGS; extern DSETTINGS Settings; -#define _xres Settings.xres -#define _yres Settings.yres -#define _fullscreen Settings.fullscreen -#define _sound Settings.sound -#define _f8bit Settings.f8bit -#define _xscale Settings.xscale -#define _yscale Settings.yscale -#define _xscalefs Settings.xscalefs -#define _yscalefs Settings.yscalefs -#define _efx Settings.efx -#define _efxfs Settings.efxfs -#define _ebufsize Settings.ebufsize -#define _lbufsize Settings.lbufsize -#define _fshack Settings.fshack -#define _fshacksave Settings.fshacksave +void gp2x_opt_setup(void); -#define joyAMap Settings.joyAMap -#define joyBMap Settings.joyBMap -#define joy Settings.joy diff --git a/drivers/gp2x/input.c b/drivers/gp2x/input.c index 9ba438a..cd25e97 100644 --- a/drivers/gp2x/input.c +++ b/drivers/gp2x/input.c @@ -29,13 +29,12 @@ #include "minimal.h" +extern uint8 Exit; // exit emu loop extern int swapbuttons; extern int scaled_display; extern int FSkip_setting; -extern void SetVideoScaling(int pixels,int width,int height); - /* UsrInputType[] is user-specified. InputType[] is current @@ -99,7 +98,7 @@ static void setsoundvol(int soundvolume) void FCEUD_UpdateInput(void) { long lastpad2=lastpad; - unsigned long pad=gp2x_joystick_read(); + unsigned long pad=gp2x_joystick_read(1); // TODO: USB joys and stuff uint32 JS=0; #define down(b) (pad & GP2X_##b) @@ -132,6 +131,10 @@ void FCEUD_UpdateInput(void) //FCEUI_SetSoundVolume(soundvol); setsoundvol(soundvol); } + else if (down(VOL_DOWN) && down(VOL_UP)) + { + Exit = 1; + } if (shift) { @@ -149,11 +152,11 @@ void FCEUD_UpdateInput(void) if (scaled_display) { - SetVideoScaling(320, 256, 240); + gp2x_video_RGB_setscaling(0, 256, 240); } else { - SetVideoScaling(320, 320, 240); + gp2x_video_RGB_setscaling(0, 320, 240); } goto no_pad; diff --git a/drivers/gp2x/main.c b/drivers/gp2x/main.c index 4437dc6..e9223f2 100644 --- a/drivers/gp2x/main.c +++ b/drivers/gp2x/main.c @@ -37,6 +37,8 @@ #include "main.h" #include "throttle.h" +#include "menu.h" +#include "gp2x.h" #include "../common/config.h" #include "../common/args.h" @@ -49,6 +51,12 @@ #include "../../fce.h" #include "../../ines.h" +// internals +extern char lastLoadedGameName[2048]; +extern uint8 Exit; // exit emu loop flag +void CloseGame(void); + +FCEUGI *fceugi = NULL; static int ntsccol=0,ntschue=-1,ntsctint=-1; int soundvol=70; int inited=0; @@ -56,9 +64,7 @@ int swapbuttons=0; int showfps=0; int srendlinev[2]={0,0}; -//int srendlinev[2]={0,0}; int erendlinev[2]={239,239}; -//int erendlinev[2]={231,239}; int srendline,erendline; @@ -123,6 +129,7 @@ static CFGSTRUCT fceuconfig[]={ AC(eoptions), ACA(srendlinev), ACA(erendlinev), + ACA(lastLoadedGameName), ADDCFGSTRUCT(DriverConfig), ENDCFGSTRUCT }; @@ -193,7 +200,7 @@ static void CloseStuff(int signum) exit(1); } -static void DoArgs(int argc, char *argv[]) +static int DoArgs(int argc, char *argv[]) { static char *cortab[5]={"none","gamepad","zapper","powerpad","arkanoid"}; static int cortabi[5]={SI_NONE,SI_GAMEPAD, @@ -202,7 +209,7 @@ static void DoArgs(int argc, char *argv[]) static int fccortabi[5]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW, SIFC_4PLAYER,SIFC_FKB}; - int x; + int x, ret; static char *inputa[2]={0,0}; static char *fcexp=0; static int docheckie[4]; @@ -232,7 +239,7 @@ static void DoArgs(int argc, char *argv[]) }; memset(docheckie,0,sizeof(docheckie)); - ParseArguments(argc, argv, FCEUArgs); + ret=ParseArguments(argc, argv, FCEUArgs); if(cpalette) { if(cpalette[0]=='0') @@ -299,62 +306,97 @@ static void DoArgs(int argc, char *argv[]) } } } + return ret; } #include "usage.h" int CLImain(int argc, char *argv[]) { - FCEUGI *tmp; - int ret; - - if(argc<=1) + int last_arg_parsed; + /* TODO if(argc<=1) { ShowUsage(argv[0]); return 1; - } + }*/ if(!DriverInitialize()) { return 1; } - if(!(ret=FCEUI_Initialize())) + if(!FCEUI_Initialize()) return(1); GetBaseDirectory(BaseDirectory); FCEUI_SetBaseDirectory(BaseDirectory); + lastLoadedGameName[0] = 0; CreateDirs(); LoadConfig(); - DoArgs(argc-2,&argv[1]); + gp2x_opt_setup(); + last_arg_parsed=DoArgs(argc-1,&argv[1]); if(cpalette) LoadCPalette(); if(InitSound()) inited|=1; - if(!(tmp=FCEUI_LoadGame(argv[argc-1]))) - { - ret=0; - goto dk; - } - ParseGI(tmp); - //RefreshThrottleFPS(); - InitOtherInput(); - - // additional print for gpfce + if (argc > 1 && !last_arg_parsed) { - int MapperNo; - iNES_HEADER *head = iNESGetHead(); - MapperNo = (head->ROM_type>>4); - MapperNo|=(head->ROM_type2&0xF0); - FCEU_DispMessage("%s, Mapper: %d%s%s", PAL?"PAL":"NTSC", MapperNo, (head->ROM_type&2)?", BB":"", (head->ROM_type&4)?", T":""); + strncpy(lastLoadedGameName, argv[argc-1], sizeof(lastLoadedGameName)); + lastLoadedGameName[sizeof(lastLoadedGameName)-1] = 0; + Exit = 0; + } + else + { + lastLoadedGameName[0] = 0; + Exit = 1; } - FCEUI_Emulate(); + while (1) + { + if(!Exit) + { + if (fceugi) + CloseGame(); + fceugi=FCEUI_LoadGame(lastLoadedGameName); + if (fceugi) + { + ParseGI(fceugi); + //RefreshThrottleFPS(); + InitOtherInput(); + + // additional print for gpfce + // TODO: handlers for other formats then iNES + { + int MapperNo; + iNES_HEADER *head = iNESGetHead(); + MapperNo = (head->ROM_type>>4); + MapperNo|=(head->ROM_type2&0xF0); + FCEU_DispMessage("%s, Mapper: %d%s%s", PAL?"PAL":"NTSC", MapperNo, (head->ROM_type&2)?", BB":"", (head->ROM_type&4)?", T":""); + } + } + else + strcpy(menuErrorMsg, "failed to load ROM"); + } + if(Exit || !fceugi) + { + int ret; + ret = gp2x_menu_do(); + if (ret == 1) break; // exit emu + if (ret == 2) { // reload ROM + Exit = 0; + continue; + } + } + + gp2x_video_changemode(Settings.scaling == 3 ? 15 : 8); + gp2x_video_RGB_setscaling(0, 320, 240); + gp2x_start_sound(22050, 16, 0); + FCEUI_Emulate(); + } - dk: DriverKill(); - return(ret?0:1); + return 0; } static int DriverInitialize(void) diff --git a/drivers/gp2x/main.h b/drivers/gp2x/main.h index 99dc5b5..b544bd6 100644 --- a/drivers/gp2x/main.h +++ b/drivers/gp2x/main.h @@ -28,3 +28,5 @@ extern int eoptions; #define EO_NOTHROTTLE 64 extern int srendline,erendline,srendlinev[2],erendlinev[2]; extern int NoWaiting; + +extern FCEUGI *fceugi; diff --git a/drivers/gp2x/menu.c b/drivers/gp2x/menu.c new file mode 100644 index 0000000..bafabf3 --- /dev/null +++ b/drivers/gp2x/menu.c @@ -0,0 +1,1091 @@ +// (c) Copyright 2006,2007 notaz, All rights reserved. +// Free for non-commercial use. + +// For commercial use, separate licencing terms must be obtained. + +#include +#include +#include +#include +#include +#include + +#include "minimal.h" +#include "usbjoy.h" +#include "asmutils.h" +#include "menu.h" +#include "main.h" +#include "fonts.h" +#include "gp2x.h" + +#ifndef _DIRENT_HAVE_D_TYPE +#error "need d_type for file browser +#endif + +extern char lastLoadedGameName[PATH_MAX]; +extern int mmuhack_status; +//extern int state_slot; // TODO +extern uint8 Exit; // exit emu loop flag + +static char *gp2xKeyNames[] = { + "UP", "01???", "LEFT", "03???", "DOWN", "05???", "RIGHT", "07???", + "START", "SELECT", "L", "R", "A", "B", "X", "Y", + "10???", "11???", "12???","13???", "14???","15???", "VOL DOWN", "VOL UP", + "18???", "19???", "1a???","PUSH", "1c???","1d???", "1e???", "1f???" +}; + +char menuErrorMsg[40] = {0, }; + +// TODO +void gp2x_fceu_copy_bg(void) +{ + memset(gp2x_screen, 0, 320*240*2); +} + +// draws white text to current bbp15 screen +static void gp2x_text_out15_(int x, int y, const char *text) +{ + int i,l; + unsigned short *screen = gp2x_screen; + + screen = screen + x + y*320; + + for (i = 0; i < strlen(text); i++) + { + for (l=0;l<8;l++) + { + if(fontdata8x8[((text[i])*8)+l]&0x80) screen[l*320+0]=0xffff; + if(fontdata8x8[((text[i])*8)+l]&0x40) screen[l*320+1]=0xffff; + if(fontdata8x8[((text[i])*8)+l]&0x20) screen[l*320+2]=0xffff; + if(fontdata8x8[((text[i])*8)+l]&0x10) screen[l*320+3]=0xffff; + if(fontdata8x8[((text[i])*8)+l]&0x08) screen[l*320+4]=0xffff; + if(fontdata8x8[((text[i])*8)+l]&0x04) screen[l*320+5]=0xffff; + if(fontdata8x8[((text[i])*8)+l]&0x02) screen[l*320+6]=0xffff; + if(fontdata8x8[((text[i])*8)+l]&0x01) screen[l*320+7]=0xffff; + } + screen += 8; + } +} + +void gp2x_text_out15(int x, int y, const char *texto, ...) +{ + va_list args; + char buffer[512]; + + va_start(args,texto); + vsprintf(buffer,texto,args); + va_end(args); + + gp2x_text_out15_(x,y,buffer); +} + + +void gp2x_text_out15_lim(int x, int y, const char *texto, int max) +{ + char buffer[320/8+1]; + + strncpy(buffer, texto, 320/8); + if (max > 320/8) max = 320/8; + if (max < 0) max = 0; + buffer[max] = 0; + + gp2x_text_out15(x,y,buffer); +} + +static void gp2x_smalltext16(int x, int y, const char *texto) +{ + int i; + unsigned char *src; + unsigned short *dst; + + for (i = 0;; i++, x += 6) + { + unsigned char c = (unsigned char) texto[i]; + int h = 8; + + if (!c) break; + + src = fontdata6x8[c]; + dst = (unsigned short *)gp2x_screen + x + y*320; + + while (h--) + { + int w = 0x20; + while (w) + { + if( *src & w ) *dst = 0xffff; + dst++; + w>>=1; + } + src++; + + dst += 320-6; + } + } +} + +static void gp2x_smalltext8_lim(int x, int y, const char *texto, int max) +{ + char buffer[320/6+1]; + + strncpy(buffer, texto, 320/6); + if (max > 320/6) max = 320/6; + if (max < 0) max = 0; + buffer[max] = 0; + + gp2x_smalltext16(x, y, buffer); +} + + +static unsigned long inp_prev = 0; +static int inp_prevjoy = 0; + +static unsigned long wait_for_input(unsigned long interesting) +{ + unsigned long ret; + static int repeats = 0, wait = 50*1000; + int release = 0, i; + + if (repeats == 2 || repeats == 4) wait /= 2; + if (repeats == 6) wait = 15 * 1000; + + for (i = 0; i < 6 && inp_prev == gp2x_joystick_read(1); i++) { + if (i == 0) repeats++; + if (wait >= 30*1000) usleep(wait); // usleep sleeps for ~30ms minimum + else spend_cycles(wait * Settings.cpuclock); + } + + while ( !((ret = gp2x_joystick_read(1)) & interesting) ) { + usleep(50000); + release = 1; + } + + if (release || ret != inp_prev) { + repeats = 0; + wait = 50*1000; + } + inp_prev = ret; + inp_prevjoy = 0; + + // we don't need diagonals in menus + if ((ret&GP2X_UP) && (ret&GP2X_LEFT)) ret &= ~GP2X_LEFT; + if ((ret&GP2X_UP) && (ret&GP2X_RIGHT)) ret &= ~GP2X_RIGHT; + if ((ret&GP2X_DOWN) && (ret&GP2X_LEFT)) ret &= ~GP2X_LEFT; + if ((ret&GP2X_DOWN) && (ret&GP2X_RIGHT)) ret &= ~GP2X_RIGHT; + + return ret; +} + +static unsigned long input2_read(unsigned long interesting, int *joy) +{ + unsigned long ret; + int i; + + do + { + *joy = 0; + if ((ret = gp2x_joystick_read(0) & interesting)) break; + gp2x_usbjoy_update(); + for (i = 0; i < num_of_joys; i++) { + ret = gp2x_usbjoy_check2(i); + if (ret) { *joy = i + 1; break; } + } + if (ret) break; + } + while(0); + + return ret; +} + +// similar to wait_for_input(), but returns joy num +static unsigned long wait_for_input_usbjoy(unsigned long interesting, int *joy) +{ + unsigned long ret; + const int wait = 300*1000; + int i; + + if (inp_prevjoy == 0) inp_prev &= interesting; + for (i = 0; i < 6; i++) { + ret = input2_read(interesting, joy); + if (*joy != inp_prevjoy || ret != inp_prev) break; + usleep(wait/6); + } + + while ( !(ret = input2_read(interesting, joy)) ) { + usleep(50000); + } + + inp_prev = ret; + inp_prevjoy = *joy; + + return ret; +} + + + +// -------------- ROM selector -------------- + +static void draw_dirlist(char *curdir, struct dirent **namelist, int n, int sel) +{ + int start, i, pos; + + start = 12 - sel; + n--; // exclude current dir (".") + + //memset(gp2x_screen, 0, 320*240); + gp2x_fceu_copy_bg(); + + if(start - 2 >= 0) + gp2x_smalltext8_lim(14, (start - 2)*10, curdir, 53-2); + for (i = 0; i < n; i++) { + pos = start + i; + if (pos < 0) continue; + if (pos > 23) break; + if (namelist[i+1]->d_type == DT_DIR) { + gp2x_smalltext8_lim(14, pos*10, "/", 1); + gp2x_smalltext8_lim(14+6, pos*10, namelist[i+1]->d_name, 53-3); + } else { + gp2x_smalltext8_lim(14, pos*10, namelist[i+1]->d_name, 53-2); + } + } + gp2x_text_out15(5, 120, ">"); + gp2x_video_flip(); +} + +static int scandir_cmp(const void *p1, const void *p2) +{ + struct dirent **d1 = (struct dirent **)p1, **d2 = (struct dirent **)p2; + if ((*d1)->d_type == (*d2)->d_type) return alphasort(d1, d2); + if ((*d1)->d_type == DT_DIR) return -1; // put before + if ((*d2)->d_type == DT_DIR) return 1; + return alphasort(d1, d2); +} + +static char *filter_exts[] = { + // TODO + ".mp3", ".MP3", ".srm", ".brm", "s.gz", ".mds", "bcfg", ".txt", ".htm", "html", + ".jpg", ".gpe", ".cue" +}; + +static int scandir_filter(const struct dirent *ent) +{ + const char *p; + int i; + + if (ent == NULL || ent->d_name == NULL) return 0; + if (strlen(ent->d_name) < 5) return 1; + + p = ent->d_name + strlen(ent->d_name) - 4; + + for (i = 0; i < sizeof(filter_exts)/sizeof(filter_exts[0]); i++) + { + if (strcmp(p, filter_exts[i]) == 0) return 0; + } + + return 1; +} + +static char *romsel_loop(char *curr_path) +{ + struct dirent **namelist; + DIR *dir; + int n, sel = 0; + unsigned long inp = 0; + char *ret = NULL, *fname = NULL; + + // is this a dir or a full path? + if ((dir = opendir(curr_path))) { + closedir(dir); + } else { + char *p; + for (p = curr_path + strlen(curr_path) - 1; p > curr_path && *p != '/'; p--); + *p = 0; + fname = p+1; + } + + n = scandir(curr_path, &namelist, scandir_filter, scandir_cmp); + if (n < 0) { + // try root + n = scandir("/", &namelist, scandir_filter, scandir_cmp); + if (n < 0) { + // oops, we failed + printf("dir: %s\n", curr_path); + perror("scandir"); + return NULL; + } + } + + // try to find sel + if (fname != NULL) { + int i; + for (i = 1; i < n; i++) { + if (strcmp(namelist[i]->d_name, fname) == 0) { + sel = i - 1; + break; + } + } + } + + for (;;) + { + draw_dirlist(curr_path, namelist, n, sel); + inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT|GP2X_L|GP2X_R|GP2X_B|GP2X_X); + if(inp & GP2X_UP ) { sel--; if (sel < 0) sel = n-2; } + if(inp & GP2X_DOWN) { sel++; if (sel > n-2) sel = 0; } + if(inp & GP2X_LEFT) { sel-=10; if (sel < 0) sel = 0; } + if(inp & GP2X_L) { sel-=24; if (sel < 0) sel = 0; } + if(inp & GP2X_RIGHT) { sel+=10; if (sel > n-2) sel = n-2; } + if(inp & GP2X_R) { sel+=24; if (sel > n-2) sel = n-2; } + if(inp & GP2X_B) { // enter dir/select + again: + if (namelist[sel+1]->d_type == DT_REG) { + strcpy(lastLoadedGameName, curr_path); + strcat(lastLoadedGameName, "/"); + strcat(lastLoadedGameName, namelist[sel+1]->d_name); + ret = lastLoadedGameName; + break; + } else if (namelist[sel+1]->d_type == DT_DIR) { + int newlen = strlen(curr_path) + strlen(namelist[sel+1]->d_name) + 2; + char *p, *newdir = malloc(newlen); + if (strcmp(namelist[sel+1]->d_name, "..") == 0) { + char *start = curr_path; + p = start + strlen(start) - 1; + while (*p == '/' && p > start) p--; + while (*p != '/' && p > start) p--; + if (p <= start) strcpy(newdir, "/"); + else { strncpy(newdir, start, p-start); newdir[p-start] = 0; } + } else { + strcpy(newdir, curr_path); + p = newdir + strlen(newdir) - 1; + while (*p == '/' && p >= newdir) *p-- = 0; + strcat(newdir, "/"); + strcat(newdir, namelist[sel+1]->d_name); + } + ret = romsel_loop(newdir); + free(newdir); + break; + } else { + // unknown file type, happens on NTFS mounts. Try to guess. + FILE *tstf; int tmp; + strcpy(lastLoadedGameName, curr_path); + strcat(lastLoadedGameName, "/"); + strcat(lastLoadedGameName, namelist[sel+1]->d_name); + tstf = fopen(lastLoadedGameName, "rb"); + if (tstf != NULL) + { + if (fread(&tmp, 1, 1, tstf) > 0 || ferror(tstf) == 0) + namelist[sel+1]->d_type = DT_REG; + else namelist[sel+1]->d_type = DT_DIR; + fclose(tstf); + goto again; + } + } + } + if(inp & GP2X_X) break; // cancel + } + + if (n > 0) { + while(n--) free(namelist[n]); + free(namelist); + } + + return ret; +} + +// ------------ patch/gg menu ------------ + +#if 0 // TODO? +static void draw_patchlist(int sel) +{ + int start, i, pos; + + start = 12 - sel; + + gp2x_fceu_copy_bg(); + + for (i = 0; i < PicoPatchCount; i++) { + pos = start + i; + if (pos < 0) continue; + if (pos > 23) break; + gp2x_smalltext8_lim(14, pos*10, PicoPatches[i].active ? "ON " : "OFF", 3); + gp2x_smalltext8_lim(14+6*4, pos*10, PicoPatches[i].name, 53-6); + } + pos = start + i; + if (pos < 24) gp2x_smalltext8_lim(14, pos*10, "done", 4); + + gp2x_text_out15(5, 120, ">"); + gp2x_video_flip(); +} + + +void patches_menu_loop(void) +{ + int menu_sel = 0; + unsigned long inp = 0; + + for(;;) + { + draw_patchlist(menu_sel); + inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT|GP2X_L|GP2X_R|GP2X_B|GP2X_X); + if(inp & GP2X_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = PicoPatchCount; } + if(inp & GP2X_DOWN) { menu_sel++; if (menu_sel > PicoPatchCount) menu_sel = 0; } + if(inp &(GP2X_LEFT|GP2X_L)) { menu_sel-=10; if (menu_sel < 0) menu_sel = 0; } + if(inp &(GP2X_RIGHT|GP2X_R)) { menu_sel+=10; if (menu_sel > PicoPatchCount) menu_sel = PicoPatchCount; } + if(inp & GP2X_B) { // action + if (menu_sel < PicoPatchCount) + PicoPatches[menu_sel].active = !PicoPatches[menu_sel].active; + else return; + } + if(inp & GP2X_X) return; + } + +} + +// ------------ savestate loader ------------ + +static void menu_prepare_bg(void); + +static int state_slot_flags = 0; + +static void state_check_slots(void) +{ + int slot; + + state_slot_flags = 0; + + for (slot = 0; slot < 10; slot++) + { + if (emu_check_save_file(slot)) + { + state_slot_flags |= 1 << slot; + } + } +} + +static void draw_savestate_bg(int slot) +{ + struct PicoVideo tmp_pv; + unsigned short tmp_cram[0x40]; + unsigned short tmp_vsram[0x40]; + void *tmp_vram, *file; + char *fname; + + fname = emu_GetSaveFName(1, 0, slot); + if (!fname) return; + + tmp_vram = malloc(sizeof(Pico.vram)); + if (tmp_vram == NULL) return; + + memcpy(tmp_vram, Pico.vram, sizeof(Pico.vram)); + memcpy(tmp_cram, Pico.cram, sizeof(Pico.cram)); + memcpy(tmp_vsram, Pico.vsram, sizeof(Pico.vsram)); + memcpy(&tmp_pv, &Pico.video, sizeof(Pico.video)); + + if (strcmp(fname + strlen(fname) - 3, ".gz") == 0) { + file = gzopen(fname, "rb"); + emu_set_save_cbs(1); + } else { + file = fopen(fname, "rb"); + emu_set_save_cbs(0); + } + + if (file) { + if (PicoMCD & 1) { + PicoCdLoadStateGfx(file); + } else { + areaSeek(file, 0x10020, SEEK_SET); // skip header and RAM in state file + areaRead(Pico.vram, 1, sizeof(Pico.vram), file); + areaSeek(file, 0x2000, SEEK_CUR); + areaRead(Pico.cram, 1, sizeof(Pico.cram), file); + areaRead(Pico.vsram, 1, sizeof(Pico.vsram), file); + areaSeek(file, 0x221a0, SEEK_SET); + areaRead(&Pico.video, 1, sizeof(Pico.video), file); + } + areaClose(file); + } + + emu_forced_frame(); + gp2x_memcpy_buffers((1<<2), gp2x_screen, 0, 320*240*2); + menu_prepare_bg(); + + memcpy(Pico.vram, tmp_vram, sizeof(Pico.vram)); + memcpy(Pico.cram, tmp_cram, sizeof(Pico.cram)); + memcpy(Pico.vsram, tmp_vsram, sizeof(Pico.vsram)); + memcpy(&Pico.video, &tmp_pv, sizeof(Pico.video)); + free(tmp_vram); +} + +static void draw_savestate_menu(int menu_sel, int is_loading) +{ + int tl_x = 25, tl_y = 60, y, i; + + if (state_slot_flags & (1 << menu_sel)) + draw_savestate_bg(menu_sel); + gp2x_fceu_copy_bg(); + + gp2x_text_out15(tl_x, 30, is_loading ? "Load state" : "Save state"); + + /* draw all 10 slots */ + y = tl_y; + for (i = 0; i < 10; i++, y+=10) + { + gp2x_text_out15(tl_x, y, "SLOT %i (%s)", i, (state_slot_flags & (1 << i)) ? "USED" : "free"); + } + gp2x_text_out15(tl_x, y, "back"); + + // draw cursor + gp2x_text_out15(tl_x - 16, tl_y + menu_sel*10, ">"); + + gp2x_video_flip(); +} + +static int savestate_menu_loop(int is_loading) +{ + int menu_sel = 10, menu_sel_max = 10; + unsigned long inp = 0; + + state_check_slots(); + + for(;;) + { + draw_savestate_menu(menu_sel, is_loading); + inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_B|GP2X_X); + if(inp & GP2X_UP ) { + do { + menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; + } while (!(state_slot_flags & (1 << menu_sel)) && menu_sel != menu_sel_max && is_loading); + } + if(inp & GP2X_DOWN) { + do { + menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; + } while (!(state_slot_flags & (1 << menu_sel)) && menu_sel != menu_sel_max && is_loading); + } + if(inp & GP2X_B) { // save/load + if (menu_sel < 10) { + state_slot = menu_sel; + if (emu_SaveLoadGame(is_loading, 0)) { + strcpy(menuErrorMsg, is_loading ? "Load failed" : "Save failed"); + return 1; + } + return 0; + } else return 1; + } + if(inp & GP2X_X) return 1; + } +} + +// -------------- key config -------------- + +static char *usb_joy_key_name(int joy, int num) +{ + static char name[16]; + switch (num) + { + case 0: sprintf(name, "Joy%i UP", joy); break; + case 1: sprintf(name, "Joy%i DOWN", joy); break; + case 2: sprintf(name, "Joy%i LEFT", joy); break; + case 3: sprintf(name, "Joy%i RIGHT", joy); break; + default:sprintf(name, "Joy%i b%i", joy, num-3); break; + } + return name; +} + +static void draw_key_config(int curr_act, int is_p2) +{ + char strkeys[32*5]; + int joy, i; + + strkeys[0] = 0; + for (i = 0; i < 32; i++) + { + if (currentConfig.KeyBinds[i] & (1 << curr_act)) + { + if (curr_act < 16 && (currentConfig.KeyBinds[i] & (1 << 16)) != (is_p2 << 16)) continue; + if (strkeys[0]) { strcat(strkeys, " + "); strcat(strkeys, gp2xKeyNames[i]); break; } + else strcpy(strkeys, gp2xKeyNames[i]); + } + } + for (joy = 0; joy < num_of_joys; joy++) + { + for (i = 0; i < 32; i++) + { + if (currentConfig.JoyBinds[joy][i] & (1 << curr_act)) + { + if (curr_act < 16 && (currentConfig.JoyBinds[joy][i] & (1 << 16)) != (is_p2 << 16)) continue; + if (strkeys[0]) { + strcat(strkeys, ", "); strcat(strkeys, usb_joy_key_name(joy + 1, i)); + break; + } + else strcpy(strkeys, usb_joy_key_name(joy + 1, i)); + } + } + } + + //memset(gp2x_screen, 0, 320*240); + gp2x_fceu_copy_bg(); + gp2x_text_out15(60, 40, "Action: %s", actionNames[curr_act]); + gp2x_text_out15(60, 60, "Keys: %s", strkeys); + + gp2x_text_out15(30, 180, "Use SELECT to change action"); + gp2x_text_out15(30, 190, "Press a key to bind/unbind"); + gp2x_text_out15(30, 200, "Select \"Done\" action and"); + gp2x_text_out15(30, 210, " press any key to finish"); + gp2x_video_flip(); +} + +static void key_config_loop(int is_p2) +{ + int curr_act = 0, joy = 0, i; + unsigned long inp = 0; + + for (;;) + { + draw_key_config(curr_act, is_p2); + inp = wait_for_input_usbjoy(CONFIGURABLE_KEYS, &joy); + // printf("got %08lX from joy %i\n", inp, joy); + if (joy == 0) { + if (inp & GP2X_SELECT) { + curr_act++; + while (!actionNames[curr_act] && curr_act < 32) curr_act++; + if (curr_act > 31) curr_act = 0; + } + inp &= CONFIGURABLE_KEYS; + inp &= ~GP2X_SELECT; + } + if (curr_act == 31 && inp) break; + if (joy == 0) { + for (i = 0; i < 32; i++) + if (inp & (1 << i)) { + currentConfig.KeyBinds[i] ^= (1 << curr_act); + if (is_p2) currentConfig.KeyBinds[i] |= (1 << 16); // player 2 flag + else currentConfig.KeyBinds[i] &= ~(1 << 16); + } + } else { + for (i = 0; i < 32; i++) + if (inp & (1 << i)) { + currentConfig.JoyBinds[joy-1][i] ^= (1 << curr_act); + if (is_p2) currentConfig.JoyBinds[joy-1][i] |= (1 << 16); + else currentConfig.JoyBinds[joy-1][i] &= ~(1 << 16); + } + } + } +} + +static void draw_kc_sel(int menu_sel) +{ + int tl_x = 25+40, tl_y = 60, y, i; + char joyname[36]; + + y = tl_y; + //memset(gp2x_screen, 0, 320*240); + gp2x_fceu_copy_bg(); + gp2x_text_out15(tl_x, y, "Player 1"); + gp2x_text_out15(tl_x, (y+=10), "Player 2"); + gp2x_text_out15(tl_x, (y+=10), "Done"); + + // draw cursor + gp2x_text_out15(tl_x - 16, tl_y + menu_sel*10, ">"); + + tl_x = 25; + gp2x_text_out15(tl_x, (y=110), "USB joys detected:"); + if (num_of_joys > 0) { + for (i = 0; i < num_of_joys; i++) { + strncpy(joyname, joy_name(joys[i]), 33); joyname[33] = 0; + gp2x_text_out15(tl_x, (y+=10), "%i: %s", i+1, joyname); + } + } else { + gp2x_text_out15(tl_x, (y+=10), "none"); + } + + + gp2x_video_flip(); +} + +static void kc_sel_loop(void) +{ + int menu_sel = 2, menu_sel_max = 2; + unsigned long inp = 0; + + for(;;) + { + draw_kc_sel(menu_sel); + inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_B|GP2X_X); + if(inp & GP2X_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } + if(inp & GP2X_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } + if(inp & GP2X_B) { + switch (menu_sel) { + case 0: key_config_loop(0); return; + case 1: key_config_loop(1); return; + default: return; + } + } + if(inp & GP2X_X) return; + } +} +#endif + + + +// --------- advanced options ---------- +#if 0 +static void draw_amenu_options(int menu_sel) +{ + int tl_x = 25, tl_y = 60, y; + char *mms = mmuhack_status ? "active) " : "inactive)"; + + y = tl_y; + //memset(gp2x_screen, 0, 320*240); + gp2x_fceu_copy_bg(); + + gp2x_text_out15(tl_x, y, "Gamma correction %i.%02i", currentConfig.gamma / 100, currentConfig.gamma%100); // 0 + gp2x_text_out15(tl_x, (y+=10), "Don't save last used ROM %s", (currentConfig.EmuOpt &0x020)?"ON":"OFF"); // 5 + gp2x_text_out15(tl_x, (y+=10), "needs restart:"); + gp2x_text_out15(tl_x, (y+=10), "craigix's RAM timings %s", (currentConfig.EmuOpt &0x100)?"ON":"OFF"); // 7 + gp2x_text_out15(tl_x, (y+=10), "squidgehack (now %s %s", mms, (currentConfig.EmuOpt &0x010)?"ON":"OFF"); // 8 + gp2x_text_out15(tl_x, (y+=10), "Done"); + + // draw cursor + gp2x_text_out15(tl_x - 16, tl_y + menu_sel*10, ">"); + + gp2x_video_flip(); +} + +static void amenu_loop_options(void) +{ + int menu_sel = 0, menu_sel_max = 9; + unsigned long inp = 0; + + for(;;) + { + draw_amenu_options(menu_sel); + inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT|GP2X_B|GP2X_X|GP2X_A); + if(inp & GP2X_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } + if(inp & GP2X_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } + if((inp& GP2X_B)||(inp&GP2X_LEFT)||(inp&GP2X_RIGHT)) { // toggleable options + switch (menu_sel) { + case 1: break; + case 9: return; + } + } + if(inp & (GP2X_X|GP2X_A)) return; + if(inp & (GP2X_LEFT|GP2X_RIGHT)) { // multi choise + switch (menu_sel) { + case 0: + while ((inp = gp2x_joystick_read(1)) & (GP2X_LEFT|GP2X_RIGHT)) { + currentConfig.gamma += (inp & GP2X_LEFT) ? -1 : 1; + if (currentConfig.gamma < 1) currentConfig.gamma = 1; + if (currentConfig.gamma > 300) currentConfig.gamma = 300; + draw_amenu_options(menu_sel); + usleep(18*1000); + } + break; + } + } + } +} +#endif + +// -------------- options -------------- + +static void draw_menu_options(int menu_sel) +{ + int tl_x = 25, tl_y = 32, y; + char monostereo[8], strframeskip[8], *strscaling, *strssconfirm; + + //strcpy(monostereo, (currentConfig.PicoOpt&0x08)?"stereo":"mono"); + if (Settings.frameskip < 0) + strcpy(strframeskip, "Auto"); + else sprintf(strframeskip, "%i", Settings.frameskip); + switch (Settings.scaling) { + default: strscaling = " OFF"; break; + case 1: strscaling = "hw horizontal"; break; + case 2: strscaling = "hw horiz. + vert."; break; + case 3: strscaling = "sw horizontal"; break; + } + switch (Settings.sstate_confirm) { + default: strssconfirm = "OFF"; break; + case 1: strssconfirm = "writes"; break; + case 2: strssconfirm = "loads"; break; + case 3: strssconfirm = "both"; break; + } + + y = tl_y; + //memset(gp2x_screen, 0, 320*240); + gp2x_fceu_copy_bg(); + + gp2x_text_out15(tl_x, (y+=10), "Scaling: %s", strscaling); // 0 + gp2x_text_out15(tl_x, (y+=10), "Show FPS %s", Settings.showfps?"ON":"OFF"); // 1 + gp2x_text_out15(tl_x, (y+=10), "Frameskip %s", strframeskip); // 2 + gp2x_text_out15(tl_x, (y+=10), "Enable sound %s", /*(currentConfig.EmuOpt &0x004)?"ON":*/"OFF"); // 3 + gp2x_text_out15(tl_x, (y+=10), "Sound Quality: %5iHz %s", 0, "" /*currentConfig.PsndRate, monostereo*/); // 4 + gp2x_text_out15(tl_x, (y+=10), "Region: %s", + Settings.region_force == 2 ? "NTSC" : Settings.region_force == 1 ? "PAL" : "OFF"); // 5 + gp2x_text_out15(tl_x, (y+=10), "Use SRAM savestates %s", "OFF"); + gp2x_text_out15(tl_x, (y+=10), "Confirm savestate %s", strssconfirm); + gp2x_text_out15(tl_x, (y+=10), "Save slot %i", 0/*state_slot*/); // 8 + gp2x_text_out15(tl_x, (y+=10), "GP2X CPU clock %iMhz", Settings.cpuclock); + gp2x_text_out15(tl_x, (y+=10), "[advanced options]"); // 10 + gp2x_text_out15(tl_x, (y+=10), "Save cfg as default"); + if (fceugi) + gp2x_text_out15(tl_x, (y+=10), "Save cfg for current game only"); + + // draw cursor + gp2x_text_out15(tl_x - 16, tl_y + menu_sel*10, ">"); + + gp2x_video_flip(); +} + +/* +static int sndrate_prevnext(int rate, int dir) +{ + int i, rates[] = { 8000, 11025, 16000, 22050, 44100 }; + + for (i = 0; i < 5; i++) + if (rates[i] == rate) break; + + i += dir ? 1 : -1; + if (i > 4) return dir ? 44100 : 22050; + if (i < 0) return dir ? 11025 : 8000; + return rates[i]; +} +*/ +static void int_incdec(int *p, int inc, int min, int max) +{ + *p += inc; + if (*p < min) *p = min; + else if (*p > max) *p = max; +} + +static int menu_loop_options(void) +{ + int menu_sel = 0, menu_sel_max = 11; + unsigned long inp = 0; + + if (fceugi) menu_sel_max++; + + for(;;) + { + draw_menu_options(menu_sel); + inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT|GP2X_B|GP2X_X|GP2X_A); + if(inp & GP2X_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } + if(inp & GP2X_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } + if((inp& GP2X_B)||(inp&GP2X_LEFT)||(inp&GP2X_RIGHT)) { // toggleable options + switch (menu_sel) { + case 1: Settings.showfps = !Settings.showfps; break; + //case 6: Settings. = !Settings.showfps; break; + //case 16: amenu_loop_options(); break; + case 17: // done (update and write) + //if (emu_WriteConfig(0)) strcpy(menuErrorMsg, "config saved"); + //else strcpy(menuErrorMsg, "failed to write config"); + return 1; + case 18: // done (update and write for current game) + //if (emu_WriteConfig(1)) strcpy(menuErrorMsg, "config saved"); + //else strcpy(menuErrorMsg, "failed to write config"); + return 1; + } + } + if(inp & (GP2X_X|GP2X_A)) { + return 0; // done (update, no write) + } + if(inp & (GP2X_LEFT|GP2X_RIGHT)) { // multi choise + switch (menu_sel) { + case 0: int_incdec(&Settings.scaling, (inp & GP2X_LEFT) ? -1 : 1, 0, 3); break; + case 2: int_incdec(&Settings.frameskip, (inp & GP2X_LEFT) ? -1 : 1, -1, 32); break; +/* + case 4: + if ((inp & GP2X_RIGHT) && currentConfig.PsndRate == 44100 && !(currentConfig.PicoOpt&0x08)) { + currentConfig.PsndRate = 8000; currentConfig.PicoOpt|= 0x08; + } else if ((inp & GP2X_LEFT) && currentConfig.PsndRate == 8000 && (currentConfig.PicoOpt&0x08)) { + currentConfig.PsndRate = 44100; currentConfig.PicoOpt&=~0x08; + } else currentConfig.PsndRate = sndrate_prevnext(currentConfig.PsndRate, inp & GP2X_RIGHT); + break; +*/ + case 5: int_incdec(&Settings.region_force, (inp & GP2X_LEFT) ? -1 : 1, 0, 2); break; + case 7: int_incdec(&Settings.sstate_confirm, (inp & GP2X_LEFT) ? -1 : 1, 0, 3); break; + //case 8: int_incdec(&Settings., (inp & GP2X_LEFT) ? -1 : 1, 0, 9); break; + case 14: + while ((inp = gp2x_joystick_read(1)) & (GP2X_LEFT|GP2X_RIGHT)) { + Settings.cpuclock += (inp & GP2X_LEFT) ? -1 : 1; + if (Settings.cpuclock < 1) Settings.cpuclock = 1; + draw_menu_options(menu_sel); + usleep(50*1000); + } + break; + } + } + } +} + +// -------------- credits -------------- + +static void draw_menu_credits(void) +{ + int tl_x = 15, tl_y = 70, y; + //memset(gp2x_screen, 0, 320*240); + gp2x_fceu_copy_bg(); + + // TODO + + gp2x_video_flip(); +} + + +// -------------- root menu -------------- + +static void draw_menu_root(int menu_sel) +{ + int tl_x = 70, tl_y = 70, y; + gp2x_fceu_copy_bg(); + + y = tl_y; + if (fceugi) { + gp2x_text_out15(tl_x, y, "Resume game"); + gp2x_text_out15(tl_x, (y+=10), "Save State"); + gp2x_text_out15(tl_x, (y+=10), "Load State"); + gp2x_text_out15(tl_x, (y+=10), "Reset game"); + } else { + y += 30; + } + gp2x_text_out15(tl_x, (y+=10), "Load new ROM"); + gp2x_text_out15(tl_x, (y+=10), "Change options"); + gp2x_text_out15(tl_x, (y+=10), "Configure controls"); + gp2x_text_out15(tl_x, (y+=10), "Credits"); + gp2x_text_out15(tl_x, (y+=10), "Exit"); +// TODO +// if (PicoPatches) +// gp2x_text_out15(tl_x, (y+=10), "Patches / GameGenie"); + + // draw cursor + gp2x_text_out15(tl_x - 16, tl_y + menu_sel*10, ">"); + // error + if (menuErrorMsg[0]) gp2x_text_out15(5, 226, menuErrorMsg); + gp2x_video_flip(); +} + + +static int menu_loop_root(void) +{ + int ret, menu_sel = 4, menu_sel_max = 8, menu_sel_min = 4; + unsigned long inp = 0; + char curr_path[PATH_MAX], *selfname; + FILE *tstf; + + if ( (tstf = fopen(lastLoadedGameName, "rb")) ) + { + fclose(tstf); + strncpy(curr_path, lastLoadedGameName, sizeof(curr_path)); + curr_path[sizeof(curr_path)-1] = 0; + } + else + { + getcwd(curr_path, PATH_MAX); + } + + if (fceugi) menu_sel = menu_sel_min = 0; +// TODO if (PicoPatches) menu_sel_max = 9; + + /* make sure action buttons are not pressed on entering menu */ + draw_menu_root(menu_sel); + while (gp2x_joystick_read(1) & (GP2X_B|GP2X_X|GP2X_SELECT)) usleep(50*1000); + + for (;;) + { + draw_menu_root(menu_sel); + inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_B|GP2X_X); + if(inp & GP2X_UP ) { menu_sel--; if (menu_sel < menu_sel_min) menu_sel = menu_sel_max; } + if(inp & GP2X_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = menu_sel_min; } + if(inp &(GP2X_SELECT|GP2X_X)){ + if (fceugi) { + while (gp2x_joystick_read(1) & GP2X_X) usleep(50*1000); // wait until X is released + Exit = 0; + return 0; + } + } + if(inp & GP2X_B ) { + switch (menu_sel) { + case 0: // resume game + if (fceugi) { + while (gp2x_joystick_read(1) & GP2X_B) usleep(50*1000); + Exit = 0; + return 0; + } + break; + case 1: // save state + if (fceugi) { + /*if(savestate_menu_loop(0)) + continue;*/ + return 0; + } + break; + case 2: // load state + if (fceugi) { + /*if(savestate_menu_loop(1)) + continue;*/ + return 0; + } + break; + case 3: // reset game + if (fceugi) { + return 0; + } + break; + case 4: // select rom + selfname = romsel_loop(curr_path); + if (selfname) { + printf("selected file: %s\n", selfname); + return 2; + } + break; + case 5: // options + ret = menu_loop_options(); + if (ret == 1) continue; // status update + break; + case 6: // controls + // TODO kc_sel_loop(); + break; + case 7: // credits + draw_menu_credits(); + usleep(500*1000); + inp = wait_for_input(GP2X_B|GP2X_X); + break; + case 8: // exit + return 1; + case 9: // patches/gg + break; + } + } + menuErrorMsg[0] = 0; // clear error msg + } +} + + +static void menu_prepare_bg(void) +{ + // TODO... +} + +static void menu_gfx_prepare(void) +{ + menu_prepare_bg(); + + // switch bpp + gp2x_video_changemode(16); + gp2x_video_RGB_setscaling(0, 320, 240); + gp2x_video_flip(); +} + + +int gp2x_menu_do(void) +{ + int ret; + + menu_gfx_prepare(); + + ret = menu_loop_root(); + + menuErrorMsg[0] = 0; + + return ret; +} + + diff --git a/drivers/gp2x/menu.h b/drivers/gp2x/menu.h new file mode 100644 index 0000000..f673197 --- /dev/null +++ b/drivers/gp2x/menu.h @@ -0,0 +1,5 @@ + +extern char menuErrorMsg[40]; + +int gp2x_menu_do(void); + diff --git a/drivers/gp2x/minimal.c b/drivers/gp2x/minimal.c index 0250587..ba4ffe0 100644 --- a/drivers/gp2x/minimal.c +++ b/drivers/gp2x/minimal.c @@ -1,508 +1,349 @@ -/* - GP2X minimal library v0.A by rlyeh, 2005. emulnation.info@rlyeh (swap it!) - - + GP2X 920t/940t CPUs library with a FIFO message system. - + GP2X video library with double buffering. - + GP2X sound library with double buffering. - + GP2X blitter library. - + GP2X timer library. - + GP2X joystick library. - - Thanks to Squidge, Robster, snaff, Reesy and NK, for the help & previous work! :-) - - - License - ======= - - Free for non-commercial projects (it would be nice receiving a mail from you). - Other cases, ask me first. - - GamePark Holdings is not allowed to use this library and/or use parts from it. - - - Known projects using the library or parts from it - ================================================= - - REminiscence-0.1.8 (rlyeh) - Atari800 GP2X pre-release 3 (foft) - XUMP (kedo) - MAME2X (Franxis) - DrMD for GP2X (Reesy) - - - What's new - ========== - - 0.A: 940t disabled all time unless required - sound is paused by default now, use gp2x_sound_pause() to unlock it - - fixed functions: - - gp2x_sound_play() ; increased the number of sampling buffers - - gp2x_timer_read() ; it should work again. broken at some point before - - gp2x_dualcore_launch_program_from_disk() ; it missed the code uploading call - - added functions: - - gp2x_sound_pause() - - gp2x_timer_delay() - - gp2x_dualcore_pause() - - 0.9: initial FIFO message system for dual cpu cores. - initial 48 Mb support. - initial quadruple buffering in 8bbp mode. - - added functions: - - gp2x_dualcore_exec() ; initial FIFO message system for dual cpu cores. - - gp2x_dualcore_sync() ; initial FIFO message system for dual cpu cores. - - improved functions: - - gp2x_video_flip() ; initial quadruple buffering in 8bbp mode. - - 0.8: initial dual cores cpu support. - very basic blit functions by popular demand ;-) - vsync & hsync waiting code (thanks Reesy) - - added functions: - - gp2x_launch_program() ; initial dual cores cpu support. - - gp2x_launch_program_from_disk() ; initial dual cores cpu support. - - gp2x_launch_subprogram() ; initial dual cores cpu support. - - gp2x_blitter_rect15() ; very basic blit function by popular demand ;-) - - gp2x_blitter_rect8() ; very basic blit function by popular demand ;-) - - gp2x_video_hsync() ; hsync waiting code (thanks Reesy) - - gp2x_video_vsync() ; vsync waiting code (thanks Reesy) - - fixed functions: - - gp2x_video_color8() ; bugfixed a stupid typo (thanks Franxis for the bug report) - - 0.7: added functions: - - gp2x_sound_volume() - - fixed functions: - - gp2x_deinit() ; fixed menu launch code when exiting. - - improved functions: - - gp2x_timer_read() ; rewritten timer. it should be more accurate now. - - gp2x_init() ; faster init code. - - 0.6: added functions: - - gp2x_timer_read() - - gp2x_sound_pause() - - fixed functions: - - gp2x_video_setpalette() ; palette handling was incorrect. fixed. - - 0.5: improved functions: - - gp2x_init() ; better and cleaner initalizing code. - - gp2x_init() ; sound patched for real stereo output (by using NK's solution) - - 0.4: lots of cleanups. - sound is threaded and double buffered now. - 8 bpp video support. - - fixed functions: - - gp2x_deinit() ; better and cleaner exiting code. - - 0.3: shorter library. - - fixed functions: - - gp2x_joystick_read() ; improved joystick diagonal detection. - - 0.2: better code layout. - public release. - - 0.1: beta release. -*/ - -#include "minimal.h" -#include "squidgehack.h" -#include "asmutils.h" - - unsigned char *gp2x_screen8 ,*gp2x_upperRAM; - unsigned long gp2x_dev[8]={0,0,0,0,0,0,0,0}, gp2x_physvram[8], *gp2x_memregl, gp2x_volume, gp2x_ticks_per_second; -volatile unsigned long gp2x_sound_pausei=1, gp2x_ticks=0, gp2x_sound=0, *gp2x_dualcore_ram=0; - unsigned short *gp2x_memregs, *gp2x_screen15, *gp2x_logvram15[4], gp2x_sound_buffer[4+((44100/25)*2)*8]; //25 Hz gives our biggest supported sampling buffer -volatile unsigned short gp2x_palette[512]; - -extern void gp2x_sound_frame(void *blah, void *buff, int samples); - -// hack -static int scaling_enabled = 0; - -void gp2x_video_flip(void) -{ - unsigned long address=gp2x_physvram[gp2x_physvram[7]]; - if (scaling_enabled) address += 32; - - // since we are using the mmu hack, we must flush the cache first - // (the params are most likely wrong, but they seem to work somehow) - flushcache(address, address + 320*240, 0); - - if(++gp2x_physvram[7]==4) gp2x_physvram[7]=0; - gp2x_screen15=gp2x_logvram15[gp2x_physvram[7]]; - gp2x_screen8=(unsigned char *)gp2x_screen15; - - gp2x_memregs[0x290E>>1]=(unsigned short)(address & 0xFFFF); - gp2x_memregs[0x2910>>1]=(unsigned short)(address >> 16); - gp2x_memregs[0x2912>>1]=(unsigned short)(address & 0xFFFF); - gp2x_memregs[0x2914>>1]=(unsigned short)(address >> 16); -} - -void gp2x_video_flip_single(void) -{ - unsigned long address=gp2x_physvram[0]; - - gp2x_screen15=gp2x_logvram15[0]; - gp2x_screen8=(unsigned char *)gp2x_screen15; - - gp2x_memregs[0x290E>>1]=(unsigned short)(address & 0xFFFF); - gp2x_memregs[0x2910>>1]=(unsigned short)(address >> 16); - gp2x_memregs[0x2912>>1]=(unsigned short)(address & 0xFFFF); - gp2x_memregs[0x2914>>1]=(unsigned short)(address >> 16); -} - - -void gp2x_video_setgamma(unsigned short gamma) /*0..255*/ -{ - int i=256*3; - gp2x_memregs[0x295C>>1]=0; - while(i--) gp2x_memregs[0x295E>>1]=gamma; -} - -void gp2x_video_setpalette(void) -{ - unsigned short *g=(unsigned short *)gp2x_palette; int i=512; - gp2x_memregs[0x2958>>1]=0; - while(i--) gp2x_memregs[0x295A>>1]=*g++; -} - -void gp2x_blitter_rect15(gp2x_rect *r) -{ - int x, y; unsigned short *data=r->data15, *offset=&gp2x_screen15[r->x+r->y*320]; - - y=r->h; if(r->solid) - while(y--) { x=r->w; while(x--) *offset++=*data++; offset+=320-x; } - else - while(y--) { x=r->w; while(x--) { if(*data) *offset=*data; offset++, data++; } - offset+=320-x; } -} - -void gp2x_blitter_rect8(gp2x_rect *r) -{ - int x, y; unsigned char *data=r->data8, *offset=&gp2x_screen8[r->x+r->y*320]; - - y=r->h; if(r->solid) - while(y--) { x=r->w; while(x--) *offset++=*data++; offset+=320-x; } - else - while(y--) { x=r->w; while(x--) { if(*data) *offset=*data; offset++, data++; } - offset+=320-x; } -} - -unsigned long gp2x_joystick_read(void) -{ - unsigned long value=(gp2x_memregs[0x1198>>1] & 0x00FF); - - if(value==0xFD) value=0xFA; - if(value==0xF7) value=0xEB; - if(value==0xDF) value=0xAF; - if(value==0x7F) value=0xBE; - - return ~((gp2x_memregs[0x1184>>1] & 0xFF00) | value | (gp2x_memregs[0x1186>>1] << 16)); -} - -void gp2x_sound_volume(int l, int r) -{ - l=(((l*0x50)/100)<<8)|((r*0x50)/100); //0x5A, 0x60 - ioctl(gp2x_dev[4], SOUND_MIXER_WRITE_PCM, &l); //SOUND_MIXER_WRITE_VOLUME -} - -void gp2x_timer_delay(unsigned long ticks) -{ - unsigned long target=gp2x_memregl[0x0A00>>2]+ticks*gp2x_ticks_per_second; - while(gp2x_memregl[0x0A00>>2]>2]/gp2x_ticks_per_second; -} - -unsigned long gp2x_timer_read_ms(void) -{ - return gp2x_memregl[0x0A00>>2]; -} - - -void gp2x_sound_pause(int yes) { gp2x_sound_pausei=yes; } - -#if 0 -static void *gp2x_sound_play(void *blah) -{ - int flip=0, flyp=gp2x_sound_buffer[1]; - struct timespec ts; ts.tv_sec=0, ts.tv_nsec=gp2x_sound_buffer[2]; - - while(!gp2x_sound) - { - nanosleep(&ts, NULL); - - - if(!gp2x_sound_pausei) - { - // [1] is sound buffer size at 22050, 16, stereo, it is 1468 (367*4) - // [0] number of bytes?, at 22050,16,stereo, it is 367 - // first half of buffer - - // first one is 368 - - - gp2x_sound_frame(blah, (void *)(&gp2x_sound_buffer[4+flip]), gp2x_sound_buffer[0]); - // write out to second half of buffer - write(gp2x_dev[3], (void *)(&gp2x_sound_buffer[4+flyp]), gp2x_sound_buffer[1]); - - flip+=gp2x_sound_buffer[1]; - if(flip==gp2x_sound_buffer[1]*8) flip=0; - flyp+=gp2x_sound_buffer[1]; - if(flyp==gp2x_sound_buffer[1]*8) flyp=0; - } - } - return NULL; -} -#endif - -#if 0 -static void gp2x_initqueue(gp2x_queue *q, unsigned long queue_items, unsigned long *position920t, unsigned long *position940t) -{ - q->head = q->tail = q->items = 0; - q->max_items = queue_items; - if(position920t) q->place920t=position920t; else q->place920t=(unsigned long *)malloc(sizeof(unsigned long) * queue_items); - if(position940t) q->place940t=position940t; - memset(q->place920t, 0, sizeof(unsigned long) * queue_items); -} - -static void gp2x_enqueue(gp2x_queue *q, unsigned long data) -{ - while(q->items==q->max_items); /*waiting for tail to decrease...*/ - q->place920t[q->head = (q->head < q->max_items ? q->head+1 : 0)] = data; - q->items++; -} - -/* UNUSED - static unsigned long gp2x_dequeue(gp2x_queue *q) -{ - while(!q->items); //waiting for head to increase... - q->items--; - return q->place920t[q->tail = (q->tail < q->max_items ? q->tail+1 : 0)]; -} */ -#endif - - void gp2x_dualcore_pause(int yes) { if(yes) gp2x_memregs[0x0904>>1] &= 0xFFFE; else gp2x_memregs[0x0904>>1] |= 1; } -static void gp2x_940t_reset(int yes) { gp2x_memregs[0x3B48>>1] = ((yes&1) << 7) | (0x03); } -static void gp2x_940t_pause(int yes) { gp2x_dualcore_pause(yes); } - -static void gp2x_dualcore_registers(int save) -{ - static unsigned short regs[8]; - - if(save) - { - regs[0]=gp2x_memregs[0x0904>>1]; regs[1]=gp2x_memregs[0x0912>>1]; - regs[2]=gp2x_memregs[0x091c>>1]; regs[3]=gp2x_memregs[0x3b40>>1]; - regs[4]=gp2x_memregs[0x3b42>>1]; regs[5]=gp2x_memregs[0x3b48>>1]; - regs[6]=gp2x_memregs[0x3b44>>1]; regs[7]=gp2x_memregs[0x3b46>>1]; - - gp2x_940t_reset(1); - gp2x_940t_pause(1); - } - else - { - gp2x_memregs[0x0904>>1]=regs[0]; gp2x_memregs[0x0912>>1]=regs[1]; - gp2x_memregs[0x091c>>1]=regs[2]; gp2x_memregs[0x3b40>>1]=regs[3]; - gp2x_memregs[0x3b42>>1]=regs[4]; gp2x_memregs[0x3b48>>1]=regs[5]; - gp2x_memregs[0x3b44>>1]=regs[6]; gp2x_memregs[0x3b46>>1]=regs[7]; - } -} - -#if 0 -void gp2x_dualcore_sync(void) -{ - gp2x_queue *q=(gp2x_queue *)gp2x_1stcore_data_ptr(GP2X_QUEUE_ARRAY_PTR); - while(q->items); -} - -void gp2x_dualcore_exec(unsigned long command) { gp2x_enqueue((gp2x_queue *)gp2x_1stcore_data_ptr(GP2X_QUEUE_ARRAY_PTR),command); } - -void gp2x_dualcore_launch_program(unsigned long *area, unsigned long size) -{ - unsigned long i=0, *arm940t_ram=(unsigned long *)gp2x_dualcore_ram; - - gp2x_940t_reset(1); - - gp2x_memregs[0x3B40>>1] = 0; //disable interrupts - gp2x_memregs[0x3B42>>1] = 0; - gp2x_memregs[0x3B44>>1] = 0xffff; - gp2x_memregs[0x3B46>>1] = 0xffff; - - gp2x_940t_pause(0); - - while(i < size) *arm940t_ram++=area[i++]; - - gp2x_initqueue((gp2x_queue *)gp2x_1stcore_data_ptr(GP2X_QUEUE_ARRAY_PTR), GP2X_QUEUE_MAX_ITEMS, (unsigned long *)gp2x_1stcore_data_ptr(GP2X_QUEUE_DATA_PTR), (unsigned long *)gp2x_2ndcore_data_ptr(GP2X_QUEUE_DATA_PTR)); - - gp2x_940t_reset(0); -} - -void gp2x_dualcore_launch_program_from_disk(const char *file, unsigned long offset, unsigned long size) -{ - FILE *in; void *data; - - if((in=fopen(file, "rb"))==NULL) return; - if((data=malloc(size))==NULL) { fclose(in); return; } - fseek(in, 0L, offset); - fread(data, 1, size, in); - gp2x_dualcore_launch_program((unsigned long *)data, size); - free(data); - fclose(in); -} -#endif - -void gp2x_init(int ticks_per_second, int bpp, int rate, int bits, int stereo, int Hz) -{ - struct fb_fix_screeninfo fixed_info; - static int first=1; - - // GP2X_DO_SOUND - int gp2x_do_sound=1; - int frag=0; - int channels=1; - int stereoLocal=0; - int ret; - - gp2x_ticks_per_second=7372800/ticks_per_second; - - if(!gp2x_dev[0]) gp2x_dev[0] = open("/dev/fb0", O_RDWR); - if(!gp2x_dev[1]) gp2x_dev[1] = open("/dev/fb1", O_RDWR); - if(!gp2x_dev[2]) gp2x_dev[2] = open("/dev/mem", O_RDWR); - - ioctl(gp2x_dev[gp2x_physvram[7]=0], FBIOGET_FSCREENINFO, &fixed_info); - gp2x_physvram[2]=gp2x_physvram[0]=fixed_info.smem_start; - gp2x_screen15=gp2x_logvram15[2]=gp2x_logvram15[0]= - (unsigned short *)mmap(0, 0x20000*2, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], gp2x_physvram[0]); - gp2x_screen8=(unsigned char *)gp2x_screen15; - printf("/dev/fb0 is @ %08lx / %p\n", gp2x_physvram[0], gp2x_screen15); - - ioctl(gp2x_dev[1], FBIOGET_FSCREENINFO, &fixed_info); - gp2x_physvram[3]=gp2x_physvram[1]=fixed_info.smem_start; - gp2x_logvram15[3]=gp2x_logvram15[1]= - (unsigned short *)mmap(0, 0x20000*2, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], gp2x_physvram[1]); - printf("/dev/fb1 is @ %08lx / %p\n", gp2x_physvram[1], gp2x_logvram15[1]); - - // apply the MMU hack - ret = mmuhack(); - printf("squidge hack code finished and returned %s\n", ret ? "ok" : "fail"); - - // don't run sound right now - if ( gp2x_do_sound) - { - if(!gp2x_dev[3]) gp2x_dev[3] = open("/dev/dsp", O_WRONLY|O_ASYNC); - if(!gp2x_dev[4]) gp2x_dev[4] = open("/dev/mixer", O_RDWR); - } - -// gp2x_dualcore_ram=(unsigned long *)mmap(0, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], 0x03000000); -/*gp2x_dualcore_ram=(unsigned long *)mmap(0, 0x2000000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], 0x02000000);*/ - gp2x_memregl=(unsigned long *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], 0xc0000000); - gp2x_memregs=(unsigned short *)gp2x_memregl; - - if(first) { printf(MINILIB_VERSION "\n"); - gp2x_dualcore_registers(1); - gp2x_sound_volume(100,100); - gp2x_memregs[0x0F16>>1] = 0x830a; usleep(100000); - gp2x_memregs[0x0F58>>1] = 0x100c; usleep(100000); } - - gp2x_memregs[0x28DA>>1]=(((bpp+1)/8)<<9)|0xAB; /*8/15/16/24bpp...*/ - gp2x_memregs[0x290C>>1]=320*((bpp+1)/8); /*line width in bytes*/ - - memset(gp2x_screen15, 0, 320*240*2); gp2x_video_flip(); - memset(gp2x_screen15, 0, 320*240*2); gp2x_video_flip(); - - //if(bpp==8) gp2x_physvram[2]+=320*240, gp2x_physvram[3]+=320*240, - // gp2x_logvram15[2]+=320*240/2, gp2x_logvram15[3]+=320*240/2; - if(bpp==8) gp2x_physvram[2]+=0x20000, gp2x_physvram[3]+=0x20000, - gp2x_logvram15[2]+=0x20000/2, gp2x_logvram15[3]+=0x20000/2; - - - if ( gp2x_do_sound) - { - ioctl(gp2x_dev[3], SNDCTL_DSP_SPEED, &rate); - ioctl(gp2x_dev[3], SNDCTL_DSP_SETFMT, &bits); - - ioctl(gp2x_dev[3], SNDCTL_DSP_CHANNELS, &channels); - ioctl(gp2x_dev[3], SNDCTL_DSP_STEREO, &stereoLocal); - - frag = 0x40000|13; - ioctl(gp2x_dev[3], SNDCTL_DSP_SETFRAGMENT, &frag); - - { - // calculate buffer size - int frag = 0, bsize, buffers = 16; - bsize = rate / 32; - if (rate > 22050) { bsize*=4; buffers*=2; } // 44k mode seems to be very demanding - while ((bsize>>=1)) frag++; - frag |= buffers<<16; // 16 buffers - ioctl(gp2x_dev[3], SNDCTL_DSP_SETFRAGMENT, &frag); - printf("gp2x_set_sound: %i/%ibit/%s, %i buffers of %i bytes\n", - rate, bits, stereo?"stereo":"mono", frag>>16, 1<<(frag&0xffff)); - } - - if(first) - { - first=0; - } - } -} - - -extern int fcloseall(void); -void gp2x_deinit(void) -{ - while((gp2x_sound++)<1000000); //wait arm920t threads to finish - - gp2x_dualcore_registers(0); - mmuunhack(); - - gp2x_memregs[0x28DA>>1]=0x4AB; //set video mode - gp2x_memregs[0x290C>>1]=640; - - { int i; for(i=0;i<8;i++) if(gp2x_dev[i]) close(gp2x_dev[i]); } //close all devices - - fcloseall(); //close all files - -} - - -void SetVideoScaling(int pixels,int width,int height) -{ - float x, y; - float xscale,yscale=0; - - int bpp=(gp2x_memregs[0x28DA>>1]>>9)&0x3; /* bytes per pixel */ - - scaling_enabled = (width == 320) ? 0 : 1; - - if(gp2x_memregs[0x2800>>1]&0x100) /* TV-Out ON? */ - { - xscale=489.0; /* X-Scale with TV-Out (PAL or NTSC) */ - if (gp2x_memregs[0x2818>>1] == 287) /* PAL? */ - yscale=(pixels*274.0)/320.0; /* Y-Scale with PAL */ - else if (gp2x_memregs[0x2818>>1] == 239) /* NTSC? */ - yscale=(pixels*331.0)/320.0; /* Y-Scale with NTSC */ - } - else /* TV-Out OFF? */ - { - xscale=1024.0; /* X-Scale for LCD */ - yscale=pixels; /* Y-Scale for LCD */ - } - - x=(xscale*width)/320.0; - y=(yscale*bpp*height)/240.0; - gp2x_memregs[0x2906>>1]=(unsigned short)x; /* scale horizontal */ - gp2x_memregl[0x2908>>2]=(unsigned long)y; /* scale vertical */ - gp2x_memregs[0x290C>>1]=pixels*bpp; /* Set Video Width */ -} +/** + * This is a rewrite of a subset of rlyeh's minimal library. +**/ + +/* + + GP2X minimal library v0.A by rlyeh, (c) 2005. emulnation.info@rlyeh (swap it!) + + Thanks to Squidge, Robster, snaff, Reesy and NK, for the help & previous work! :-) + + License + ======= + + Free for non-commercial projects (it would be nice receiving a mail from you). + Other cases, ask me first. + + GamePark Holdings is not allowed to use this library and/or use parts from it. + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "minimal.h" +#include "usbjoy.h" +#include "asmutils.h" + +volatile unsigned short *gp2x_memregs; +//static +volatile unsigned long *gp2x_memregl; +static void *gp2x_screens[4]; +static int screensel = 0; +//static +int memdev = 0; +static int sounddev = 0, mixerdev = 0; + +void *gp2x_screen; + +#define FRAMEBUFF_WHOLESIZE (0x30000*4) // 320*240*2 + some more +#define FRAMEBUFF_ADDR0 (0x4000000-FRAMEBUFF_WHOLESIZE) +#define FRAMEBUFF_ADDR1 (FRAMEBUFF_ADDR0+0x30000) +#define FRAMEBUFF_ADDR2 (FRAMEBUFF_ADDR1+0x30000) +#define FRAMEBUFF_ADDR3 (FRAMEBUFF_ADDR2+0x30000) + +static const int gp2x_screenaddrs[4] = { FRAMEBUFF_ADDR0, FRAMEBUFF_ADDR1, FRAMEBUFF_ADDR2, FRAMEBUFF_ADDR3 }; +static int gp2x_screenaddrs_use[4]; +static unsigned short gp2x_screenaddr_old[4]; + + +// hack to simplify thing for fceu +static int scaling_enabled = 0; + +/* video stuff */ +void gp2x_video_flip(void) +{ + unsigned short lsw, msw; + int addr = gp2x_screenaddrs_use[screensel&3]; + + if (scaling_enabled) addr += 32; + + // since we are using the mmu hack, we must flush the cache first + // (the params are most likely wrong, but they seem to work somehow) + flushcache(addr, addr + 320*240*2, 0); + + lsw = (unsigned short) addr; + msw = (unsigned short)(addr >> 16); + + gp2x_memregs[0x2910>>1] = msw; + gp2x_memregs[0x2914>>1] = msw; + gp2x_memregs[0x290E>>1] = lsw; + gp2x_memregs[0x2912>>1] = lsw; + + // jump to other buffer: + gp2x_screen = gp2x_screens[++screensel&3]; +} + +/* doulblebuffered flip */ +void gp2x_video_flip2(void) +{ + unsigned short msw = (unsigned short)(gp2x_screenaddrs_use[screensel&1] >> 16); + + gp2x_memregs[0x2910>>1] = msw; + gp2x_memregs[0x2914>>1] = msw; + gp2x_memregs[0x290E>>1] = 0; + gp2x_memregs[0x2912>>1] = 0; + + // jump to other buffer: + gp2x_screen = gp2x_screens[++screensel&1]; +} + + +void gp2x_video_changemode2(int bpp) +{ + gp2x_memregs[0x28DA>>1]=(((bpp+1)/8)<<9)|0xAB; /*8/15/16/24bpp...*/ + gp2x_memregs[0x290C>>1]=320*((bpp+1)/8); /*line width in bytes*/ +} + + +void gp2x_video_changemode(int bpp) +{ + gp2x_video_changemode2(bpp); + + gp2x_memset_all_buffers(0, 0, 320*240*2); + gp2x_video_flip(); +} + + +void gp2x_video_setpalette(int *pal, int len) +{ + unsigned short *g=(unsigned short *)pal; + volatile unsigned short *memreg = &gp2x_memregs[0x295A>>1]; + gp2x_memregs[0x2958>>1] = 0; + + len *= 2; + while(len--) *memreg=*g++; +} + + +// TV Compatible function // +void gp2x_video_RGB_setscaling(int ln_offs, int W, int H) +{ + float escalaw, escalah; + int bpp = (gp2x_memregs[0x28DA>>1]>>9)&0x3; + unsigned short scalw; + + // fceu hack + scaling_enabled = (W == 320) ? 0 : 1; + + // set offset + gp2x_screenaddrs_use[0] = gp2x_screenaddrs[0] + ln_offs * 320 * bpp; + gp2x_screenaddrs_use[1] = gp2x_screenaddrs[1] + ln_offs * 320 * bpp; + gp2x_screenaddrs_use[2] = gp2x_screenaddrs[2] + ln_offs * 320 * bpp; + gp2x_screenaddrs_use[3] = gp2x_screenaddrs[3] + ln_offs * 320 * bpp; + + escalaw = 1024.0; // RGB Horiz LCD + escalah = 320.0; // RGB Vert LCD + + if(gp2x_memregs[0x2800>>1]&0x100) //TV-Out + { + escalaw=489.0; // RGB Horiz TV (PAL, NTSC) + if (gp2x_memregs[0x2818>>1] == 287) //PAL + escalah=274.0; // RGB Vert TV PAL + else if (gp2x_memregs[0x2818>>1] == 239) //NTSC + escalah=331.0; // RGB Vert TV NTSC + } + + // scale horizontal + scalw = (unsigned short)((float)escalaw *(W/320.0)); + /* if there is no horizontal scaling, vertical doesn't work. Here is a nasty wrokaround... */ + if (H != 240 && W == 320) scalw--; + gp2x_memregs[0x2906>>1]=scalw; + // scale vertical + gp2x_memregl[0x2908>>2]=(unsigned long)((float)escalah *bpp *(H/240.0)); +} + + +void gp2x_memcpy_buffers(int buffers, void *data, int offset, int len) +{ + if (buffers & (1<<0)) memcpy((char *)gp2x_screens[0] + offset, data, len); + if (buffers & (1<<1)) memcpy((char *)gp2x_screens[1] + offset, data, len); + if (buffers & (1<<2)) memcpy((char *)gp2x_screens[2] + offset, data, len); + if (buffers & (1<<3)) memcpy((char *)gp2x_screens[3] + offset, data, len); +} + + +void gp2x_memcpy_all_buffers(void *data, int offset, int len) +{ + gp2x_memcpy_buffers(0xf, data, offset, len); +} + + +void gp2x_memset_all_buffers(int offset, int byte, int len) +{ + memset((char *)gp2x_screens[0] + offset, byte, len); + memset((char *)gp2x_screens[1] + offset, byte, len); + memset((char *)gp2x_screens[2] + offset, byte, len); + memset((char *)gp2x_screens[3] + offset, byte, len); +} + + +unsigned long gp2x_joystick_read(int allow_usb_joy) +{ + int i; + unsigned long value=(gp2x_memregs[0x1198>>1] & 0x00FF); + if(value==0xFD) value=0xFA; + if(value==0xF7) value=0xEB; + if(value==0xDF) value=0xAF; + if(value==0x7F) value=0xBE; + value = ~((gp2x_memregs[0x1184>>1] & 0xFF00) | value | (gp2x_memregs[0x1186>>1] << 16)); + + if (allow_usb_joy && num_of_joys > 0) { + // check the usb joy as well.. + gp2x_usbjoy_update(); + for (i = 0; i < num_of_joys; i++) + value |= gp2x_usbjoy_check(i); + } + + return value; +} + +static int s_oldrate = 0, s_oldbits = 0, s_oldstereo = 0; + +void gp2x_start_sound(int rate, int bits, int stereo) +{ + int frag = 0, bsize, buffers; + + // if no settings change, we don't need to do anything + if (rate == s_oldrate && s_oldbits == bits && s_oldstereo == stereo) return; + + if (sounddev > 0) close(sounddev); + sounddev = open("/dev/dsp", O_WRONLY|O_ASYNC); + if (sounddev == -1) + printf("open(\"/dev/dsp\") failed with %i\n", errno); + + ioctl(sounddev, SNDCTL_DSP_SPEED, &rate); + ioctl(sounddev, SNDCTL_DSP_SETFMT, &bits); + ioctl(sounddev, SNDCTL_DSP_STEREO, &stereo); + // calculate buffer size + buffers = 16; + bsize = rate / 32; + if (rate > 22050) { bsize*=4; buffers*=2; } // 44k mode seems to be very demanding + while ((bsize>>=1)) frag++; + frag |= buffers<<16; // 16 buffers + ioctl(sounddev, SNDCTL_DSP_SETFRAGMENT, &frag); + printf("gp2x_set_sound: %i/%ibit/%s, %i buffers of %i bytes\n", + rate, bits, stereo?"stereo":"mono", frag>>16, 1<<(frag&0xffff)); + + s_oldrate = rate; s_oldbits = bits; s_oldstereo = stereo; + usleep(100000); +} + + +void gp2x_sound_write(void *buff, int len) +{ + write(sounddev, buff, len); +} + +void gp2x_sound_sync(void) +{ + ioctl(sounddev, SOUND_PCM_SYNC, 0); +} + +void gp2x_sound_volume(int l, int r) +{ + l=l<0?0:l; l=l>255?255:l; r=r<0?0:r; r=r>255?255:r; + l<<=8; l|=r; + ioctl(mixerdev, SOUND_MIXER_WRITE_PCM, &l); /*SOUND_MIXER_WRITE_VOLUME*/ +} + + +/* common */ +void gp2x_init(void) +{ + printf("entering init()\n"); fflush(stdout); + + memdev = open("/dev/mem", O_RDWR); + if (memdev == -1) + { + printf("open(\"/dev/mem\") failed with %i\n", errno); + exit(1); + } + + gp2x_memregs = mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000); + printf("memregs are @ %p\n", gp2x_memregs); + if(gp2x_memregs == MAP_FAILED) + { + printf("mmap(memregs) failed with %i\n", errno); + exit(1); + } + gp2x_memregl = (unsigned long *) gp2x_memregs; + + gp2x_screens[0] = mmap(0, FRAMEBUFF_WHOLESIZE, PROT_WRITE, MAP_SHARED, memdev, FRAMEBUFF_ADDR0); + if(gp2x_screens[0] == MAP_FAILED) + { + printf("mmap(gp2x_screen) failed with %i\n", errno); + exit(1); + } + printf("framebuffers point to %p\n", gp2x_screens[0]); + gp2x_screens[1] = (char *) gp2x_screens[0]+0x30000; + gp2x_screens[2] = (char *) gp2x_screens[1]+0x30000; + gp2x_screens[3] = (char *) gp2x_screens[2]+0x30000; + + gp2x_screen = gp2x_screens[0]; + screensel = 0; + + gp2x_screenaddr_old[0] = gp2x_memregs[0x290E>>1]; + gp2x_screenaddr_old[1] = gp2x_memregs[0x2910>>1]; + gp2x_screenaddr_old[2] = gp2x_memregs[0x2912>>1]; + gp2x_screenaddr_old[3] = gp2x_memregs[0x2914>>1]; + + memcpy(gp2x_screenaddrs_use, gp2x_screenaddrs, sizeof(gp2x_screenaddrs)); + gp2x_memset_all_buffers(0, 0, 320*240*2); + + // snd + mixerdev = open("/dev/mixer", O_RDWR); + if (mixerdev == -1) + printf("open(\"/dev/mixer\") failed with %i\n", errno); + + /* init usb joys -GnoStiC */ + gp2x_usbjoy_init(); + + printf("exitting init()\n"); fflush(stdout); +} + +char *ext_menu = 0, *ext_state = 0; + +void gp2x_deinit(void) +{ + gp2x_video_changemode(15); + gp2x_memregs[0x290E>>1] = gp2x_screenaddr_old[0]; + gp2x_memregs[0x2910>>1] = gp2x_screenaddr_old[1]; + gp2x_memregs[0x2912>>1] = gp2x_screenaddr_old[2]; + gp2x_memregs[0x2914>>1] = gp2x_screenaddr_old[3]; + + munmap(gp2x_screens[0], FRAMEBUFF_WHOLESIZE); + munmap((void *)gp2x_memregs, 0x10000); + close(memdev); + close(mixerdev); + if (sounddev > 0) close(sounddev); + + gp2x_usbjoy_deinit(); + + printf("all done, running "); + + // Zaq121's alternative frontend support from MAME + if(ext_menu && ext_state) { + printf("%s -state %s\n", ext_menu, ext_state); + execl(ext_menu, ext_menu, "-state", ext_state, NULL); + } else if(ext_menu) { + printf("%s\n", ext_menu); + execl(ext_menu, ext_menu, NULL); + } else { + printf("gp2xmenu\n"); + chdir("/usr/gp2x"); + execl("gp2xmenu", "gp2xmenu", NULL); + } +} + + diff --git a/drivers/gp2x/minimal.h b/drivers/gp2x/minimal.h index ecafd75..37507f0 100644 --- a/drivers/gp2x/minimal.h +++ b/drivers/gp2x/minimal.h @@ -1,107 +1,38 @@ -/* - GP2X minimal library v0.A by rlyeh, (c) 2005. emulnation.info@rlyeh (swap it!) +#ifndef __GP2X_H__ +#define __GP2X_H__ - Thanks to Squidge, Robster, snaff, Reesy and NK, for the help & previous work! :-) - License - ======= +void gp2x_init(void); +void gp2x_deinit(void); - Free for non-commercial projects (it would be nice receiving a mail from you). - Other cases, ask me first. +/* video */ +void gp2x_video_flip(void); +void gp2x_video_changemode(int bpp); +void gp2x_video_changemode2(int bpp); +void gp2x_video_setpalette(int *pal, int len); +void gp2x_video_RGB_setscaling(int ln_offs, int W, int H); +void gp2x_memcpy_buffers(int buffers, void *data, int offset, int len); +void gp2x_memcpy_all_buffers(void *data, int offset, int len); +void gp2x_memset_all_buffers(int offset, int byte, int len); - GamePark Holdings is not allowed to use this library and/or use parts from it. +/* sound */ +void gp2x_start_sound(int rate, int bits, int stereo); +void gp2x_sound_write(void *buff, int len); +void gp2x_sound_volume(int l, int r); -*/ +/* joy */ +unsigned long gp2x_joystick_read(int allow_usb_joy); -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include -#include -#include -#include +extern void *gp2x_screen; +extern int memdev; +extern char *ext_menu, *ext_state; -#ifndef __MINIMAL_H__ -#define __MINIMAL_H__ - -#define MINILIB_VERSION "GP2X minimal library v0.A by rlyeh, (c) 2005." - -typedef struct gp2x_queue { volatile unsigned long head, tail, items, max_items; unsigned long *place920t, *place940t; } gp2x_queue; -typedef struct gp2x_rect { int x,y,w,h,solid; unsigned short *data15; unsigned char *data8; } gp2x_rect; - -extern void gp2x_timer_delay(unsigned long ticks); -extern void gp2x_sound_pause(int yes); -extern void gp2x_dualcore_pause(int yes); -extern void gp2x_blitter_rect15(gp2x_rect *r); -extern void gp2x_blitter_rect8(gp2x_rect *r); - - - -//extern void gp2x_sound_frame (void *blah, void *bufferg, int samples); enum { GP2X_UP=0x1, GP2X_LEFT=0x4, GP2X_DOWN=0x10, GP2X_RIGHT=0x40, GP2X_START=1<<8, GP2X_SELECT=1<<9, GP2X_L=1<<10, GP2X_R=1<<11, GP2X_A=1<<12, GP2X_B=1<<13, GP2X_X=1<<14, GP2X_Y=1<<15, - GP2X_VOL_UP=1<<23, GP2X_VOL_DOWN=1<<22, GP2X_PUSH=1<<27 }; - - -#define GP2X_QUEUE_MAX_ITEMS 16 -#define GP2X_QUEUE_ARRAY_PTR ((0x1000-(sizeof(gp2x_queue)<<2))) -#define GP2X_QUEUE_DATA_PTR (GP2X_QUEUE_ARRAY_PTR-(GP2X_QUEUE_MAX_ITEMS<<2)) - -#define gp2x_2ndcore_code(v) (*(volatile unsigned long *)(v)) -#define gp2x_1stcore_code(v) gp2x_dualcore_ram[(v)>>2] -#define gp2x_2ndcore_data(v) gp2x_2ndcore_code((v)+0x100000) -#define gp2x_1stcore_data(v) gp2x_1stcore_code((v)+0x100000) -#define gp2x_dualcore_data(v) gp2x_1stcore_data(v) - -#define gp2x_2ndcore_code_ptr(v) ((volatile unsigned long *)(v)) -#define gp2x_1stcore_code_ptr(v) (&gp2x_dualcore_ram[(v)>>2]) -#define gp2x_2ndcore_data_ptr(v) gp2x_2ndcore_code_ptr((v)+0x100000) -#define gp2x_1stcore_data_ptr(v) gp2x_1stcore_code_ptr((v)+0x100000) - -#define gp2x_video_wait_vsync() while(gp2x_memregs[0x1182>>1]&(1<<4)); -#define gp2x_video_wait_hsync() while(gp2x_memregs[0x1182>>1]&(1<<5)); - -#define gp2x_video_color8(C,R,G,B) do gp2x_palette[((C)<<1)+0]=((G)<<8)|(B),gp2x_palette[((C)<<1)+1]=(R); while(0) -#define gp2x_video_color15(R,G,B,A) ((((R)&0xF8)<<8)|(((G)&0xF8)<<3)|(((B)&0xF8)>>3)|((A)<<5)) - - -extern volatile unsigned short gp2x_palette[512]; -extern unsigned short *gp2x_screen15; -extern unsigned char *gp2x_screen8; -extern volatile unsigned long *gp2x_dualcore_ram; - -extern void gp2x_init(int tickspersecond, int bpp, int rate, int bits, int stereo, int hz); -extern void gp2x_deinit(void); - -extern void gp2x_video_flip(void); -extern void gp2x_video_flip_single(void); -extern void gp2x_video_setpalette(void); - -extern unsigned long gp2x_joystick_read(void); - -extern void gp2x_sound_volume(int left, int right); - -extern unsigned long gp2x_timer_read(void); -extern unsigned long gp2x_timer_read_ms(void); - -extern void gp2x_dualcore_enable(int on); -extern void gp2x_dualcore_sync(void); -extern void gp2x_dualcore_exec(unsigned long command); -extern void gp2x_dualcore_launch_program(unsigned long *area, unsigned long size); -extern void gp2x_dualcore_launch_program_from_disk(const char *file, unsigned long offset, unsigned long size); - -#define gp2x_dualcore_declare_subprogram(name) extern void gp2x_dualcore_launch_## name ##_subprogram(void); -#define gp2x_dualcore_launch_subprogram(name) gp2x_dualcore_launch_## name ##_subprogram() + GP2X_VOL_UP=1<<23, GP2X_VOL_DOWN=1<<22, GP2X_PUSH=1<<27 }; #endif - diff --git a/drivers/gp2x/minimal_940t.h b/drivers/gp2x/minimal_940t.h deleted file mode 100644 index 82cd1c0..0000000 --- a/drivers/gp2x/minimal_940t.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - - GP2X minimal library v0.A by rlyeh, (c) 2005. emulnation.info@rlyeh (swap it!) - - Thanks to Squidge, Robster, snaff, Reesy and NK, for the help & previous work! :-) - - License - ======= - - Free for non-commercial projects (it would be nice receiving a mail from you). - Other cases, ask me first. - - GamePark Holdings is not allowed to use this library and/or use parts from it. - -*/ - -#include "minimal.h" - -#ifndef __MINIMAL_H_STUB_940T__ -#define __MINIMAL_H_STUB_940T__ - -#undef gp2x_dualcore_data -#define gp2x_dualcore_data(v) gp2x_2ndcore_data(v) - -#define main gp2x_2ndcore_run - -static void gp2x_2ndcore_start(void) __attribute__((naked)); - -static void gp2x_2ndcore_start(void) -{ - unsigned long gp2x_dequeue(gp2x_queue *q) - { - unsigned long data; - - while(!q->items); //waiting for head to increase... - - data=q->place940t[q->tail = (q->tail < q->max_items ? q->tail+1 : 0)]; - q->items--; - - return data; - } - -#define gp2x_dualcore_name_subprogram(name) \ -/* 00000020 <_start>: */ \ -/* 0:*/ asm volatile (".word 0xe59ff02c"); /* ldr pc, [pc, #44] ; 34 */ \ -/* 4:*/ asm volatile (".word 0xe59ff028"); /* ldr pc, [pc, #40] ; 34 */ \ -/* 8:*/ asm volatile (".word 0xe59ff024"); /* ldr pc, [pc, #36] ; 34 */ \ -/* c:*/ asm volatile (".word 0xe59ff020"); /* ldr pc, [pc, #32] ; 34 */ \ -/* 10:*/ asm volatile (".word 0xe59ff01c"); /* ldr pc, [pc, #28] ; 34 */ \ -/* 14:*/ asm volatile (".word 0xe59ff018"); /* ldr pc, [pc, #24] ; 34 */ \ -/* 18:*/ asm volatile (".word 0xe59ff014"); /* ldr pc, [pc, #20] ; 34 */ \ -/* 1c:*/ asm volatile (".word 0xe59ff010"); /* ldr pc, [pc, #16] ; 34 */ \ -/* 00000020 <_init>: */ \ -/* 20:*/ asm volatile (".word 0xe59fd010"); /* ldr sp, [pc, #16] ; 38 */ \ -/* 24:*/ asm volatile (".word 0xe59fc010"); /* ldr ip, [pc, #16] ; 3c */ \ -/* 28:*/ asm volatile (".word 0xe59fb010"); /* ldr fp, [pc, #16] ; 40 */ \ -/* 2c:*/ asm volatile (".word 0xe92d1800"); /* stmdb sp!, {fp, ip} */ \ -/* 30:*/ asm volatile (".word 0xea000004"); /* b 48 */ \ -/* 00000034 : */ \ -/* 34:*/ asm volatile (".word 0x00000020"); /* */ \ -/* 00000038 : */ \ -/* 38:*/ asm volatile (".word 0x000ffffc"); /* */ \ -/* 0000003c : */ \ -/* 3c:*/ asm volatile (".word 0xdeadbeef"); /* */ \ -/* 00000040 : */ \ -/* 40:*/ asm volatile (".word 0x1ee7face"); /* */ \ -/* 00000044 : */ \ -/* 44:*/ asm volatile (".word 0x00100019"); /* */ \ -/* 00000048 : */ \ -/* our main code starts here... */ \ -/* 48:*/ asm volatile (".word 0xe3a0003f"); /* mov r0, #63 ; 0x3f */ \ -/* 4c:*/ asm volatile (".word 0xee060f10"); /* mcr 15, 0, r0, cr6, cr0, {0} */ \ -/* 50:*/ asm volatile (".word 0xee060f30"); /* mcr 15, 0, r0, cr6, cr0, {1} */ \ -/* 54:*/ asm volatile (".word 0xe51f0018"); /* ldr r0, [pc, #-24] ; 44 */ \ -/* 58:*/ asm volatile (".word 0xee060f11"); /* mcr 15, 0, r0, cr6, cr1, {0} */ \ -/* 5c:*/ asm volatile (".word 0xee060f31"); /* mcr 15, 0, r0, cr6, cr1, {1} */ \ -/* 60:*/ asm volatile (".word 0xe3a00001"); /* mov r0, #1 ; 0x1 */ \ -/* 64:*/ asm volatile (".word 0xee020f10"); /* mcr 15, 0, r0, cr2, cr0, {0} */ \ -/* 68:*/ asm volatile (".word 0xee020f30"); /* mcr 15, 0, r0, cr2, cr0, {1} */ \ -/* 6c:*/ asm volatile (".word 0xee030f10"); /* mcr 15, 0, r0, cr3, cr0, {0} */ \ -/* 70:*/ asm volatile (".word 0xe3a0000f"); /* mov r0, #15 ; 0xf */ \ -/* 74:*/ asm volatile (".word 0xee050f10"); /* mcr 15, 0, r0, cr5, cr0, {0} */ \ -/* 78:*/ asm volatile (".word 0xee050f30"); /* mcr 15, 0, r0, cr5, cr0, {1} */ \ -/* 7c:*/ asm volatile (".word 0xee110f10"); /* mrc 15, 0, r0, cr1, cr0, {0} */ \ -/* 80:*/ asm volatile (".word 0xe3800001"); /* orr r0, r0, #1 ; 0x1 */ \ -/* 84:*/ asm volatile (".word 0xe3800004"); /* orr r0, r0, #4 ; 0x4 */ \ -/* 88:*/ asm volatile (".word 0xe3800a01"); /* orr r0, r0, #4096 ; 0x1000 */ \ -/* 8c:*/ asm volatile (".word 0xe3800103"); /* orr r0, r0, #-1073741824 ; 0xc0000000 */ \ -/* 90:*/ asm volatile (".word 0xee010f10"); /* mcr 15, 0, r0, cr1, cr0, {0} */ \ - while(1) gp2x_2ndcore_run(gp2x_dequeue((gp2x_queue *)gp2x_2ndcore_data_ptr(GP2X_QUEUE_ARRAY_PTR))); \ -} \ -void gp2x_dualcore_launch_##name##_subprogram(void) { gp2x_dualcore_launch_program((unsigned long *)&gp2x_2ndcore_start, ((int)&gp2x_dualcore_launch_##name##_subprogram)-((int)&gp2x_2ndcore_start)); } - -#endif - - diff --git a/drivers/gp2x/throttle.c b/drivers/gp2x/throttle.c index e70bbd3..b6b628c 100644 --- a/drivers/gp2x/throttle.c +++ b/drivers/gp2x/throttle.c @@ -1,5 +1,6 @@ #include #include "main.h" +#include "gp2x.h" #include "throttle.h" #if 0 @@ -48,7 +49,7 @@ INLINE void SpeedThrottle(void) #else extern uint8 PAL; -extern int FSkip, FSkip_setting; +extern int FSkip; static int usec_aim = 0, usec_done = 0; static int skip_count = 0; @@ -73,9 +74,9 @@ INLINE void SpeedThrottle(void) usec_done += tv_now.tv_usec - tv_prev.tv_usec; #ifdef FRAMESKIP - if (FSkip_setting >= 0) + if (Settings.frameskip >= 0) { - if (skip_count >= FSkip_setting) + if (skip_count >= Settings.frameskip) skip_count = 0; else { skip_count++; @@ -85,9 +86,10 @@ INLINE void SpeedThrottle(void) else if (usec_done > usec_aim + 1024*4) { /* auto frameskip */ - if (usec_done - usec_aim > 150000) + if (usec_done - usec_aim > 1024*32) usec_done = usec_aim = 1; // too much behind, try to recover.. - FSkip = 1; + else + FSkip = 1; tv_prev = tv_now; return; } diff --git a/drivers/gp2x/usbjoy.c b/drivers/gp2x/usbjoy.c new file mode 100644 index 0000000..de1178a --- /dev/null +++ b/drivers/gp2x/usbjoy.c @@ -0,0 +1,424 @@ +/* Title: USB Joystick library + Version 0.2 + Written by Puck2099 (puck2099@gmail.com), (c) 2006. + + + If you use this library or a part of it, please, let it know. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include /* For the definition of NULL */ +#include // For Device open +#include +#include +#include +#include // For Device read + +#include +#include /* For the definition of PATH_MAX */ +#include + +#include "usbjoy.h" + + +/* + Function: joy_open + + Opens a USB joystick and fills its information. + + Parameters: + + joynumber - Joystick's identifier (0 reserved for GP2X's builtin Joystick). + + Returns: + + Filled usbjoy structure. + +*/ +struct usbjoy *joy_open(int joynumber) +{ + int fd; + char path [128]; + struct usbjoy * joy = NULL; + struct js_event event; + static char insmod_done = 0; + + // notaz: on my system I get unresolved input_* symbols, so have to 'insmod input' too + // also we should insmod only once, not on every joy_open() call. + if (!insmod_done) { + system ("insmod input"); + system ("insmod joydev"); // Loads joydev module + insmod_done = 1; + } + + if (joynumber == 0) { + } + else if (joynumber > 0) { + sprintf (path, "/dev/input/js%d", joynumber-1); + fd = open(path, O_RDONLY, 0); + if (fd > 0) { + joy = (struct usbjoy *) malloc(sizeof(*joy)); + if (joy == NULL) { close(fd); return NULL; } + memset(joy, 0, sizeof(*joy)); + + // Set the joystick to non-blocking read mode + fcntl(fd, F_SETFL, O_NONBLOCK); + + // notaz: maybe we should flush init events now. + // My pad returns axis as active when I plug it in, which is kind of annoying. + while (read(fd, &event, sizeof(event)) > 0); + + // Joystick's file descriptor + joy->fd = fd; + + // Joystick's name + ioctl(joy->fd, JSIOCGNAME(128*sizeof(char)), joy->name); + + // Joystick's device + strcpy(joy->device, path); + + // Joystick's buttons + ioctl(joy->fd, JSIOCGBUTTONS, &joy->numbuttons); + + // Joystick's axes + ioctl(joy->fd, JSIOCGAXES, &joy->numaxes); + + // Joystick's type (derived from name) + if (strncasecmp(joy->name, "logitech", strlen("logitech")) == 0) + joy->type = JOY_TYPE_LOGITECH; + else joy->type = JOY_TYPE_GENERIC; + } else { + // printf ("ERROR: No Joystick found\n"); + } + } + return joy; +} + +/* + Function: joy_name + + Returns Joystick's name. + + Parameters: + + joy - Selected joystick. + + Returns: + + Joystick's name or NULL if struct is empty. +*/ +char * joy_name (struct usbjoy * joy) { + if (joy != NULL) return joy->name; + else return NULL; +} + + +/* + Function: joy_device + + Returns Joystick's device. + + Parameters: + + joy - Selected joystick. + + Returns: + + Joystick's device or NULL if struct is empty. +*/ +char * joy_device (struct usbjoy * joy) { + if (joy != NULL) return joy->device; + else return NULL; +} + + +/* + Function: joy_buttons + + Returns Joystick's buttons number. + + Parameters: + + joy - Selected joystick. + + Returns: + + Joystick's buttons or 0 if struct is empty. +*/ +int joy_buttons (struct usbjoy * joy) { + if (joy != NULL) return joy->numbuttons; + else return 0; +} + + +/* + Function: joy_axes + + Returns Joystick's axes number. + + Parameters: + + joy - Selected joystick. + + Returns: + + Joystick's axes or 0 if struct is empty. +*/ +int joy_axes (struct usbjoy * joy) { + if (joy != NULL) return joy->numaxes; + else return 0; +} + + +/* + Function: joy_update + + Updates Joystick's internal information ( and fields). + + Parameters: + + joy - Selected joystick. + + Returns: + + 0 - No events registered (no need to update). + 1 - Events registered (a button or axe has been pushed). + -1 - Error: struct is empty. +*/ +int joy_update (struct usbjoy * joy) { + struct js_event events[0xff]; + int i, len; + int event = 0; + if (joy != NULL) { + if ((len=read(joy->fd, events, (sizeof events))) >0) { + len /= sizeof(events[0]); + for ( i=0; istateaxes[JOYLEFT] = joy->stateaxes[JOYRIGHT] = 0; + else if (events[i].value < 0) joy->stateaxes[JOYLEFT] = 1; + else joy->stateaxes[JOYRIGHT] = 1; + } + else if (events[i].number == 1) { + if (events[i].value == 0) joy->stateaxes[JOYUP] = joy->stateaxes[JOYDOWN] = 0; + else if (events[i].value < 0) joy->stateaxes[JOYUP] = 1; + else joy->stateaxes[JOYDOWN] = 1; + } + event = 1; + break; + case JS_EVENT_BUTTON: + joy->statebuttons[events[i].number] = events[i].value; + event = 1; + break; + default: + break; + } + } + } + } + else { + event = -1; + } + return event; +} + + +/* + Function: joy_getbutton + + Returns Joystick's button information. + + Parameters: + + button - Button which value you want to know (from 0 to 31). + joy - Selected joystick. + + Returns: + + 0 - Button NOT pushed. + 1 - Button pushed. + -1 - Error: struct is empty. +*/ +int joy_getbutton (int button, struct usbjoy * joy) { + if (joy != NULL) { + if (button < joy_buttons(joy)) return joy->statebuttons[button]; + else return 0; + } + else return -1; +} + + +/* + Function: joy_getaxe + + Returns Joystick's axes information. + + Parameters: + + axe - Axe which value you want to know (see ). + joy - Selected joystick. + + Returns: + + 0 - Direction NOT pushed. + 1 - Direction pushed. + -1 - Error: struct is empty. +*/ +int joy_getaxe (int axe, struct usbjoy * joy) { + if (joy != NULL) { + if (axe < 4) return joy->stateaxes[axe]; + else return 0; + } + else return -1; +} + + +/* + Function: joy_close + + Closes selected joystick's file descriptor and detroys it's fields. + + Parameters: + + joy - Selected joystick. + + Returns: + + 0 - Joystick successfully closed. + -1 - Error: struct is empty. +*/ +int joy_close (struct usbjoy * joy) { + if (joy != NULL) { + close (joy->fd); + free (joy); + return 0; + } + else return -1; +} + + +/*********************************************************************/ +/* GP2X USB Joystick Handling -GnoStiC */ +/*********************************************************************/ + +#include "minimal.h" + +int num_of_joys = 0; +struct usbjoy *joys[4]; + +void gp2x_usbjoy_init (void) { + /* Open available joysticks -GnoStiC */ + int i, n = 0; + + printf("\n"); + for (i = 0; i < 4; i++) { + joys[n] = joy_open(i+1); + if (joys[n] && joy_buttons(joys[n]) > 0) { + printf ("+-Joystick %d: \"%s\", buttons = %i\n", i+1, joy_name(joys[n]), joy_buttons(joys[n])); + n++; + } + } + num_of_joys = n; + + printf("Found %d Joystick(s)\n",num_of_joys); +} + +void gp2x_usbjoy_update (void) { + /* Update Joystick Event Cache */ + int q, foo; + for (q=0; q < num_of_joys; q++) { + foo = joy_update (joys[q]); + } +} + +int gp2x_usbjoy_check (int joyno) { + /* Check Joystick */ + int q, joyExKey = 0; + struct usbjoy *joy = joys[joyno]; + + if (joy != NULL) { + if (joy_getaxe(JOYUP, joy)) { joyExKey |= GP2X_UP; } + if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= GP2X_DOWN; } + if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= GP2X_LEFT; } + if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= GP2X_RIGHT; } + + /* loop through joy buttons to check if they are pushed */ + for (q=0; qtype == JOY_TYPE_LOGITECH) { + switch (q) { + case 0: joyExKey |= GP2X_A; break; + case 1: joyExKey |= GP2X_X; break; + case 2: joyExKey |= GP2X_B; break; + case 3: joyExKey |= GP2X_Y; break; + } + } else { + switch (q) { + case 0: joyExKey |= GP2X_Y; break; + case 1: joyExKey |= GP2X_B; break; + case 2: joyExKey |= GP2X_X; break; + case 3: joyExKey |= GP2X_A; break; + } + } + + switch (q) { + case 4: joyExKey |= GP2X_L; break; + case 5: joyExKey |= GP2X_R; break; + case 6: joyExKey |= GP2X_L; break; /* left shoulder button 2 */ + case 7: joyExKey |= GP2X_R; break; /* right shoulder button 2 */ + case 8: joyExKey |= GP2X_SELECT;break; + case 9: joyExKey |= GP2X_START; break; + case 10: joyExKey |= GP2X_PUSH; break; + case 11: joyExKey |= GP2X_PUSH; break; + } + } + } + } + return joyExKey; +} + +int gp2x_usbjoy_check2 (int joyno) { + /* Check Joystick, don't map to gp2x joy */ + int q, to, joyExKey = 0; + struct usbjoy *joy = joys[joyno]; + + if (joy != NULL) { + if (joy_getaxe(JOYUP, joy)) { joyExKey |= 1 << 0; } + if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= 1 << 1; } + if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= 1 << 2; } + if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= 1 << 3; } + + /* loop through joy buttons to check if they are pushed */ + to = joy->numbuttons; + if (to > 32-4) to = 32-4; + for (q=0; q < to; q++) + if (joy->statebuttons[q]) joyExKey |= 1 << (q+4); + } + return joyExKey; +} + + + +void gp2x_usbjoy_deinit (void) { + int i; + for (i=0; i + + If you use this library or a part of it, please, let it know. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef USBJOY_H +#define USBJOY_H + +/* notaz: my Logitech has different button layout, and I want it to match gp2x's */ +typedef enum { + JOY_TYPE_GENERIC, + JOY_TYPE_LOGITECH +} joy_type; + +/* + Enumeration: Axes values + This enumeration contains shortcuts to the values used on axes. + + Constants: + JOYUP - Joystick Up + JOYDOWN - Joystick Down + JOYLEFT - Joystick Left + JOYRIGHT - Joystick Right + + See also: + +*/ +#define JOYUP (0) +#define JOYDOWN (1) +#define JOYLEFT (2) +#define JOYRIGHT (3) + + +/* + Struct: usbjoy + + Contains all Joystick needed information. + + Fields: + fd - File descriptor used. + name - Joystick's name. + device - /dev/input/jsX device. + numbuttons - Joystick's buttons. + numaxes - Joystick's axes. + numhats - Joystick's hats. + statebuttons - Current state of each button. + stateaxes - Current state of each direction. +*/ +struct usbjoy { + int fd; + char name [128]; + char device [128]; + int numbuttons; + int numaxes; + int numhats; + int statebuttons[32]; + int stateaxes[4]; + joy_type type; +}; + + +/* + Function: joy_open + + Opens a USB joystick and fills its information. + + Parameters: + + joynumber - Joystick's identifier (0 reserved for GP2X's builtin Joystick). + + Returns: + + Filled usbjoy structure. +*/ +struct usbjoy * joy_open (int joynumber); + + +/* + Function: joy_name + + Returns Joystick's name. + + Parameters: + + joy - Selected joystick. + + Returns: + + Joystick's name or NULL if struct is empty. +*/ +char * joy_name (struct usbjoy * joy); + + +/* + Function: joy_device + + Returns Joystick's device. + + Parameters: + + joy - Selected joystick. + + Returns: + + Joystick's device or NULL if struct is empty. +*/ +char * joy_device (struct usbjoy * joy); + +/* + Function: joy_buttons + + Returns Joystick's buttons number. + + Parameters: + + joy - Selected joystick. + + Returns: + + Joystick's buttons or 0 if struct is empty. +*/ +int joy_buttons (struct usbjoy * joy); + +/* + Function: joy_axes + + Returns Joystick's axes number. + + Parameters: + + joy - Selected joystick. + + Returns: + + Joystick's axes or 0 if struct is empty. +*/ +int joy_axes (struct usbjoy * joy); + + +/* + Function: joy_update + + Updates Joystick's internal information ( and fields). + + Parameters: + + joy - Selected joystick. + + Returns: + + 0 - No events registered (no need to update). + 1 - Events registered (a button or axe has been pushed). + -1 - Error: struct is empty. +*/ +int joy_update (struct usbjoy * joy); + + +/* + Function: joy_getbutton + + Returns Joystick's button information. + + Parameters: + + button - Button which value you want to know (from 0 to 31). + joy - Selected joystick. + + Returns: + + 0 - Button NOT pushed. + 1 - Button pushed. + -1 - Error: struct is empty. +*/ +int joy_getbutton (int button, struct usbjoy * joy); + + +/* + Function: joy_getaxe + + Returns Joystick's axes information. + + Parameters: + + axe - Axe which value you want to know (see ). + joy - Selected joystick. + + Returns: + + 0 - Direction NOT pushed. + 1 - Direction pushed. + -1 - Error: struct is empty. +*/ +int joy_getaxe (int axe, struct usbjoy * joy); + +/* + Function: joy_close + + Closes selected joystick's file descriptor and detroys it's fields. + + Parameters: + + joy - Selected joystick. + + Returns: + + 0 - Joystick successfully closed. + -1 - Error: struct is empty. +*/ +int joy_close (struct usbjoy * joy); + + + +/* gp2x stuff */ +extern int num_of_joys; +extern struct usbjoy *joys[4]; + +void gp2x_usbjoy_update(void); +void gp2x_usbjoy_init(void); +int gp2x_usbjoy_check(int joyno); +int gp2x_usbjoy_check2(int joyno); +void gp2x_usbjoy_deinit(void); + + +#endif // USBJOY_H diff --git a/fce.c b/fce.c index 35d7209..38680f9 100644 --- a/fce.c +++ b/fce.c @@ -1092,7 +1092,7 @@ FCEUGI *FCEUI_LoadGame(char *name) int have_movie = 0; int fp; - Exit=1; + //Exit=1; ResetGameLoaded(); strncpy(name2, name, sizeof(name2)); @@ -1114,6 +1114,8 @@ FCEUGI *FCEUI_LoadGame(char *name) FCEU_fclose(fp); *p = 0; fp=FCEU_fopen(name2,"rb"); + if (!fp && p - name2 > 2) p[-2] = 0; + fp=FCEU_fopen(name2,"rb"); if (!fp) { printf("no ROM for movie\n"); return 0; @@ -1356,7 +1358,7 @@ update: if(Exit) { - CloseGame(); + //CloseGame(); break; } -- 2.39.2