From 35868d35201adb0e4066584d1145c920f5be9b03 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 7 Apr 2007 22:47:59 +0000 Subject: [PATCH] move 1 git-svn-id: file:///home/notaz/opt/svn/fceu@96 be3aeb3a-fb24-0410-a615-afba39da0efa --- drivers/gp2x/dface.h | 32 +++ drivers/gp2x/input.c | 438 +++++++++++++++++++++++++++++++++ drivers/gp2x/lnx-joystick.c | 201 +++++++++++++++ drivers/gp2x/lnx-joystick.h | 3 + drivers/gp2x/main.c | 385 +++++++++++++++++++++++++++++ drivers/gp2x/main.h | 30 +++ drivers/gp2x/minimal.c | 476 ++++++++++++++++++++++++++++++++++++ drivers/gp2x/minimal.h | 108 ++++++++ drivers/gp2x/minimal_940t.h | 96 ++++++++ drivers/gp2x/sdl-sound.c | 140 +++++++++++ drivers/gp2x/sdl-video.c | 269 ++++++++++++++++++++ drivers/gp2x/sdl-video.h | 1 + drivers/gp2x/sdl.c | 253 +++++++++++++++++++ drivers/gp2x/sdl.h | 46 ++++ drivers/gp2x/throttle.c | 110 +++++++++ drivers/gp2x/throttle.h | 2 + drivers/gp2x/unix-basedir.h | 0 drivers/gp2x/unix-netplay.c | 171 +++++++++++++ drivers/gp2x/unix-netplay.h | 5 + drivers/gp2x/usage.h | 56 +++++ 20 files changed, 2822 insertions(+) create mode 100644 drivers/gp2x/dface.h create mode 100644 drivers/gp2x/input.c create mode 100644 drivers/gp2x/lnx-joystick.c create mode 100644 drivers/gp2x/lnx-joystick.h create mode 100644 drivers/gp2x/main.c create mode 100644 drivers/gp2x/main.h create mode 100644 drivers/gp2x/minimal.c create mode 100644 drivers/gp2x/minimal.h create mode 100644 drivers/gp2x/minimal_940t.h create mode 100644 drivers/gp2x/sdl-sound.c create mode 100644 drivers/gp2x/sdl-video.c create mode 100644 drivers/gp2x/sdl-video.h create mode 100644 drivers/gp2x/sdl.c create mode 100644 drivers/gp2x/sdl.h create mode 100644 drivers/gp2x/throttle.c create mode 100644 drivers/gp2x/throttle.h create mode 100644 drivers/gp2x/unix-basedir.h create mode 100644 drivers/gp2x/unix-netplay.c create mode 100644 drivers/gp2x/unix-netplay.h create mode 100644 drivers/gp2x/usage.h diff --git a/drivers/gp2x/dface.h b/drivers/gp2x/dface.h new file mode 100644 index 0000000..92df082 --- /dev/null +++ b/drivers/gp2x/dface.h @@ -0,0 +1,32 @@ +extern CFGSTRUCT DriverConfig[]; +extern ARGPSTRUCT DriverArgs[]; +extern char *DriverUsage; + +void DoDriverArgs(void); +void GetBaseDirectory(char *BaseDirectory); + +int InitSound(void); +void WriteSound(int32 *Buffer, int Count, int NoWaiting); +void KillSound(void); +void SilenceSound(int s); /* DOS and SDL */ + + +int InitMouse(void); +void KillMouse(void); +void GetMouseData(uint32 *MouseData); + +int InitJoysticks(void); +void KillJoysticks(void); +uint32 *GetJSOr(void); + +int InitKeyboard(void); +int UpdateKeyboard(void); +char *GetKeyboard(void); +void KillKeyboard(void); + +int InitVideo(void); +void KillVideo(void); +void BlitScreen(uint8 *XBuf); +void LockConsole(void); +void UnlockConsole(void); +void ToggleFS(); /* SDL */ diff --git a/drivers/gp2x/input.c b/drivers/gp2x/input.c new file mode 100644 index 0000000..8936ec0 --- /dev/null +++ b/drivers/gp2x/input.c @@ -0,0 +1,438 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Ben Parnell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define JOY_A 1 +#define JOY_B 2 +#define JOY_SELECT 4 +#define JOY_START 8 +#define JOY_UP 0x10 +#define JOY_DOWN 0x20 +#define JOY_LEFT 0x40 +#define JOY_RIGHT 0x80 + + +#include "minimal.h" +extern int swapbuttons; +extern int stretch_offset; +extern int FSkip_setting; + +extern void SetVideoScaling(int pixels,int width,int height); +INLINE long UpdateGamepadGP2X(void); + + + +/* UsrInputType[] is user-specified. InputType[] is current + (game loading can override user settings) +*/ +static int UsrInputType[2]={SI_GAMEPAD,SI_GAMEPAD}; +static int InputType[2]; + +static int UsrInputTypeFC={SI_NONE}; +static int InputTypeFC; + +static uint32 JSreturn; +int NoWaiting=0; + +static int powerpadsc[2][12]; +static int powerpadside=0; + + +static uint32 MouseData[3]; +static uint8 fkbkeys[0x48]; +unsigned long lastpad=0; + +void FCEUD_UpdateInput(void) +{ + int t=0; + long lastpad2=lastpad; + long pad = UpdateGamepadGP2X(); + t=1; + // JSreturn=(JSreturn&0xFF000000)|(JSreturn&0xFF)|((JSreturn&0xFF0000)>>8)|((JSreturn&0xFF00)<<8); + if(gametype==GIT_FDS) + { + NoWaiting&=~1; + if ((pad & GP2X_PUSH) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_R)) && (!(lastpad2 & GP2X_PUSH))) + { + DriverInterface(DES_FDSSELECT,0); + } + else if ((pad & GP2X_L) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_PUSH)) && (!(pad & GP2X_R))&& (!(lastpad2 & GP2X_L))) + { + DriverInterface(DES_FDSINSERT,0); + } + else if ((pad & GP2X_R) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_PUSH)) && (!(lastpad2 & GP2X_R))) + { + DriverInterface(DES_FDSEJECT,0); + } + } + +} + + +//#ifdef GP2X + +extern void ResetNES(void); +extern void CleanSurface(void); + +char soundvolmeter[21]; +int soundvolIndex=0; +int L_count=0; +int R_count=0; +extern int CurrentState; +int TurboFireOff=1; +int TurboFireTop=0; // 0 is none // 1 is A & X turbo // 2 is Y & B turbo +int TurboFireBottom=0; +int turbo_toggle_A=0; +int turbo_toggle_B=0; + +static void setsoundvol(int soundvolume) +{ + //FCEUI_SetSoundVolume(soundvol); + // draw on screen :D + gp2x_sound_volume(soundvolume, soundvolume); + int meterval=soundvolume/5; + for (soundvolIndex=0; soundvolIndex < 20; soundvolIndex++) + { + if (soundvolIndex < meterval) + { + soundvolmeter[soundvolIndex]='*'; + } + else + { + soundvolmeter[soundvolIndex]='_'; + } + } + soundvolmeter[20]=0; + FCEU_DispMessage("|%s|", soundvolmeter); +} +/** + * GP2x joystick reader + * + */ +INLINE long UpdateGamepadGP2X(void) +{ + uint32 JS=0; + + unsigned long pad=gp2x_joystick_read(); +#define down(b) (pad & GP2X_##b) +#define last_down(b) (lastpad & GP2X_##b) +#define L_down (pad & GP2X_L) +#define R_down (pad & GP2X_R) +#define last_L_down (lastpad & GP2X_L) +#define last_R_down (lastpad & GP2X_R) +#define shift ((pad & GP2X_PUSH) || ((pad & (GP2X_VOL_UP|GP2X_VOL_DOWN)) == (GP2X_VOL_UP|GP2X_VOL_DOWN))) +#define last_shift ((lastpad & GP2X_PUSH) || ((lastpad & (GP2X_VOL_UP|GP2X_VOL_DOWN)) == (GP2X_VOL_UP|GP2X_VOL_DOWN))) + + if (L_down && R_down && !(pad & GP2X_PUSH) && !(last_R_down && last_L_down)) + { + ResetNES(); + puts("Reset"); + goto no_pad; + } + + if (down(VOL_UP) && !down(VOL_DOWN)) + { + soundvol+=1; + if (soundvol >= 100) soundvol=100; + //FCEUI_SetSoundVolume(soundvol); + setsoundvol(soundvol); + } + else if (down(VOL_DOWN) && !down(VOL_UP)) + { + soundvol-=1; + if (soundvol < 0) soundvol=0; + //FCEUI_SetSoundVolume(soundvol); + setsoundvol(soundvol); + } + + if (shift) + { + // only if it's something else then last time, and not moving around the joystick + if (!(pad & (GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT))) + { + if (down(SELECT)) + { + if (last_down(SELECT) && last_shift) + { + // still pressed down from stretching from last one + goto no_pad; + } + if (stretch_offset == 32) + { + stretch_offset=0; + } + else + { + stretch_offset=32; + } + + if (stretch_offset == 32) + { + SetVideoScaling(320, 320, 240); + CleanSurface(); + } + else + { + SetVideoScaling(320, 256, 240); + } + + goto no_pad; + } + else if (L_down && R_down) + { + FCEUI_CloseGame(); + puts("Quit"); + goto no_pad; + } + else if (R_down && !(last_R_down && last_shift)) + { + FCEUI_LoadState(); + goto no_pad; + } + else if (L_down && !(last_L_down && last_shift)) + { + FCEUI_SaveState(); + goto no_pad; + } + else if (down(A) && !(last_down(A) && last_shift)) + { + FSkip_setting--; + if (FSkip_setting < 0) { + FSkip_setting = -1; + FCEUI_DispMessage("Auto frameskip"); + } + else + FCEUI_DispMessage("Frameskip: %i", FSkip_setting); + goto no_pad; + } + else if (down(Y) && !(last_down(Y) && last_shift)) + { + FSkip_setting++; + if (FSkip_setting > 8) FSkip_setting = 8; + FCEUI_DispMessage("Frameskip: %i", FSkip_setting); + goto no_pad; + } + } + } + + // r is toggle savestate + if (R_down) + { + if (last_R_down) + { + R_count++; + if ((R_count & 31)== 31) + { + CurrentState=(CurrentState+1) % 10; + FCEUI_DispMessage("Now Using Save State %d", CurrentState); + } + } + } + else + { + R_count=0; + } + + // l is toggle turbo + if (L_down) + { + if (last_L_down) + { + L_count++; + if ((L_count & 31)== 31) + { + // 0 is none // 1 is Y & B turbo // 2 is X & A turbo + if ((!TurboFireTop) && (!TurboFireBottom)) + { + // was off + TurboFireTop=1; + TurboFireBottom=0; + if (swapbuttons) + { + FCEUI_DispMessage("Turbo A and Y"); + } + else + { + FCEUI_DispMessage("Turbo Y and B"); + } + } + else if (TurboFireTop) + { + TurboFireTop=0; + TurboFireBottom=1; + if (swapbuttons) + { + FCEUI_DispMessage("Turbo X and B"); + } + else + { + FCEUI_DispMessage("Turbo A and X"); + } + } + else + { + TurboFireTop=0; + TurboFireBottom=0; + FCEUI_DispMessage("Turbo Off"); + } + + } + } + } + else + { + L_count=0; + } + + //unsigned long padTmp=0; + // shift the bits in + // up + //padTmp=(pad & GP2X_UP) ; // 1 is 2^0, + JS |= ((pad & GP2X_UP) << (4-0)); // 0x10 is 2^4 + + //padTmp=(pad & GP2X_DOWN); // 0x10 is 2^4, + JS |= ((pad & GP2X_DOWN) << (5-4)); // 0x20 is 2^5 + + //padTmp=(pad & GP2X_LEFT); // 0x4 is 2^2, + JS |= ((pad & GP2X_LEFT) << (6-2)); // 0x40 is 2^6 + + //padTmp=(pad & GP2X_RIGHT); // 0x40 is 2^6, + JS |= ((pad & GP2X_RIGHT) << (7-6)); // 0x80 is 2^7 + + +#define A_down (pad & GP2X_A) +#define B_down (pad & GP2X_B) +#define X_down (pad & GP2X_X) +#define Y_down (pad & GP2X_Y) + + // should be 2 cycles held, 1 cycle release + turbo_toggle_A=(turbo_toggle_A+1) % 3; + turbo_toggle_B=(turbo_toggle_B+1) % 3; + + // 0 is none // 1 is Y & B turbo // 2 is X & A turbo + // B or X are both considered A + //padTmp=B_down >> 13; // 2^13, + + if (!(TurboFireTop && (!turbo_toggle_A))) + { + JS |= ((B_down >> 13) << 0); // 0x1 is 2^0 + } + // A or Y are both considered B + //padTmp=A_down >> 12; // 2^13, + if (!(TurboFireBottom && (!turbo_toggle_B))) + { + JS |= ((A_down >> 12) << 1); // 0x2 is 2^1 + } + + if (swapbuttons) + { + //padTmp=X_down >> 14; // 2^13, + if (!(TurboFireBottom && (!turbo_toggle_A))) + { +// JS |= ((X_down >> 14) << 0); // 0x1 is 2^0 + JS |= ((Y_down >> 15) << 0); // 0x1 is 2^0 + } + + //padTmp=Y_down >> 15; // 2^13, + if (!(TurboFireTop && (!turbo_toggle_B))) + { + JS |= ((X_down >> 14) << 1); // 0x2 is 2^1 + } + } + else + { + //padTmp=X_down >> 14; // 2^13, + if (!(TurboFireBottom && (!turbo_toggle_A))) + { + JS |= ((X_down >> 14) << 0); // 0x1 is 2^0 + } + + //padTmp=Y_down >> 15; // 2^13, + if (!(TurboFireTop && (!turbo_toggle_B))) + { + JS |= ((Y_down >> 15) << 1); // 0x2 is 2^1 + } + } + + // select + //padTmp=(pad & GP2X_SELECT) >> 9; // 0x40 is 2^9, + JS |= (((pad & GP2X_SELECT) >> 9) << 2); // 0x4 is 2^2 + + // start + //padTmp=(pad & GP2X_START) >> 8; // 2^8, + JS |= (((pad & GP2X_START) >> 8) << 3); // 0x8 is 2^3 + + + JSreturn = JS; + lastpad=pad; + + return pad; + //JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8); +no_pad: + JSreturn=0; + lastpad=pad; + return 0; +} +//#endif + + +static void InitOtherInput(void) +{ + + void *InputDPtr; + + int t; + int x; + int attrib; + + for(t=0,x=0;x<2;x++) + { + attrib=0; + InputDPtr=0; + switch(InputType[x]) + { + //case SI_POWERPAD:InputDPtr=&powerpadbuf[x];break; + case SI_GAMEPAD:InputDPtr=((uint8 *)&JSreturn)+(x<<1);break; + case SI_ARKANOID:InputDPtr=MouseData;t|=1;break; + case SI_ZAPPER:InputDPtr=MouseData; + t|=1; + attrib=1; + break; + } + FCEUI_SetInput(x,InputType[x],InputDPtr,attrib); + } + + attrib=0; + InputDPtr=0; + switch(InputTypeFC) + { + case SIFC_SHADOW:InputDPtr=MouseData;t|=1;attrib=1;break; + case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break; + case SIFC_FKB:InputDPtr=fkbkeys;break; + } + + FCEUI_SetInputFC(InputTypeFC,InputDPtr,attrib); + FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE); + + if(t && !(inited&16)) + { + InitMouse(); + inited|=16; + } +} diff --git a/drivers/gp2x/lnx-joystick.c b/drivers/gp2x/lnx-joystick.c new file mode 100644 index 0000000..4c2ae6a --- /dev/null +++ b/drivers/gp2x/lnx-joystick.c @@ -0,0 +1,201 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Ben Parnell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include "main.h" +#include "lnx-joystick.h" + +int joy[4]={0,0,0,0}; +int joyBMap[4][4]; + +static int32 joybuttons[4]={0,0,0,0}; +static int32 joyx[4]={0,0,0,0}; +static int32 joyy[4]={0,0,0,0}; + +static void ConfigJoystick(int z); +static int fd[4]; + +#define JOY_A 1 +#define JOY_B 2 +#define JOY_SELECT 4 +#define JOY_START 8 +#define JOY_UP 0x10 +#define JOY_DOWN 0x20 +#define JOY_LEFT 0x40 +#define JOY_RIGHT 0x80 + +static void UpdateJoyData(int x) +{ + struct js_event e; + + while(read(fd[x],&e,sizeof(struct js_event))==sizeof(struct js_event)) + { + e.type&=~JS_EVENT_INIT; + if(e.type==JS_EVENT_BUTTON) + { + if(e.value) + joybuttons[x]|=(1<=16383) ret|=JOY_RIGHT<<(x<<3); + if(joyy[x]<=-16383) ret|=JOY_UP<<(x<<3); + else if(joyy[x]>=16383) ret|=JOY_DOWN<<(x<<3); + } + return ret; +} + +void KillJoysticks(void) +{ + int x; + for(x=0;x<4;x++) + if(joy[x]) + close(fd[x]); +} + +int InitJoysticks(void) +{ + char dbuf[64]; + int version; + int z; + + for(z=0;z<4;z++) + { + if(!joy[z]) continue; + sprintf(dbuf,"/dev/js%d",joy[z]-1); + if((fd[z]=open(dbuf,O_RDONLY|O_NONBLOCK))<0) + { + printf("Could not open %s.\n",dbuf); + joy[z]=0; + continue; + } + + if(ioctl(fd[z], JSIOCGVERSION, &version)==-1) + { + printf("Error using ioctl JSIOCGVERSION on %s.\n",dbuf); + joy[z]=0; + close(fd[z]); + continue; + } + + if(!(joyBMap[z][0]|joyBMap[z][1]|joyBMap[z][2]|joyBMap[z][3])) + ConfigJoystick(z); + } + + return(joy[0]|joy[1]|joy[2]|joy[3]); +} + +#define WNOINPUT(); for(;;){uint8 t; if(read(fileno(stdin),&t,1)==-1) \ + {break;}} + +static void BConfig(int z,int b) +{ + WNOINPUT(); + for(;;) + { + uint8 t; + if(read(fileno(stdin),&t,1)==-1) + { + if(errno!=EAGAIN) break; + } + else + break; + + { + struct js_event e; + + while(read(fd[z],&e,sizeof(struct js_event))==sizeof(struct js_event)) + { + if(e.type==JS_EVENT_BUTTON) + { + if(!e.value) + { + joyBMap[z][b]=1< +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "main.h" +#include "throttle.h" + +#include "../common/config.h" +#include "../common/args.h" +#include "../common/unixdsp.h" +#include "../common/cheat.h" + +#include "dface.h" + +static int ntsccol=0,ntschue=-1,ntsctint=-1; +int soundvol=70; +int inited=0; +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; + + +static char BaseDirectory[2048]; + +int eoptions=0; + +static void DriverKill(void); +static int DriverInitialize(void); + +static int gametype; +#include "input.c" + +static void ParseGI(FCEUGI *gi) +{ + gametype=gi->type; + + InputType[0]=UsrInputType[0]; + InputType[1]=UsrInputType[1]; + InputTypeFC=UsrInputTypeFC; + + if(gi->input[0]>=0) + InputType[0]=gi->input[0]; + if(gi->input[1]>=0) + InputType[1]=gi->input[1]; + if(gi->inputfc>=0) + InputTypeFC=gi->inputfc; + FCEUI_GetCurrentVidSystem(&srendline,&erendline); +} + +void FCEUD_PrintError(char *s) +{ + puts(s); +} + +static char *cpalette=0; +static void LoadCPalette(void) +{ + char tmpp[192]; + FILE *fp; + + if(!(fp=fopen(cpalette,"rb"))) + { + printf(" Error loading custom palette from file: %s\n",cpalette); + return; + } + fread(tmpp,1,192,fp); + FCEUI_SetPaletteArray((uint8 *)tmpp); + fclose(fp); +} + +static CFGSTRUCT fceuconfig[]={ + AC(soundvol), + ACS(cpalette), + AC(ntsctint), + AC(ntschue), + AC(ntsccol), + AC(UsrInputTypeFC), + ACA(UsrInputType), + AC(powerpadside), + AC(powerpadsc), + AC(eoptions), + ACA(srendlinev), + ACA(erendlinev), + ADDCFGSTRUCT(DriverConfig), + ENDCFGSTRUCT +}; + +static void SaveConfig(void) +{ + char tdir[2048]; + sprintf(tdir,"%s"PSS"fceu.cfg",BaseDirectory); + DriverInterface(DES_GETNTSCTINT,&ntsctint); + DriverInterface(DES_GETNTSCHUE,&ntschue); + SaveFCEUConfig(tdir,fceuconfig); +} + +static void LoadConfig(void) +{ + char tdir[2048]; + sprintf(tdir,"%s"PSS"fceu.cfg",BaseDirectory); + LoadFCEUConfig(tdir,fceuconfig); + if(ntsctint>=0) DriverInterface(DES_SETNTSCTINT,&ntsctint); + if(ntschue>=0) DriverInterface(DES_SETNTSCHUE,&ntschue); +} + +static void CreateDirs(void) +{ + char *subs[5]={"fcs","snaps","gameinfo","sav","cheats"}; + char tdir[2048]; + int x; + + mkdir(BaseDirectory,S_IRWXU); + for(x=0;x<5;x++) + { + sprintf(tdir,"%s"PSS"%s",BaseDirectory,subs[x]); + mkdir(tdir,S_IRWXU); + } +} + +static void SetSignals(void (*t)(int)) +{ + int sigs[11]={SIGINT,SIGTERM,SIGHUP,SIGPIPE,SIGSEGV,SIGFPE,SIGKILL,SIGALRM,SIGABRT,SIGUSR1,SIGUSR2}; + int x; + for(x=0;x<11;x++) + signal(sigs[x],t); +} + +static void CloseStuff(int signum) +{ + DriverKill(); + printf("\nSignal %d has been caught and dealt with...\n",signum); + switch(signum) + { + case SIGINT:printf("How DARE you interrupt me!\n");break; + case SIGTERM:printf("MUST TERMINATE ALL HUMANS\n");break; + case SIGHUP:printf("Reach out and hang-up on someone.\n");break; + case SIGPIPE:printf("The pipe has broken! Better watch out for floods...\n");break; + case SIGSEGV:printf("Iyeeeeeeeee!!! A segmentation fault has occurred. Have a fluffy day.\n");break; + /* So much SIGBUS evil. */ + #ifdef SIGBUS + #if(SIGBUS!=SIGSEGV) + case SIGBUS:printf("I told you to be nice to the driver.\n");break; + #endif + #endif + case SIGFPE:printf("Those darn floating points. Ne'er know when they'll bite!\n");break; + case SIGALRM:printf("Don't throw your clock at the meowing cats!\n");break; + case SIGABRT:printf("Abort, Retry, Ignore, Fail?\n");break; + case SIGUSR1: + case SIGUSR2:printf("Killing your processes is not nice.\n");break; + } + exit(1); +} + +static void DoArgs(int argc, char *argv[]) +{ + static char *cortab[5]={"none","gamepad","zapper","powerpad","arkanoid"}; + static int cortabi[5]={SI_NONE,SI_GAMEPAD, + SI_ZAPPER,SI_POWERPAD,SI_ARKANOID}; + static char *fccortab[5]={"none","arkanoid","shadow","4player","fkb"}; + static int fccortabi[5]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW, + SIFC_4PLAYER,SIFC_FKB}; + + int x; + static char *inputa[2]={0,0}; + static char *fcexp=0; + static int docheckie[4]; + + static ARGPSTRUCT FCEUArgs[]={ + {"-soundvol",0,&soundvol,0}, + {"-cpalette",0,&cpalette,0x4001}, + + {"-ntsccol",0,&ntsccol,0}, + {"-pal",&docheckie[0],0,0}, + {"-input1",0,&inputa[0],0x4001},{"-input2",0,&inputa[1],0x4001}, + {"-fcexp",0,&fcexp,0x4001}, + + {"-gg",&docheckie[1],0,0}, + {"-no8lim",0,&eoptions,0x8001}, + {"-subase",0,&eoptions,0x8002}, + {"-snapname",0,&eoptions,0x8000|EO_SNAPNAME}, + {"-nofs",0,&eoptions,0x8000|EO_NOFOURSCORE}, + {"-clipsides",0,&eoptions,0x8000|EO_CLIPSIDES}, + {"-nothrottle",0,&eoptions,0x8000|EO_NOTHROTTLE}, + {"-slstart",0,&srendlinev[0],0},{"-slend",0,&erendlinev[0],0}, + {"-slstartp",0,&srendlinev[1],0},{"-slendp",0,&erendlinev[1],0}, + {"-swapbuttons",&swapbuttons, 0, 0}, + {"-showfps",&showfps, 0, 0}, + {0,(void *)DriverArgs,0,0}, + {0,0,0,0} + }; + + memset(docheckie,0,sizeof(docheckie)); + ParseArguments(argc, argv, FCEUArgs); + if(cpalette) + { + if(cpalette[0]=='0') + if(cpalette[1]==0) + { + free(cpalette); + cpalette=0; + } + } + if(docheckie[0]) + FCEUI_SetVidSystem(1); + if(docheckie[1]) + FCEUI_SetGameGenie(1); + FCEUI_DisableSpriteLimitation(1); + FCEUI_SaveExtraDataUnderBase(eoptions&2); + FCEUI_SetSnapName(eoptions&EO_SNAPNAME); + + for(x=0;x<2;x++) + { + if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0; + if(erendlinev[x]239) erendlinev[x]=239; + } + + printf("main() setrendered lines: %d, %d, %d, %d\n",srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]); + printf("main() clip sides %d\n", eoptions&EO_CLIPSIDES); + srendlinev[0]=0; + FCEUI_SetRenderedLines(srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]); + FCEUI_SetRenderedLines(0,erendlinev[0],srendlinev[1],erendlinev[1]); + FCEUI_SetSoundVolume(soundvol); + DriverInterface(DES_NTSCCOL,&ntsccol); + DoDriverArgs(); + + if(fcexp) + { + int y; + for(y=0;y<5;y++) + { + if(!strncmp(fccortab[y],fcexp,8)) + { + UsrInputTypeFC=fccortabi[y]; + break; + } + } + free(fcexp); + } + for(x=0;x<2;x++) + { + int y; + + if(!inputa[x]) + continue; + + for(y=0;y<5;y++) + { + if(!strncmp(cortab[y],inputa[x],8)) + { + UsrInputType[x]=cortabi[y]; + if(y==3) + { + powerpadside&=~(1<>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; } + + +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; +} + +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)]; +} */ + + + + 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]; + } +} + +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); +} + +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; + + 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); + + // don't run sound right now + if ( gp2x_do_sound) + { + if(!gp2x_dev[3]) gp2x_dev[3] = open("/dev/dsp", O_WRONLY); + 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); } + + ioctl(gp2x_dev[gp2x_physvram[7]=0], FBIOGET_FSCREENINFO, &fixed_info); + gp2x_screen15=gp2x_logvram15[2]=gp2x_logvram15[0]=(unsigned short *)mmap(0, 320*240*2, PROT_WRITE, MAP_SHARED, gp2x_dev[0], 0); + gp2x_screen8=(unsigned char *)gp2x_screen15; + gp2x_physvram[2]=gp2x_physvram[0]=fixed_info.smem_start; + + ioctl(gp2x_dev[1], FBIOGET_FSCREENINFO, &fixed_info); + gp2x_logvram15[3]=gp2x_logvram15[1]=(unsigned short *)mmap(0, 320*240*2, PROT_WRITE, MAP_SHARED, gp2x_dev[1], 0); + gp2x_physvram[3]=gp2x_physvram[1]=fixed_info.smem_start; + + 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 ( 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); + + + printf("minimal() do sound, rate %d, bits %d, stereo %d, frag %d\n", rate, bits, stereo, frag); + + 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); + + 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; + + int bpp=(gp2x_memregs[0x28DA>>1]>>9)&0x3; /* bytes per pixel */ + + 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 */ +} diff --git a/drivers/gp2x/minimal.h b/drivers/gp2x/minimal.h new file mode 100644 index 0000000..53127b9 --- /dev/null +++ b/drivers/gp2x/minimal.h @@ -0,0 +1,108 @@ +/* + + 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 +#include +#include + +#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() + +#endif + diff --git a/drivers/gp2x/minimal_940t.h b/drivers/gp2x/minimal_940t.h new file mode 100644 index 0000000..82cd1c0 --- /dev/null +++ b/drivers/gp2x/minimal_940t.h @@ -0,0 +1,96 @@ +/* + + 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/sdl-sound.c b/drivers/gp2x/sdl-sound.c new file mode 100644 index 0000000..6693222 --- /dev/null +++ b/drivers/gp2x/sdl-sound.c @@ -0,0 +1,140 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdl.h" +#include "minimal.h" + +#define GP2X_SOUND 1 + +extern void pthread_yield(void); +extern void FCEUI_FrameSkip(int x); + +//extern int dosound; +extern int soundvol; + +// always have this call +INLINE void gp2x_sound_frame(void *blah, void *buff, int samples) + { +} + + + + + +//static int sexy_in_function=0; +#define NumSexyBufferBuffers 2 +struct timespec gp2x_sleep_ts; +int firstentry=1; +//int firstprint=1; +struct timeval sleeptimer; + + + +pthread_t gp2x_sexy_sound_thread=0; +int** SexyBufferBuffers=NULL; +int SexyBufferBufferCounts[NumSexyBufferBuffers]; +int gp2x_sound_inited=0; +int gp2x_in_sound_thread=0; +extern unsigned long gp2x_dev[8]; + +pthread_cond_t gp2x_sound_cond=PTHREAD_COND_INITIALIZER; +pthread_mutex_t gp2x_sound_mutex = PTHREAD_MUTEX_INITIALIZER; +int zzdebug01_entry=0; +int zzdebug01_wait=0; +int hasSound=0; +extern unsigned long fps; +extern unsigned long avg_fps; +extern unsigned long ticks; + +int throttlecount=0; + +void WriteSound(int32 *Buffer, int Count) + { + write(gp2x_dev[3], Buffer, Count<<1); + pthread_yield(); + SpeedThrottle(); + } + +void* gp2x_write_sound(void* blah) + { + gp2x_in_sound_thread=1; + { + if (hasSound) + { + hasSound=0; + } + else + { + } + + } + gp2x_in_sound_thread=0; + return NULL; +} + +void SilenceSound(int n) +{ + soundvol=0; +} + +int InitSound(FCEUGI *gi) +{ + Settings.sound=22050; + FCEUI_Sound(Settings.sound); + gp2x_sound_volume(soundvol, soundvol); + printf("InitSound() sound_rate: %d\n", Settings.sound); + if(firstentry) + { + firstentry=0; + gp2x_sound_inited=1; + } + return 1 ; +} + +uint32 GetMaxSound(void) +{ + return(4096); +} + +uint32 GetWriteSound(void) + { + return 1024; +} + +int KillSound(void) +{ + FCEUI_Sound(0); + gp2x_sound_inited=0; + + return 1; +} + + + + diff --git a/drivers/gp2x/sdl-video.c b/drivers/gp2x/sdl-video.c new file mode 100644 index 0000000..9a4e787 --- /dev/null +++ b/drivers/gp2x/sdl-video.c @@ -0,0 +1,269 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "sdl.h" +//#include "../common/vidblit.h" + + +#include "minimal.h" + +extern int showfps; + +static char fps_str[32]; +static int framesEmulated, framesRendered; + +int stretch_offset=32; +int paletterefresh; + +#define FPS_COLOR 61 + + +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; + slen=strlen(text); + + screen=screen+x+y*320; + + for (i=0;i> 8); + *b = (uint8) gp2x_palette[(index << 1) + 0]; +} + + +static INLINE void printFps(uint8 *screen) +{ + struct timeval tv_now; + static int prevsec, needfpsflip = 0; + + gettimeofday(&tv_now, 0); + if (prevsec != tv_now.tv_sec) + { + sprintf(fps_str, "%i/%i", framesRendered, framesEmulated); + framesEmulated = framesRendered = 0; + needfpsflip = 4; + prevsec = tv_now.tv_sec; + } + + if (stretch_offset > 0) + { + if (needfpsflip) + { + int y, *destt = (int *) screen; + for (y = 240; y; y--) + { + *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; + *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; + destt += 64; + + *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; + *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; + } + if (showfps) + { + fps_str[2] = 0; + gp2x_text(screen, 0, 0, fps_str, FPS_COLOR, 0); + gp2x_text(screen, 0, 10, fps_str+3, FPS_COLOR, 0); + } + needfpsflip--; + } + } + else + { + if (showfps) + { + gp2x_text(screen, 0, 0, fps_str, FPS_COLOR, 0); + } + } +} + + +void BlitScreen(uint8 * XBuf) +{ + int x, y, yinc; + + framesEmulated++; + + if (!XBuf) return; + + framesRendered++; + +#if 1 // 48->54 + y=240; + yinc=272*(y-1); + while (y--) + { + int* dest=(int *) (gp2x_screen8+((y << 8) + (y << 6))+stretch_offset); + + int* src=(int *) (XBuf+yinc); + x=64; + while (x--) + { + dest[x]=src[x]; + } + yinc-=272; + } + + if (paletterefresh) + { + gp2x_video_setpalette(); + paletterefresh = 0; + } +#endif + printFps(gp2x_screen8); + gp2x_video_flip(); +} + + diff --git a/drivers/gp2x/sdl-video.h b/drivers/gp2x/sdl-video.h new file mode 100644 index 0000000..036c933 --- /dev/null +++ b/drivers/gp2x/sdl-video.h @@ -0,0 +1 @@ +uint32 PtoV(uint16 x, uint16 y); diff --git a/drivers/gp2x/sdl.c b/drivers/gp2x/sdl.c new file mode 100644 index 0000000..7826c8c --- /dev/null +++ b/drivers/gp2x/sdl.c @@ -0,0 +1,253 @@ +#include +#include +#include +#include + +#include "sdl.h" +#include "sdl-video.h" +#ifdef NETWORK +#include "unix-netplay.h" +#endif +#include "minimal.h" +//extern int soundvol; +int CLImain(int argc, char *argv[]); +extern int gp2x_in_sound_thread; +extern void pthread_yield(void); +extern void SetVideoScaling(int, int, int); + +//#define SOUND_RATE 44100 +#define SOUND_RATE 22050 + +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), + 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\ +-sound x Sound.\n\ + 0 = Disabled.\n\ + Otherwise, x = playback rate.\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 +"-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."; + +#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 + #ifdef NETWORK + {"-connect",&docheckie[0],&netplayhost,0x4001}, + {"-server",&docheckie[1],0,0}, + {"-netport",0,&Port,0}, + #endif + {0,0,0,0} +}; + + + + + +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"); + } +} + +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)); +} + +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; + else if(docheckie[1]) + netplay=1; + + if(netplay) + FCEUI_SetNetworkPlay(netplay); + #endif + + for(x=0;x<4;x++) + if(!joy[x]) + { + memset(joyBMap[x],0,sizeof(joyBMap[0])); + memset(joyAMap[x],0,sizeof(joyAMap[0])); + } +} +int InitMouse(void) +{ + return(0); +} +void KillMouse(void){} +void GetMouseData(uint32 *d) +{ +} + +int InitKeyboard(void) +{ + return(1); +} + +int UpdateKeyboard(void) +{ + return(1); +} + +void KillKeyboard(void) +{ + +} + +char *GetKeyboard(void) +{ + return NULL; +} + +#include "unix-basedir.h" +extern int showfps; +extern int swapbuttons; + +int main(int argc, char *argv[]) +{ + + puts("Starting GPFCE - Port version 0.2 05-29-2006"); + puts("Based on FCE Ultra "VERSION_STRING"..."); + puts("Ported by Zheng Zhu\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); + + SetDefaults(); + int ret=CLImain(argc,argv); + + // unscale the screen, in case this is bad. + SetVideoScaling(320, 320, 240); + + gp2x_deinit(); + // make sure sound thread has exited cleanly + while (gp2x_in_sound_thread) pthread_yield(); + printf("Sound thread exited\n"); + 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); +} + diff --git a/drivers/gp2x/sdl.h b/drivers/gp2x/sdl.h new file mode 100644 index 0000000..7882e5b --- /dev/null +++ b/drivers/gp2x/sdl.h @@ -0,0 +1,46 @@ +#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; +} 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 + +#define joyAMap Settings.joyAMap +#define joyBMap Settings.joyBMap +#define joy Settings.joy diff --git a/drivers/gp2x/throttle.c b/drivers/gp2x/throttle.c new file mode 100644 index 0000000..81cd916 --- /dev/null +++ b/drivers/gp2x/throttle.c @@ -0,0 +1,110 @@ +#include +#include "main.h" +#include "throttle.h" + +#if 0 +static uint64 tfreq; +static uint64 desiredfps; + +void RefreshThrottleFPS(void) +{ + uint64 f=FCEUI_GetDesiredFPS(); + // great, a bit faster than before + //f = (f*65) >> 6; + desiredfps=f>>8; + tfreq=1000000; + tfreq<<=16; /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */ +} + +static uint64 GetCurTime(void) +{ + uint64 ret; + struct timeval tv; + + gettimeofday(&tv,0); + ret=(uint64)tv.tv_sec*1000000; + ret+=tv.tv_usec; + return(ret); +} + +INLINE void SpeedThrottle(void) +{ + static uint64 ttime,ltime; + + waiter: + + ttime=GetCurTime(); + + if( (ttime-ltime) < (tfreq/desiredfps) ) + { + goto waiter; + } + if( (ttime-ltime) >= (tfreq*4/desiredfps)) + ltime=ttime; + else + ltime+=tfreq/desiredfps; +} + +#else + +extern uint8 PAL; +extern int FSkip, FSkip_setting; +static int usec_aim = 0, usec_done = 0; +static int skip_count = 0; + +INLINE void SpeedThrottle(void) +{ + static struct timeval tv_prev; + struct timeval tv_now; + int delta_nom = PAL ? 19997 : 16639; // ~50.007, 19.997 ms/frame : ~60.1, 16.639 ms/frame + + + if (usec_done == 0) { // first time + usec_done = 1; + gettimeofday(&tv_prev, 0); + return; + } + + gettimeofday(&tv_now, 0); + + usec_aim += delta_nom; + if (tv_now.tv_sec != tv_prev.tv_sec) + usec_done += 1000000; + usec_done += tv_now.tv_usec - tv_prev.tv_usec; + +#ifdef FRAMESKIP + if (FSkip_setting >= 0) + { + if (skip_count >= FSkip_setting) + skip_count = 0; + else { + skip_count++; + FSkip = 1; + } + } + else if (usec_done > usec_aim) + { + /* auto frameskip */ + if (usec_done - usec_aim > 150000) + usec_done = usec_aim = 0; // too much behind, try to recover.. + FSkip = 1; + tv_prev = tv_now; + return; + } +#endif + + tv_prev = tv_now; + while (usec_done < usec_aim) + { + gettimeofday(&tv_now, 0); + + if (tv_now.tv_sec != tv_prev.tv_sec) + usec_done += 1000000; + usec_done += tv_now.tv_usec - tv_prev.tv_usec; + tv_prev = tv_now; + } + usec_done = usec_done - usec_aim + 1; // reset to prevent overflows + usec_aim = 0; +} +#endif + diff --git a/drivers/gp2x/throttle.h b/drivers/gp2x/throttle.h new file mode 100644 index 0000000..0ea9365 --- /dev/null +++ b/drivers/gp2x/throttle.h @@ -0,0 +1,2 @@ +void RefreshThrottleFPS(void); +INLINE void SpeedThrottle(void); diff --git a/drivers/gp2x/unix-basedir.h b/drivers/gp2x/unix-basedir.h new file mode 100644 index 0000000..e69de29 diff --git a/drivers/gp2x/unix-netplay.c b/drivers/gp2x/unix-netplay.c new file mode 100644 index 0000000..8e777db --- /dev/null +++ b/drivers/gp2x/unix-netplay.c @@ -0,0 +1,171 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Ben Parnell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef socklen_t +#define socklen_t int +#endif +#ifdef NETWORK +static int Socket=-1; +#endif +#include "main.h" +#include "unix-netplay.h" + +char *netplayhost=0; +int Port=0xFCE; +int netplay=0; + +int FCEUD_NetworkConnect(void) +{ +#ifdef NETWORK + struct sockaddr_in sockn; + int TSocket; + + memset(&sockn,0,sizeof(sockn)); + sockn.sin_family=AF_INET; + sockn.sin_port=htons(Port); + + if((TSocket=socket(AF_INET, SOCK_STREAM, 0))<0) + { + puts("Error creating socket."); + return(0); + } + + if(netplay==1) /* Be a server. */ + { + sockn.sin_addr.s_addr=INADDR_ANY; + if(bind(TSocket, (struct sockaddr *)&sockn, sizeof(sockn))<0) + { + close(TSocket); + puts("Error binding to socket."); + return(0); + } + if(listen(TSocket, 1)<0) + { + puts("Error listening on socket."); + close(TSocket); + return(0); + } + { + socklen_t len=sizeof(sockn); + + printf("Accepting connection on port %d...\n",Port); + if((Socket=accept(TSocket,(struct sockaddr *)&sockn,&len))<0 ) + { + puts("Error accepting a connection."); + close(TSocket); + return(0); + } + close(TSocket); + } + + } + else /* Connect as a client if not a server. */ + { + struct hostent *Host; + + if((sockn.sin_addr.s_addr=inet_addr(netplayhost))==INADDR_NONE) + { + if(!(Host=gethostbyname(netplayhost))) + { + puts("Error getting network host entry."); + return(0); + } + memcpy(&sockn.sin_addr,Host->h_addr,Host->h_length); + } + printf("Attempting to connect to %s...\n",netplayhost); + if( connect(TSocket, (struct sockaddr *)&sockn, sizeof(sockn)) <0 ) + { + puts("Error connecting to remote host."); + close(TSocket); + return(0); + } + Socket=TSocket; + } +#endif + return(1); +} + +/* 0 on failure, 1 on success, -1 if it would block and blocking is not + specified. +*/ + +int FCEUD_NetworkRecvData(uint8 *data, uint32 len, int block) +{ +#ifdef NETWORK + if(block) + { + int t; + uint8 temp[32]; + t=recv(Socket,temp,32,MSG_PEEK|MSG_DONTWAIT); + if(t==-1) + { + if(errno!=EAGAIN) return(0); + } + else if(t==32) + NoWaiting|=2; + else + NoWaiting&=~2; + return(recv(Socket,data,len,0)==len); + } + else + { + int t=recv(Socket,data,len,MSG_DONTWAIT); + if(t==-1) + { + if(errno==EAGAIN) // Would block + return(-1); + return(0); + } + return(1); + } +#else + return 1; +#endif +} + +/* 0 on failure, 1 on success. This function should always block. */ + +int FCEUD_NetworkSendData(uint8 *Value, uint32 len) +{ +#ifdef NETWORK + return(send(Socket,Value,len,0)==len); +#else + return 0; +#endif +} + +void FCEUD_NetworkClose(void) +{ +#ifdef NETWORK + if(Socket>0) + close(Socket); + Socket=-1; +#endif +} + diff --git a/drivers/gp2x/unix-netplay.h b/drivers/gp2x/unix-netplay.h new file mode 100644 index 0000000..48769f6 --- /dev/null +++ b/drivers/gp2x/unix-netplay.h @@ -0,0 +1,5 @@ +extern char *netplayhost; +extern int Port; +extern int FDnetplay; +#define netplay FDnetplay + diff --git a/drivers/gp2x/usage.h b/drivers/gp2x/usage.h new file mode 100644 index 0000000..425a907 --- /dev/null +++ b/drivers/gp2x/usage.h @@ -0,0 +1,56 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Ben Parnell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void ShowUsage(char *prog) +{ +printf("\nUsage is as follows:\n%s filename\n\n",prog); +puts("Options:"); +puts(DriverUsage); +puts("-cpalette x Load a custom global palette from file x.\n\ +-ntsccol x Emulate an NTSC's TV's colors.\n\ + 0 = Disabled.\n\ + 1 = Enabled.\n\ +-pal Emulate a PAL NES.\n\ +-soundvol x Sound volume. x is an integral percentage value.\n\ +-inputx str Select device mapped to virtual input port x(1-2).\n\ + str may be: none, gamepad, zapper, powerpada, powerpadb,\n\ + arkanoid\n\ +-fcexp str Select Famicom expansion port device.\n\ + str may be: none, shadow, arkanoid, 4player, fkb\n\ +-nofs x Disables Four-Score emulation if x is 1.\n\ +-gg Enable Game Genie emulation.\n\ +-no8lim x Disables the 8 sprites per scanline limitation.\n\ + 0 = Limitation enabled.\n\ + 1 = Limitation disabled.\n\ +-subase x Save extra game data files under the base directory if enabled.\n\ + 0 = Disabled.\n\ + 1 = Enabled.\n\ +-snapname x Selects what type of file name snapshots will have.\n\ + 0 = Numeric(0.png)\n\ + 1 = File base and numeric(mario-0.png)\n\ +-nothrottle x Disable artificial speed throttling if x is non-zero.\n\ +-clipsides x Clip leftmost and rightmost 8 columns of pixels of video output.\n\ + 0 = No clipping.\n\ + 1 = Clipping.\n\ +-slstart x Set the first drawn emulated scanline. Valid values for x are\n\ + 0 through 239.\n\ +-slend x Set the last drawn emulated scanline. Valid values for x are\n\ + 0 through 239."); +} -- 2.39.5