From 71fe9d66629ef0c8f4368c49597b13ab2efeeabd Mon Sep 17 00:00:00 2001 From: no-author Date: Sun, 23 Jul 2006 03:37:43 +0000 Subject: [PATCH] Added sdl stuff from the attic --- drivers/pc/dface.h | 72 ++++ drivers/pc/dos-joystick.c | 200 +++++++++++ drivers/pc/dos-joystick.h | 27 ++ drivers/pc/dos-keyboard.c | 131 +++++++ drivers/pc/dos-mouse.c | 80 +++++ drivers/pc/dos-sound.c | 567 ++++++++++++++++++++++++++++++ drivers/pc/dos-sound.h | 26 ++ drivers/pc/dos-video.c | 246 +++++++++++++ drivers/pc/dos-video.h | 22 ++ drivers/pc/dos.c | 128 +++++++ drivers/pc/dos.h | 27 ++ drivers/pc/input.c | 720 ++++++++++++++++++++++++++++++++++++++ drivers/pc/input.h | 38 ++ drivers/pc/keyscan.h | 161 +++++++++ drivers/pc/main.c | 553 +++++++++++++++++++++++++++++ drivers/pc/main.h | 55 +++ drivers/pc/sdl-icon.h | 134 +++++++ drivers/pc/sdl-joystick.c | 99 ++++++ drivers/pc/sdl-netplay.c | 224 ++++++++++++ drivers/pc/sdl-netplay.h | 0 drivers/pc/sdl-opengl.c | 241 +++++++++++++ drivers/pc/sdl-opengl.h | 6 + drivers/pc/sdl-sound.c | 373 ++++++++++++++++++++ drivers/pc/sdl-throttle.c | 86 +++++ drivers/pc/sdl-video.c | 432 +++++++++++++++++++++++ drivers/pc/sdl-video.h | 1 + drivers/pc/sdl.c | 429 +++++++++++++++++++++++ drivers/pc/sdl.h | 50 +++ drivers/pc/throttle.c | 41 +++ drivers/pc/throttle.h | 2 + drivers/pc/unix-netplay.c | 292 ++++++++++++++++ drivers/pc/unix-netplay.h | 9 + drivers/pc/usage.h | 60 ++++ drivers/pc/vgatweak.c | 168 +++++++++ 34 files changed, 5700 insertions(+) create mode 100644 drivers/pc/dface.h create mode 100644 drivers/pc/dos-joystick.c create mode 100644 drivers/pc/dos-joystick.h create mode 100644 drivers/pc/dos-keyboard.c create mode 100644 drivers/pc/dos-mouse.c create mode 100644 drivers/pc/dos-sound.c create mode 100644 drivers/pc/dos-sound.h create mode 100644 drivers/pc/dos-video.c create mode 100644 drivers/pc/dos-video.h create mode 100644 drivers/pc/dos.c create mode 100644 drivers/pc/dos.h create mode 100644 drivers/pc/input.c create mode 100644 drivers/pc/input.h create mode 100644 drivers/pc/keyscan.h create mode 100644 drivers/pc/main.c create mode 100644 drivers/pc/main.h create mode 100644 drivers/pc/sdl-icon.h create mode 100644 drivers/pc/sdl-joystick.c create mode 100644 drivers/pc/sdl-netplay.c create mode 100644 drivers/pc/sdl-netplay.h create mode 100644 drivers/pc/sdl-opengl.c create mode 100644 drivers/pc/sdl-opengl.h create mode 100644 drivers/pc/sdl-sound.c create mode 100644 drivers/pc/sdl-throttle.c create mode 100644 drivers/pc/sdl-video.c create mode 100644 drivers/pc/sdl-video.h create mode 100644 drivers/pc/sdl.c create mode 100644 drivers/pc/sdl.h create mode 100644 drivers/pc/throttle.c create mode 100644 drivers/pc/throttle.h create mode 100644 drivers/pc/unix-netplay.c create mode 100644 drivers/pc/unix-netplay.h create mode 100644 drivers/pc/usage.h create mode 100644 drivers/pc/vgatweak.c diff --git a/drivers/pc/dface.h b/drivers/pc/dface.h new file mode 100644 index 00000000..9981bd08 --- /dev/null +++ b/drivers/pc/dface.h @@ -0,0 +1,72 @@ +#ifdef __cplusplus +extern "C" { +#endif +#include "../common/args.h" +#include "../common/config.h" + +#include "input.h" + +extern FCEUGI *CurGame; + +extern CFGSTRUCT DriverConfig[]; +extern ARGPSTRUCT DriverArgs[]; +extern char *DriverUsage; + +void DoDriverArgs(void); +uint8 *GetBaseDirectory(void); + +int InitSound(FCEUGI *gi); +void WriteSound(int32 *Buffer, int Count); +int KillSound(void); +uint32 GetMaxSound(void); +uint32 GetWriteSound(void); + +void SilenceSound(int s); /* DOS and SDL */ + + +int InitMouse(void); +void KillMouse(void); +void GetMouseData(uint32 *MouseData); + +int InitJoysticks(void); +int KillJoysticks(void); +uint32 *GetJSOr(void); + +int InitKeyboard(void); +int UpdateKeyboard(void); +char *GetKeyboard(void); +void KillKeyboard(void); + +int InitVideo(FCEUGI *gi); +int KillVideo(void); +void BlitScreen(uint8 *XBuf); +void LockConsole(void); +void UnlockConsole(void); +void ToggleFS(); /* SDL */ + +int LoadGame(const char *path); +int CloseGame(void); +int GUI_Init(int argc, char **argv, int (*dofunc)(void)); +int GUI_Idle(void); +int GUI_Update(void); +void GUI_Hide(int); +void GUI_RequestExit(void); +int GUI_SetVideo(int fullscreen, int width, int height); +char *GUI_GetKeyboard(void); +void GUI_GetMouseState(uint32 *b, int *x, int *y); + +void UpdatePhysicalInput(void); +int DTestButton(ButtConfig *bc); +int DWaitButton(const uint8 *text, ButtConfig *bc, int wb); +int ButtonConfigBegin(void); +void ButtonConfigEnd(void); + +void Giggles(int); +void DoFun(void); + +int FCEUD_NetworkConnect(void); +#ifdef __cplusplus +} +#endif + + diff --git a/drivers/pc/dos-joystick.c b/drivers/pc/dos-joystick.c new file mode 100644 index 00000000..05e18177 --- /dev/null +++ b/drivers/pc/dos-joystick.c @@ -0,0 +1,200 @@ +/* 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 + +#include "dos.h" +#include "dos-joystick.h" + +#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 + +int joy=0; +int joyBMap[6]; + +static int32 joybuttons=0; +static uint32 joyx=0; +static uint32 joyy=0; +static uint32 joyxcenter; +static uint32 joyycenter; + +static void ConfigJoystick(void); +volatile int soundjoyer=0; +volatile int soundjoyeron=0; + +/* Crude method to detect joystick. */ +static int DetectJoystick(void) +{ + uint8 b; + + outportb(0x201,0); + b=inportb(0x201); + sleep(1); + if((inportb(0x201)&3)==(b&3)) + return 0; + else + return 1; +} + +void UpdateJoyData(void) +{ + uint32 xc,yc; + + + joybuttons=((inportb(0x201)&0xF0)^0xF0)>>4; + + xc=yc=0; + + { + outportb(0x201,0); + + for(;;) + { + uint8 b; + + b=inportb(0x201); + if(!(b&3)) + break; + if(b&1) xc++; + if(b&2) yc++; + } + } + + joyx=xc; + joyy=yc; +} + +uint32 GetJSOr(void) +{ + int y; + unsigned long ret; + static int rtoggle=0; + ret=0; + + rtoggle^=1; + if(!soundo) + UpdateJoyData(); + for(y=0;y<6;y++) + if((y>=4 && rtoggle) || y<4) + if(joybuttons&joyBMap[y]) ret|=(1<=joyxcenter*1.75) ret|=JOY_RIGHT<<((joy-1)<<3); + if(joyy<=joyycenter*.25) ret|=JOY_UP<<((joy-1)<<3); + else if(joyy>=joyycenter*1.75) ret|=JOY_DOWN<<((joy-1)<<3); + + return ret; +} + +int InitJoysticks(void) +{ + if(!joy) return(0); + if(!DetectJoystick()) + { + printf("Joystick not detected!\n"); + joy=0; + return 0; + } + if(soundo) + { + soundjoyeron=1; + while(!soundjoyer); + } + else + UpdateJoyData(); + + joyxcenter=joyx; + joyycenter=joyy; + + if(!(joyBMap[0]|joyBMap[1]|joyBMap[2]|joyBMap[3])) + ConfigJoystick(); + return(1); +} + +static void BConfig(int b) +{ + int c=0; + uint32 st=time(0); + + while(time(0)< (st+4) ) + { + if(!soundo) + UpdateJoyData(); + if(joybuttons) c=joybuttons; + else if(c && !joybuttons) + { + joyBMap[b]=c; + break; + } + + } +} + +void KillJoysticks(void) +{ + +} + +static void ConfigJoystick(void) +{ + static char *genb="** Press button for "; + + printf("\n\n Joystick button configuration:\n\n"); + printf(" Push and release the button to map to the virtual joystick.\n"); + printf(" If you do not wish to assign a button, wait a few seconds\n"); + printf(" and the configuration will continue.\n\n"); + printf(" Press enter to continue...\n"); + getchar(); + + printf("%s\"Select\".\n",genb); + BConfig(2); + + printf("%s\"Start\".\n",genb); + BConfig(3); + + printf("%s\"B\".\n",genb); + BConfig(1); + + printf("%s\"A\".\n",genb); + BConfig(0); + + printf("%s\"Rapid fire B\".\n",genb); + BConfig(5); + + printf("%s\"Rapid fire A\".\n",genb); + BConfig(4); + +} + diff --git a/drivers/pc/dos-joystick.h b/drivers/pc/dos-joystick.h new file mode 100644 index 00000000..8c50c6b2 --- /dev/null +++ b/drivers/pc/dos-joystick.h @@ -0,0 +1,27 @@ +/* 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 + */ + +void UpdateJoyData(void); +uint32 GetJSOr(void); +int InitJoysticks(void); + +/* Variables to save in config file. */ +extern int joy; +extern int joyBMap[6]; diff --git a/drivers/pc/dos-keyboard.c b/drivers/pc/dos-keyboard.c new file mode 100644 index 00000000..b5926c3c --- /dev/null +++ b/drivers/pc/dos-keyboard.c @@ -0,0 +1,131 @@ +/* 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 "keyscan.h" + +static unsigned char lastsc; +static char keybuf[256]; +int newk; + +/* Read scan code from port $60 */ +/* Acknowledge interrupt( output $20 to port $20) */ + +static void ihandler(_go32_dpmi_registers *r) +{ + unsigned char scode=inp(0x60); /* Get scan code. */ + + + if(scode!=0xE0) + { + int offs=0; + + /* I'm only interested in preserving the independent status of the + right ALT and CONTROL keys. + */ + if(lastsc==0xE0) + if((scode&0x7F)==SCAN_LEFTALT || (scode&0x7F)==SCAN_LEFTCONTROL) + offs=0x80; + + + keybuf[(scode&0x7f)|offs]=((scode&0x80)^0x80); + newk++; + } + lastsc=scode; + + outp(0x20,0x20); /* Acknowledge interrupt. */ +} + +static _go32_dpmi_seginfo KBIBack,KBIBackRM; +static _go32_dpmi_seginfo KBI,KBIRM; +static _go32_dpmi_registers KBIRMRegs; +static int initdone=0; + +int InitKeyboard(void) +{ + /* I'll assume that the keyboard is in the correct scancode mode(translated + mode 2, I think). + */ + newk=0; + memset(keybuf,0,sizeof(keybuf)); + KBIRM.pm_offset=KBI.pm_offset=(int)ihandler; + KBIRM.pm_selector=KBI.pm_selector=_my_cs(); + + _go32_dpmi_get_real_mode_interrupt_vector(9,&KBIBackRM); + _go32_dpmi_allocate_real_mode_callback_iret(&KBIRM, &KBIRMRegs); + _go32_dpmi_set_real_mode_interrupt_vector(9,&KBIRM); + + _go32_dpmi_get_protected_mode_interrupt_vector(9,&KBIBack); + _go32_dpmi_allocate_iret_wrapper(&KBI); + _go32_dpmi_set_protected_mode_interrupt_vector(9,&KBI); + lastsc=0; + initdone=1; + return(1); +} + +void KillKeyboard(void) +{ + if(initdone) + { + _go32_dpmi_set_protected_mode_interrupt_vector(9,&KBIBack); + _go32_dpmi_free_iret_wrapper(&KBI); + + _go32_dpmi_set_real_mode_interrupt_vector(9,&KBIBackRM); + _go32_dpmi_free_real_mode_callback(&KBIRM); + initdone=0; + } +} + +/* In FCE Ultra, it doesn't matter if the key states change + in the middle of the keyboard handling code. If you want + to use this code elsewhere, you may want to memcpy() keybuf + to another buffer and return that when GetKeyboard() is + called. +*/ + +char *GetKeyboard(void) +{ + return keybuf; +} + +/* Returns 1 on new scan codes generated, 0 on no new scan codes. */ +int UpdateKeyboard(void) +{ + int t=newk; + + if(t) + { + asm volatile( + "subl %%eax,_newk\n\t" + : + : "a" (t) + ); + + if(keybuf[SCAN_LEFTCONTROL] && keybuf[SCAN_C]) + raise(SIGINT); + return(1); + } + return(0); +} diff --git a/drivers/pc/dos-mouse.c b/drivers/pc/dos-mouse.c new file mode 100644 index 00000000..3e0d1142 --- /dev/null +++ b/drivers/pc/dos-mouse.c @@ -0,0 +1,80 @@ +/* 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 "dos.h" + +int InitMouse(void) +{ + __dpmi_regs regs; + + memset(®s,0,sizeof(regs)); + regs.x.ax=0; + __dpmi_int(0x33,®s); + if(regs.x.ax!=0xFFFF) + return(0); + + memset(®s,0,sizeof(regs)); + regs.x.ax=0x7; + regs.x.cx=0; // Min X + regs.x.dx=260; // Max X + __dpmi_int(0x33,®s); + + memset(®s,0,sizeof(regs)); + regs.x.ax=0x8; + regs.x.cx=0; // Min Y + regs.x.dx=260; // Max Y + __dpmi_int(0x33,®s); + + memset(®s,0,sizeof(regs)); + regs.x.ax=0xF; + regs.x.cx=8; // Mickey X + regs.x.dx=8; // Mickey Y + __dpmi_int(0x33,®s); + + memset(®s,0,sizeof(regs)); + regs.x.ax=0x2; + __dpmi_int(0x33,®s); + + return(1); +} + +uint32 GetMouseData(uint32 *x, uint32 *y) +{ + if(FCEUI_IsMovieActive()<0) + return; + + __dpmi_regs regs; + + memset(®s,0,sizeof(regs)); + regs.x.ax=0x3; + __dpmi_int(0x33,®s); + + *x=regs.x.cx; + *y=regs.x.dx; + return(regs.x.bx&3); +} + +void KillMouse(void) +{ + +} diff --git a/drivers/pc/dos-sound.c b/drivers/pc/dos-sound.c new file mode 100644 index 00000000..e1a21fc1 --- /dev/null +++ b/drivers/pc/dos-sound.c @@ -0,0 +1,567 @@ +/* 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 + +#include "dos.h" +#include "dos-sound.h" +#include "dos-joystick.h" + + +static void SBIRQHandler(_go32_dpmi_registers *r); +static uint32 LMBuffer; /* Address of low memory DMA playback buffer. */ +static int LMSelector; + +static uint8 *WaveBuffer; +static unsigned int IVector, SBIRQ, SBDMA, SBDMA16, SBPort; +static int DSPV,hsmode; +static int format; +static int frags, fragsize, fragtotal; +static volatile int WritePtr, ReadPtr; +static volatile int hbusy; +static volatile int whichbuf; + + +static uint8 PICMask; +/* Protected mode interrupt vector info. */ +static _go32_dpmi_seginfo SBIH,SBIHOld; + +/* Real mode interrupt vector info. */ +static _go32_dpmi_seginfo SBIHRM,SBIHRMOld; +static _go32_dpmi_registers SBIHRMRegs; + +static int WriteDSP(uint8 V) +{ + int x; + + for(x=65536;x;x--) + { + if(!(inportb(SBPort+0xC)&0x80)) + { + outportb(SBPort+0xC,V); + return(1); + } + } + return(0); +} + +static int ReadDSP(uint8 *V) +{ + int x; + + for(x=65536;x;x--) /* Should be more than enough time... */ + { + if(inportb(SBPort+0xE)&0x80) + { + *V=inportb(SBPort+0xA); + return(1); + } + } + return(0); +} + + +static int SetVectors(void) +{ + SBIH.pm_offset=SBIHRM.pm_offset=(int)SBIRQHandler; + SBIH.pm_selector=SBIHRM.pm_selector=_my_cs(); + + /* Get and set real mode interrupt vector. */ + _go32_dpmi_get_real_mode_interrupt_vector(IVector,&SBIHRMOld); + _go32_dpmi_allocate_real_mode_callback_iret(&SBIHRM, &SBIHRMRegs); + _go32_dpmi_set_real_mode_interrupt_vector(IVector,&SBIHRM); + + /* Get and set protected mode interrupt vector. */ + _go32_dpmi_get_protected_mode_interrupt_vector(IVector,&SBIHOld); + _go32_dpmi_allocate_iret_wrapper(&SBIH); + _go32_dpmi_set_protected_mode_interrupt_vector(IVector,&SBIH); + + return(1); +} + +static void ResetVectors(void) +{ + _go32_dpmi_set_protected_mode_interrupt_vector(IVector,&SBIHOld); + _go32_dpmi_free_iret_wrapper(&SBIH); + _go32_dpmi_set_real_mode_interrupt_vector(IVector,&SBIHRMOld); + _go32_dpmi_free_real_mode_callback(&SBIHRM); +} + +int GetBLASTER(void) +{ + int check=0; + char *s; + + if(!(s=getenv("BLASTER"))) + { + puts(" Error getting BLASTER environment variable."); + return(0); + } + + while(*s) + { + switch(toupper(*s)) + { + case 'A': check|=(sscanf(s+1,"%x",&SBPort)==1)?1:0;break; + case 'I': check|=(sscanf(s+1,"%d",&SBIRQ)==1)?2:0;break; + case 'D': check|=(sscanf(s+1,"%d",&SBDMA)==1)?4:0;break; + case 'H': check|=(sscanf(s+1,"%d",&SBDMA16)==1)?8:0;break; + } + s++; + } + + if((check^7)&7 || SBDMA>=4 || (SBDMA16<=4 && check&8) || SBIRQ>15) + { + puts(" Invalid or incomplete BLASTER environment variable."); + return(0); + } + if(!(check&8)) + format=0; + return(1); +} + +static int ResetDSP(void) +{ + uint8 b; + + outportb(SBPort+0x6,0x1); + delay(10); + outportb(SBPort+0x6,0x0); + delay(10); + + if(ReadDSP(&b)) + if(b==0xAA) + return(1); + return(0); +} + +static int GetDSPVersion(void) +{ + int ret; + uint8 t; + + if(!WriteDSP(0xE1)) + return(0); + if(!ReadDSP(&t)) + return(0); + ret=t<<8; + if(!ReadDSP(&t)) + return(0); + ret|=t; + + return(ret); +} + +static void KillDMABuffer(void) +{ + __dpmi_free_dos_memory(LMSelector); +} + +static int MakeDMABuffer(void) +{ + uint32 size; + int32 tmp; + + size=fragsize*2; /* Two buffers in the DMA buffer. */ + size<<=format; /* Twice the size for 16-bit than for 8-bit. */ + + size<<=1; /* Double the size in case the first 2 buffers + cross a 64KB or 128KB page boundary. + */ + size=(size+15)>>4; /* Convert to paragraphs */ + + if((tmp=__dpmi_allocate_dos_memory(size,&LMSelector))<0) + return(0); + + LMBuffer=tmp<<=4; + + if(format) /* Check for and fix 128KB page boundary crossing. */ + { + if((LMBuffer&0x20000) != ((LMBuffer+fragsize*2*2-1)&0x20000)) + LMBuffer+=fragsize*2*2; + } + else /* Check for and fix 64KB page boundary crossing. */ + { + if((LMBuffer&0x10000) != ((LMBuffer+fragsize*2-1)&0x10000)) + LMBuffer+=fragsize*2; + } + + DOSMemSet(LMBuffer, format?0:128, (fragsize*2)<>8); + + /* Page of buffer. */ + outportb(PPorts[format?SBDMA16:SBDMA],LMBuffer>>16); + + /* Offset of buffer within page. */ + if(format) + tmp=((SBDMA16&3)<<2)+0xc0; + else + tmp=SBDMA<<1; + + outportb(tmp,(LMBuffer>>format)); + outportb(tmp,(LMBuffer>>(8+format))); +} + +int InitSB(int Rate, int bittage) +{ + hsmode=hbusy=0; + whichbuf=1; + puts("Initializing Sound Blaster..."); + + format=bittage?1:0; + frags=8; + + if(Rate<=11025) + fragsize=1<<5; + else if(Rate<=22050) + fragsize=1<<6; + else + fragsize=1<<7; + + fragtotal=frags*fragsize; + WaveBuffer=malloc(fragtotal<65535)) + { + printf(" Unsupported playback rate: %d samples per second\n",Rate); + return(0); + } + + if(!GetBLASTER()) + return(0); + + /* Disable IRQ line in PIC0 or PIC1 */ + if(SBIRQ>7) + { + PICMask=inportb(0xA1); + outportb(0xA1,PICMask|(1<<(SBIRQ&7))); + } + else + { + PICMask=inportb(0x21); + outportb(0x21,PICMask|(1<>8,DSPV&0xFF); + if(DSPV<0x201) + { + printf(" DSP version number is too low.\n"); + return(0); + } + + if(DSPV<0x400) + format=0; + if(!MakeDMABuffer()) + { + puts(" Error creating low-memory DMA buffer."); + return(0); + } + + if(SBIRQ>7) IVector=SBIRQ+0x68; + else IVector=SBIRQ+0x8; + + if(!SetVectors()) + { + puts(" Error setting interrupt vectors."); + KillDMABuffer(); + return(0); + } + + /* Reenable IRQ line. */ + if(SBIRQ>7) + outportb(0xA1,PICMask&(~(1<<(SBIRQ&7)))); + else + outportb(0x21,PICMask&(~(1<=0x400) + { + WriteDSP(0x41); // Set sampling rate + WriteDSP(Rate>>8); // High byte + WriteDSP(Rate&0xFF); // Low byte + if(!format) + { + WriteDSP(0xC6); // 8-bit output + WriteDSP(0x00); // 8-bit mono unsigned PCM + } + else + { + WriteDSP(0xB6); // 16-bit output + WriteDSP(0x10); // 16-bit mono signed PCM + } + WriteDSP((fragsize-1)&0xFF);// Low byte of size + WriteDSP((fragsize-1)>>8); // High byte of size + } + else + { + int tc,command; + if(Rate>22050) + { + tc=(65536-(256000000/Rate))>>8; + Rate=256000000/(65536-(tc<<8)); + command=0x90; // High-speed auto-initialize DMA mode transfer + hsmode=1; + } + else + { + tc=256-(1000000/Rate); + Rate=1000000/(256-tc); + command=0x1c; // Auto-initialize DMA mode transfer + } + WriteDSP(0x40); // Set DSP time constant + WriteDSP(tc); // time constant + WriteDSP(0x48); // Set DSP block transfer size + WriteDSP((fragsize-1)&0xFF); + WriteDSP((fragsize-1)>>8); + + WriteDSP(command); + } + + /* Enable DMA */ + if(format) + outportb(0xd4,SBDMA16&3); + else + outportb(0xa,SBDMA); + + printf(" %d hz, %d-bit\n",Rate,8<=8) + outportb(0xA0,0x20); + whichbuf^=1; + return; + } + hbusy=1; + + { + /* This code seems to fail on many SB emulators. Bah. + SCREW SB EMULATORS. ^_^ */ + uint32 count; + uint32 block; + uint32 port; + + if(format) + port=((SBDMA16&3)*4)+0xc2; + else + port=(SBDMA*2)+1; + + count=inportb(port); + count|=inportb(port)<<8; + + if(count>=fragsize) + block=1; + else + block=0; + dest=LMBuffer+((block*fragsize)<>2;x;x--,dest+=4) + { + _farnspokel(dest,sby); + } + } + else + { + for(x=(fragsize<>2;x;x--,dest+=4,src++) + { + _farnspokel(dest,*src); + } + ReadPtr=(ReadPtr+fragsize)&(fragtotal-1); + } + + if(soundjoyeron) + { + static int coot=0; + if(!coot) + { + UpdateJoyData(); + soundjoyer=1; + } + coot=(coot+1)&3; + } + hbusy=0; + outportb(0x20,0x20); + if(SBIRQ>=8) + outportb(0xA0,0x20); +} + +void SilenceSound(int s) +{ + ssilence=s; +} + +void WriteSBSound(int32 *Buffer, int Count, int NoBlocking) +{ + int x; + + if(!format) + { + for(x=0;x>8)^128; + WritePtr=(WritePtr+1)&(fragtotal-1); + } + } + else // 16 bit + { + for(x=0;x7)?0xA1:0x21,PICMask|(1<<(SBIRQ&7))); + ResetVectors(); + outportb((SBIRQ>7)?0xA1:0x21,PICMask); + KillDMABuffer(); +} diff --git a/drivers/pc/dos-sound.h b/drivers/pc/dos-sound.h new file mode 100644 index 00000000..c0e261b5 --- /dev/null +++ b/drivers/pc/dos-sound.h @@ -0,0 +1,26 @@ +/* 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 + */ + +int InitSB(int Rate, int bittage); +void KillSB(void); + +void WriteSBSound(int32 *Buffer, int Count, int NoBlocking); +void SilenceSound(int s); + diff --git a/drivers/pc/dos-video.c b/drivers/pc/dos-video.c new file mode 100644 index 00000000..6c9a3682 --- /dev/null +++ b/drivers/pc/dos-video.c @@ -0,0 +1,246 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 1998 \Firebug\ + * 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 "dos.h" +#include "dos-video.h" + +#define TEXT 3 +#define G320x200x256 0x13 + +static void vga_waitretrace(void) +{ + while(inp(0x3da)&0x8); + while(!(inp(0x3da)&0x8)); +} + +static void vga_setmode(int mode) +{ + __dpmi_regs regs; + + memset(®s,0,sizeof(regs)); + regs.x.ax=mode; + + __dpmi_int(0x10,®s); +} + +void vga_setpalette(int i, int r, int g, int b) +{ + outp(0x3c8,i); + outp(0x3c9,r); + outp(0x3c9,g); + outp(0x3c9,b); +} + +int FCEUDvmode=1; + +static int vidready=0; + +/* Part of the VGA low-level mass register setting code derived from + code by \Firebug\. +*/ + +#include "vgatweak.c" + +void SetBorder(void) +{ + inportb(0x3da); + outportb(0x3c0,(0x11|0x20)); + outportb(0x3c0,0x80); +} + +void TweakVGA(int VGAMode) +{ + int I; + + vga_waitretrace(); + + outportb(0x3C8,0x00); + for(I=0;I<768;I++) outportb(0x3C9,0x00); + + outportb(0x3D4,0x11); + I=inportb(0x3D5)&0x7F; + outportb(0x3D4,0x11); + outportb(0x3D5,I); + + switch(VGAMode) + { + case 1: for(I=0;I<25;I++) VGAPortSet(v256x240[I]);break; + case 2: for(I=0;I<25;I++) VGAPortSet(v256x256[I]);break; + case 3: for(I=0;I<25;I++) VGAPortSet(v256x256S[I]);break; + case 6: for(I=0;I<25;I++) VGAPortSet(v256x224S[I]);break; + case 8: for(I=0;I<25;I++) VGAPortSet(v256x224_103[I]);break; + default: break; + } + + outportb(0x3da,0); +} + + +static uint8 palettedbr[256],palettedbg[256],palettedbb[256]; + +static void FlushPalette(void) +{ + int x; + for(x=0;x<256;x++) + { + int z=x; + vga_setpalette(z,palettedbr[x]>>2,palettedbg[x]>>2,palettedbb[x]>>2); + } +} + +void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b) +{ + palettedbr[index]=r; + palettedbg[index]=g; + palettedbb[index]=b; + if(vidready) + { + vga_setpalette(index,r>>2,g>>2,b>>2); + } +} + + +void FCEUD_GetPalette(uint8 i, uint8 *r, uint8 *g, uint8 *b) +{ + *r=palettedbr[i]; + *g=palettedbg[i]; + *b=palettedbb[i]; +} + +static uint32 ScreenLoc; + +int InitVideo(void) +{ + vidready=0; + switch(FCEUDvmode) + { + default: + case 1: + case 2: + case 3: + case 6: + case 8: + vga_setmode(G320x200x256); + vidready|=1; + ScreenLoc=0xa0000; + TweakVGA(FCEUDvmode); + SetBorder(); + DOSMemSet(ScreenLoc, 128, 256*256); + break; + } + vidready|=2; + FlushPalette(); + return 1; +} + +void KillVideo(void) +{ + if(vidready) + { + vga_setmode(TEXT); + vidready=0; + } +} +void LockConsole(void){} +void UnlockConsole(void){} +void BlitScreen(uint8 *XBuf) +{ + uint32 dest; + int tlines; + + if(eoptions&4 && !NoWaiting) + vga_waitretrace(); + + tlines=erendline-srendline+1; + + dest=ScreenLoc; + + switch(FCEUDvmode) + { + case 1:dest+=(((240-tlines)>>1)<<8);break; + case 2: + case 3:dest+=(((256-tlines)>>1)<<8);break; + case 4: + case 5:dest+=(((240-tlines)>>1)*640+((640-512)>>1));break; + case 8: + case 6:if(tlines>224) tlines=224;dest+=(((224-tlines)>>1)<<8);break; + } + + XBuf+=(srendline<<8)+(srendline<<4); + + _farsetsel(_dos_ds); + if(eoptions&DO_CLIPSIDES) + { + asm volatile( + "agoop1:\n\t" + "movl $30,%%eax\n\t" + "agoop2:\n\t" + "movl (%%esi),%%edx\n\t" + "movl 4(%%esi),%%ecx\n\t" + ".byte 0x64 \n\t" + "movl %%edx,(%%edi)\n\t" + ".byte 0x64 \n\t" + "movl %%ecx,4(%%edi)\n\t" + "addl $8,%%esi\n\t" + "addl $8,%%edi\n\t" + "decl %%eax\n\t" + "jne agoop2\n\t" + "addl $32,%%esi\n\t" + "addl $16,%%edi\n\t" + "decb %%bl\n\t" + "jne agoop1\n\t" + : + : "S" (XBuf+8), "D" (dest+8), "b" (tlines) + : "%eax","%cc","%edx","%ecx" ); + } + else + { + asm volatile( + "goop1:\n\t" + "movl $32,%%eax\n\t" + "goop2:\n\t" + "movl (%%esi),%%edx\n\t" + "movl 4(%%esi),%%ecx\n\t" + ".byte 0x64 \n\t" + "movl %%edx,(%%edi)\n\t" + ".byte 0x64 \n\t" + "movl %%ecx,4(%%edi)\n\t" + "addl $8,%%esi\n\t" + "addl $8,%%edi\n\t" + "decl %%eax\n\t" + "jne goop2\n\t" + "addl $16,%%esi\n\t" + "decb %%bl\n\t" + "jne goop1\n\t" + : + : "S" (XBuf), "D" (dest), "b" (tlines) + : "%eax","%cc","%edx","%ecx" ); + } +} + + diff --git a/drivers/pc/dos-video.h b/drivers/pc/dos-video.h new file mode 100644 index 00000000..75b1a1b8 --- /dev/null +++ b/drivers/pc/dos-video.h @@ -0,0 +1,22 @@ +/* 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 + */ + +extern int FCEUDvmode; + diff --git a/drivers/pc/dos.c b/drivers/pc/dos.c new file mode 100644 index 00000000..bd34b058 --- /dev/null +++ b/drivers/pc/dos.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include + +#include "dos.h" +#include "dos-joystick.h" +#include "dos-video.h" +#include "dos-sound.h" +#include "../common/args.h" +#include "../common/config.h" + +/* _CRT0_FLAG_LOCK_MEMORY might not always result in all memory being locked. + Bummer. I'll add code to explicitly lock the data touched by the sound + interrupt handler(and the handler itself), if necessary(though that might + be tricky...). I'll also to cover the data the keyboard + interrupt handler touches. +*/ + +int _crt0_startup_flags = _CRT0_FLAG_FILL_SBRK_MEMORY | _CRT0_FLAG_LOCK_MEMORY | _CRT0_FLAG_USE_DOS_SLASHES; + +static int f8bit=0; +int soundo=44100; +int doptions=0; + + +CFGSTRUCT DriverConfig[]={ + NAC("sound",soundo), + AC(doptions), + AC(f8bit), + AC(FCEUDvmode), + NACA("joybmap",joyBMap), + AC(joy), + ENDCFGSTRUCT +}; + +char *DriverUsage= +"-vmode x Select video mode(all are 8 bpp).\n\ + 1 = 256x240 6 = 256x224(with scanlines)\n\ + 2 = 256x256 8 = 256x224\n\ + 3 = 256x256(with scanlines)\n\ +-vsync x Wait for the screen's vertical retrace before updating the\n\ + screen. Refer to the documentation for caveats.\n\ + 0 = Disabled.\n\ + 1 = Enabled.\n\ +-sound x Sound.\n\ + 0 = Disabled.\n\ + Otherwise, x = playback rate.\n\ +-f8bit x Force 8-bit sound.\n\ + 0 = Disabled.\n\ + 1 = Enabled."; + +ARGPSTRUCT DriverArgs[]={ + {"-vmode",0,&FCEUDvmode,0}, + {"-sound",0,&soundo,0}, + {"-f8bit",0,&f8bit,0}, + {"-vsync",0,&doptions,DO_VSYNC}, + {0,0,0,0} +}; + +void DoDriverArgs(void) +{ + if(!joy) memset(joyBMap,0,sizeof(joyBMap)); +} + +int InitSound(void) +{ + if(soundo) + { + if(soundo==1) + soundo=44100; + soundo=InitSB(soundo,f8bit?0:1); + FCEUI_Sound(soundo); + } + return(soundo); +} + +void WriteSound(int32 *Buffer, int Count, int NoWaiting) +{ + WriteSBSound(Buffer,Count,NoWaiting); +} + +void KillSound(void) +{ + if(soundo) + KillSB(); +} + +void DOSMemSet(uint32 A, uint8 V, uint32 count) +{ + uint32 x; + + _farsetsel(_dos_ds); + for(x=0;x=0;x--) + { + if(arg0[x]=='/' || arg0[x]=='\\') + { + ret = malloc(x + 1); + strncpy(ret,arg0,x); + break; + } + } + + if(!ret) { x=0; ret = malloc(1); } + + BaseDirectory[x]=0; +} + +int main(int argc, char *argv[]) +{ + puts("\nStarting FCE Ultra "VERSION_STRING"...\n"); + arg0=argv[0]; + return(CLImain(argc,argv)); +} + diff --git a/drivers/pc/dos.h b/drivers/pc/dos.h new file mode 100644 index 00000000..b6814800 --- /dev/null +++ b/drivers/pc/dos.h @@ -0,0 +1,27 @@ +/* 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 "main.h" +#include "dface.h" +#include "input.h" + +void DOSMemSet(uint32 A, uint8 V, uint32 count); +#define DO_VSYNC 1 + diff --git a/drivers/pc/input.c b/drivers/pc/input.c new file mode 100644 index 00000000..35fe0350 --- /dev/null +++ b/drivers/pc/input.c @@ -0,0 +1,720 @@ +/* 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 "main.h" +#include "dface.h" +#include "input.h" + +#include "../common/cheat.h" + +/* UsrInputType[] is user-specified. InputType[] is current + (game loading can override user settings) +*/ +int UsrInputType[3]={SI_GAMEPAD,SI_GAMEPAD,SIFC_NONE}; +int InputType[3]={0,0,0}; +static int cspec=0; + +int gametype=0; + +/* Necessary for proper GUI functioning(configuring when a game isn't loaded). */ +void InputUserActiveFix(void) +{ + int x; + for(x=0;x<3;x++) InputType[x]=UsrInputType[x]; +} + +void ParseGIInput(FCEUGI *gi) +{ + gametype=gi->type; + + InputType[0]=UsrInputType[0]; + InputType[1]=UsrInputType[1]; + InputType[2]=UsrInputType[2]; + + if(gi->input[0]>=0) + InputType[0]=gi->input[0]; + if(gi->input[1]>=0) + InputType[1]=gi->input[1]; + if(gi->inputfc>=0) + InputType[2]=gi->inputfc; + cspec = gi->cspecial; + + #ifdef EXTGUI + Giggles(gi->cspecial); + #endif +} + + +static uint8 QuizKingData=0; +static uint8 HyperShotData=0; +static uint32 MahjongData=0; +static uint32 FTrainerData=0; +static uint8 TopRiderData=0; + +static uint8 BWorldData[1+13+1]; + +static void UpdateFKB(void); +static void UpdateGamepad(void); +static void UpdateQuizKing(void); +static void UpdateHyperShot(void); +static void UpdateMahjong(void); +static void UpdateFTrainer(void); +static void UpdateTopRider(void); + +static uint32 JSreturn=0; +int NoWaiting=1; + +#ifndef EXTGUI +static void DoCheatSeq(void) +{ + #if defined(DOS) || defined(SDL) + SilenceSound(1); + #endif + KillKeyboard(); + KillVideo(); + + DoConsoleCheatConfig(); + InitVideo(CurGame); + InitKeyboard(); + #if defined(DOS) || defined(SDL) + SilenceSound(0); + #endif +} +#endif + +#include "keyscan.h" +static char *keys=0; +static int DIPS=0; + +static uint8 keyonce[MKK_COUNT]; +#define KEY(__a) keys[MKK(__a)] + +static int _keyonly(int a) +{ + if(keys[a]) + { + if(!keyonce[a]) + { + keyonce[a]=1; + return(1); + } + } + else + keyonce[a]=0; + return(0); +} + +#define keyonly(__a) _keyonly(MKK(__a)) + +static int cidisabled=0; + +static void KeyboardCommands(void) +{ + int is_shift, is_alt; + + keys=GetKeyboard(); + + if(InputType[2]==SIFC_FKB) + { + if(keyonly(SCROLLLOCK)) + { + cidisabled^=1; + FCEUI_DispMessage("Family Keyboard %sabled.",cidisabled?"en":"dis"); + } + #ifdef SDL + SDL_WM_GrabInput(cidisabled?SDL_GRAB_ON:SDL_GRAB_OFF); + #endif + if(cidisabled) return; + } + + is_shift = KEY(LEFTSHIFT) | KEY(RIGHTSHIFT); + is_alt = KEY(LEFTALT) | KEY(RIGHTALT); + + if(keyonly(F4)) + { + if(is_shift) FCEUI_SetRenderDisable(-1, 2); + else FCEUI_SetRenderDisable(2, -1); + } + #ifdef SDL + if(keyonly(ENTER) && is_alt) ToggleFS(); + #endif + + NoWaiting&=~1; + if(KEY(GRAVE)) + NoWaiting|=1; + + if(gametype==GIT_FDS) + { + if(keyonly(F6)) FCEUI_FDSSelect(); + if(keyonly(F8)) FCEUI_FDSInsert(); + } + + if(keyonly(F9)) FCEUI_SaveSnapshot(); + if(gametype!=GIT_NSF) + { + #ifndef EXTGUI + if(keyonly(F2)) DoCheatSeq(); + #endif + if(keyonly(F5)) + { + if(is_shift) + FCEUI_SaveMovie(NULL,0,NULL); + else + FCEUI_SaveState(NULL); + } + if(keyonly(F7)) + { + if(is_shift) + FCEUI_LoadMovie(NULL,0); + else + FCEUI_LoadState(NULL); + } + } + + if(keyonly(F1)) FCEUI_ToggleTileView(); + + if(keyonly(MINUS)) DecreaseEmulationSpeed(); + if(keyonly(EQUAL)) IncreaseEmulationSpeed(); + if(keyonly(BACKSPACE)) FCEUI_MovieToggleFrameDisplay(); + if(keyonly(BACKSLASH)) FCEUI_ToggleEmulationPause(); + if(keyonly(RIGHTCONTROL)) FCEUI_FrameAdvance(); + + if(keyonly(F10)) FCEUI_ResetNES(); + if(keyonly(F11)) FCEUI_PowerNES(); + + #ifdef EXTGUI + if(keyonly(F3)) GUI_Hide(-1); + if(KEY(F12)) GUI_RequestExit(); + if(KEY(ESCAPE)) CloseGame(); + #else + if(KEY(F12) || KEY(ESCAPE)) CloseGame(); + #endif + + if(gametype==GIT_VSUNI) + { + if(keyonly(F8)) FCEUI_VSUniCoin(); + if(keyonly(F6)) + { + DIPS^=1; + FCEUI_VSUniToggleDIPView(); + } + if(!(DIPS&1)) goto DIPSless; + if(keyonly(1)) FCEUI_VSUniToggleDIP(0); + if(keyonly(2)) FCEUI_VSUniToggleDIP(1); + if(keyonly(3)) FCEUI_VSUniToggleDIP(2); + if(keyonly(4)) FCEUI_VSUniToggleDIP(3); + if(keyonly(5)) FCEUI_VSUniToggleDIP(4); + if(keyonly(6)) FCEUI_VSUniToggleDIP(5); + if(keyonly(7)) FCEUI_VSUniToggleDIP(6); + if(keyonly(8)) FCEUI_VSUniToggleDIP(7); + } + else + { + static uint8 bbuf[32]; + static int bbuft; + static int barcoder = 0; + + if(keyonly(H)) FCEUI_NTSCSELHUE(); + if(keyonly(T)) FCEUI_NTSCSELTINT(); + if(KEY(KP_MINUS) || KEY(MINUS)) FCEUI_NTSCDEC(); + if(KEY(KP_PLUS) || KEY(EQUAL)) FCEUI_NTSCINC(); + + if((InputType[2] == SIFC_BWORLD) || (cspec == SIS_DATACH)) + { + if(keyonly(F8)) + { + barcoder ^= 1; + if(!barcoder) + { + if(InputType[2] == SIFC_BWORLD) + { + strcpy(&BWorldData[1],bbuf); + BWorldData[0]=1; + } + else + FCEUI_DatachSet(bbuf); + FCEUI_DispMessage("Barcode Entered"); + } + else { bbuft = 0; FCEUI_DispMessage("Enter Barcode");} + } + } else barcoder = 0; + + #define SSM(x) \ + { if(barcoder) { if(bbuft < 13) {bbuf[bbuft++] = '0' + x; bbuf[bbuft] = 0;} FCEUI_DispMessage("Barcode: %s",bbuf);} \ + else { \ + if(is_shift) FCEUI_SelectMovie(x,1); \ + else FCEUI_SelectState(x,1); \ + } } + + DIPSless: + if(keyonly(0)) SSM(0); + if(keyonly(1)) SSM(1); + if(keyonly(2)) SSM(2); + if(keyonly(3)) SSM(3); + if(keyonly(4)) SSM(4); + if(keyonly(5)) SSM(5); + if(keyonly(6)) SSM(6); + if(keyonly(7)) SSM(7); + if(keyonly(8)) SSM(8); + if(keyonly(9)) SSM(9); + #undef SSM + } +} + +#define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1} +#define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2} + +#define MKZ() {{0},{0},{0},0} + +#define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()} + +ButtConfig GamePadConfig[4][10]={ + /* Gamepad 1 */ + { + MK(KP3), MK(KP2), MK(TAB), MK(ENTER), MK(W),MK(Z), + MK(A), MK(S), MKZ(), MKZ() + }, + + /* Gamepad 2 */ + GPZ(), + + /* Gamepad 3 */ + GPZ(), + + /* Gamepad 4 */ + GPZ() +}; + + +static void UpdateGamepad(void) +{ + if(FCEUI_IsMovieActive()<0) + return; + + static int rapid=0; + uint32 JS=0; + int x; + int wg; + + rapid^=1; + + for(wg=0;wg<4;wg++) + { + for(x=0;x<8;x++) + if(DTestButton(&GamePadConfig[wg][x])) + JS|=(1<ButtType[wc]==bc->ButtType[wc-1] && bc->DeviceNum[wc]==bc->DeviceNum[wc-1] && + bc->ButtonNum[wc]==bc->ButtonNum[wc-1]) + break; + } + bc->NumC=wc; +} + +void ConfigDevice(int which, int arg) +{ + uint8 buf[256]; + int x; + + ButtonConfigBegin(); + switch(which) + { + case FCFGD_QUIZKING: + for(x=0;x<6;x++) + { + sprintf(buf,"Quiz King Buzzer #%d", x+1); + subcon(buf,&QuizKingButtons[x]); + } + break; + case FCFGD_HYPERSHOT: + for(x=0;x<4;x++) + { + sprintf(buf,"Hyper Shot %d: %s",((x&2)>>1)+1,(x&1)?"JUMP":"RUN"); + subcon(buf,&HyperShotButtons[x]); + } + break; + case FCFGD_POWERPAD: + for(x=0;x<12;x++) + { + sprintf(buf,"PowerPad %d: %d", (arg&1)+1,x+11); + subcon(buf,&powerpadsc[arg&1][x]); + } + break; + + case FCFGD_GAMEPAD: + { + char *str[10]={"A","B","SELECT","START","UP","DOWN","LEFT","RIGHT","Rapid A","Rapid B"}; + for(x=0;x<10;x++) + { + sprintf(buf,"GamePad #%d: %s",arg+1,str[x]); + subcon(buf,&GamePadConfig[arg][x]); + } + } + break; + } + + ButtonConfigEnd(); +} + + +CFGSTRUCT InputConfig[]={ + ACA(UsrInputType), + AC(powerpadsc), + AC(QuizKingButtons), + AC(FTrainerButtons), + AC(HyperShotButtons), + AC(MahjongButtons), + AC(GamePadConfig), + AC(fkbmap), + ENDCFGSTRUCT +}; + + +static void InputCfg(char *text) +{ + if(!strncasecmp(text,"gamepad",strlen("gamepad"))) + { + ConfigDevice(FCFGD_GAMEPAD,(text[strlen("gamepad")]-'1')&3); + } + else if(!strncasecmp(text,"powerpad",strlen("powerpad"))) + { + ConfigDevice(FCFGD_POWERPAD,(text[strlen("powerpad")]-'1')&1); + } + else if(!strcasecmp(text,"hypershot")) + ConfigDevice(FCFGD_HYPERSHOT,0); + else if(!strcasecmp(text,"quizking")) + ConfigDevice(FCFGD_QUIZKING,0); +} + +static void FCExp(char *text) +{ + static char *fccortab[11]={"none","arkanoid","shadow","4player","fkb","hypershot", + "mahjong","quizking","ftrainera","ftrainerb","oekakids"}; + + static int fccortabi[11]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW, + SIFC_4PLAYER,SIFC_FKB,SIFC_HYPERSHOT,SIFC_MAHJONG,SIFC_QUIZKING, + SIFC_FTRAINERA,SIFC_FTRAINERB,SIFC_OEKAKIDS}; + int y; + for(y=0;y<11;y++) + if(!strcmp(fccortab[y],text)) + UsrInputType[2]=fccortabi[y]; +} + +static char *cortab[6]={"none","gamepad","zapper","powerpada","powerpadb","arkanoid"}; +static int cortabi[6]={SI_NONE,SI_GAMEPAD, + SI_ZAPPER,SI_POWERPADA,SI_POWERPADB,SI_ARKANOID}; + +static void Input1(char *text) +{ + int y; + + for(y=0;y<6;y++) + if(!strcmp(cortab[y],text)) + UsrInputType[0]=cortabi[y]; +} + +static void Input2(char *text) +{ + int y; + + for(y=0;y<6;y++) + if(!strcmp(cortab[y],text)) + UsrInputType[1]=cortabi[y]; +} + +ARGPSTRUCT InputArgs[]={ + {"-inputcfg",0,(void *)InputCfg,0x2000}, + {"-fcexp",0,(void *)FCExp,0x2000}, + {"-input1",0,(void *)Input1,0x2000}, + {"-input2",0,(void *)Input2,0x2000}, + {0,0,0,0} +}; diff --git a/drivers/pc/input.h b/drivers/pc/input.h new file mode 100644 index 00000000..f9fbf36e --- /dev/null +++ b/drivers/pc/input.h @@ -0,0 +1,38 @@ +#ifndef _aosdfjk02fmasf +#define _aosdfjk02fmasf +#define MAXBUTTCONFIG 4 +typedef struct { + uint8 ButtType[MAXBUTTCONFIG]; + uint8 DeviceNum[MAXBUTTCONFIG]; + uint16 ButtonNum[MAXBUTTCONFIG]; + uint32 NumC; + //uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */ +} ButtConfig; + +extern CFGSTRUCT InputConfig[]; +extern ARGPSTRUCT InputArgs[]; +void ParseGIInput(FCEUGI *GI); + +#define BUTTC_KEYBOARD 0x00 +#define BUTTC_JOYSTICK 0x01 +#define BUTTC_MOUSE 0x02 + +#define FCFGD_GAMEPAD 1 +#define FCFGD_POWERPAD 2 +#define FCFGD_HYPERSHOT 3 +#define FCFGD_QUIZKING 4 + +void InitOtherInput(void); +void InputUserActiveFix(void); +#ifdef EXTGUI +extern ButtConfig GamePadConfig[4][10]; +extern ButtConfig powerpadsc[2][12]; +extern ButtConfig QuizKingButtons[6]; +extern ButtConfig FTrainerButtons[12]; +#endif + +void IncreaseEmulationSpeed(void); +void DecreaseEmulationSpeed(void); + +void FCEUD_UpdateInput(void); +#endif diff --git a/drivers/pc/keyscan.h b/drivers/pc/keyscan.h new file mode 100644 index 00000000..09c20a1b --- /dev/null +++ b/drivers/pc/keyscan.h @@ -0,0 +1,161 @@ +#ifdef SDL +#include +#define SDLK_A SDLK_a +#define SDLK_B SDLK_b +#define SDLK_C SDLK_c +#define SDLK_D SDLK_d +#define SDLK_E SDLK_e +#define SDLK_F SDLK_f +#define SDLK_G SDLK_g +#define SDLK_H SDLK_h +#define SDLK_I SDLK_i +#define SDLK_J SDLK_j +#define SDLK_K SDLK_k +#define SDLK_L SDLK_l +#define SDLK_M SDLK_m +#define SDLK_N SDLK_n +#define SDLK_O SDLK_o +#define SDLK_P SDLK_p +#define SDLK_Q SDLK_q +#define SDLK_R SDLK_r +#define SDLK_S SDLK_s +#define SDLK_T SDLK_t +#define SDLK_U SDLK_u +#define SDLK_V SDLK_v +#define SDLK_W SDLK_w +#define SDLK_X SDLK_x +#define SDLK_Y SDLK_y +#define SDLK_Z SDLK_z +#define SDLK_LEFTCONTROL SDLK_LCTRL +#define SDLK_RIGHTCONTROL SDLK_RCTRL +#define SDLK_LEFTALT SDLK_LALT +#define SDLK_RIGHTALT SDLK_RALT +#define SDLK_LEFTSHIFT SDLK_LSHIFT +#define SDLK_RIGHTSHIFT SDLK_RSHIFT +#define SDLK_CURSORDOWN SDLK_DOWN +#define SDLK_CURSORUP SDLK_UP +#define SDLK_CURSORLEFT SDLK_LEFT +#define SDLK_CURSORRIGHT SDLK_RIGHT +#define SDLK_ENTER SDLK_RETURN +#define SDLK_EQUAL SDLK_EQUALS +#define SDLK_APOSTROPHE SDLK_QUOTE +#define SDLK_BRACKET_LEFT SDLK_LEFTBRACKET +#define SDLK_BRACKET_RIGHT SDLK_RIGHTBRACKET +#define SDLK_SCROLLLOCK SDLK_SCROLLOCK /* I guess the SDL people don't like lots of Ls... */ +#define SDLK_GRAVE SDLK_BACKQUOTE +#define MKK(k) SDLK_##k +#define MKK_COUNT (SDLK_LAST+1) + +#elif DOS + +#define SCAN_GRAVE 0x29 +#define SCAN_1 0x02 +#define SCAN_2 0x03 +#define SCAN_3 0x04 +#define SCAN_4 0x05 +#define SCAN_5 0x06 +#define SCAN_6 0x07 +#define SCAN_7 0x08 +#define SCAN_8 0x09 +#define SCAN_9 0x0A +#define SCAN_0 0x0B +#define SCAN_MINUS 0x0C +#define SCAN_EQUAL 0x0D +#define SCAN_BACKSLASH 0x2B +#define SCAN_BACKSPACE 0x0E +#define SCAN_TAB 0x0F +#define SCAN_Q 0x10 +#define SCAN_W 0x11 +#define SCAN_E 0x12 +#define SCAN_R 0x13 +#define SCAN_T 0x14 +#define SCAN_Y 0x15 +#define SCAN_U 0x16 +#define SCAN_I 0x17 +#define SCAN_O 0x18 +#define SCAN_P 0x19 +#define SCAN_BRACKET_LEFT 0x1A +#define SCAN_BRACKET_RIGHT 0x1B +#define SCAN_LOWBACKSLASH 0x2B +#define SCAN_CAPSLOCK 0x3A +#define SCAN_A 0x1E +#define SCAN_S 0x1F +#define SCAN_D 0x20 +#define SCAN_F 0x21 +#define SCAN_G 0x22 +#define SCAN_H 0x23 +#define SCAN_J 0x24 +#define SCAN_K 0x25 +#define SCAN_L 0x26 +#define SCAN_SEMICOLON 0x27 +#define SCAN_APOSTROPHE 0x28 +#define SCAN_ENTER 0x1C +#define SCAN_LEFTSHIFT 0x2A +#define SCAN_Z 0x2C +#define SCAN_X 0x2D +#define SCAN_C 0x2E +#define SCAN_V 0x2F +#define SCAN_B 0x30 +#define SCAN_N 0x31 +#define SCAN_M 0x32 +#define SCAN_COMMA 0x33 +#define SCAN_PERIOD 0x34 +#define SCAN_SLASH 0x35 +#define SCAN_RIGHTSHIFT 0x36 +#define SCAN_LEFTCONTROL 0x1D +#define SCAN_LEFTALT 0x38 +#define SCAN_SPACE 0x39 + +/* Extended keys. */ +#define SCAN_RIGHTALT (0x38|0x80) +#define SCAN_RIGHTCONTROL (0x1D|0x80) +#define SCAN_BL_INSERT (0x52|0x80) +#define SCAN_BL_DELETE (0x53|0x80) +#define SCAN_BL_CURSORLEFT (0x4B|0x80) +#define SCAN_BL_HOME (0x47|0x80) +#define SCAN_BL_END (0x4F|0x80) +#define SCAN_BL_CURSORUP (0x48|0x80) +#define SCAN_BL_CURSORDOWN (0x50|0x80) +#define SCAN_BL_PAGEUP (0x49|0x80) +#define SCAN_BL_PAGEDOWN (0x51|0x80) +#define SCAN_BL_CURSORRIGHT (0x4D|0x80) + +#define SCAN_SCROLLLOCK 0x46 +/* Keys often found in the key pad area. */ +#define SCAN_NUMLOCK 0x45 +#define SCAN_HOME 0x47 +#define SCAN_CURSORLEFT 0x4B +#define SCAN_END 0x4F +#define SCAN_SLASH 0x35 +#define SCAN_CURSORUP 0x48 +#define SCAN_CENTER 0x4C +#define SCAN_CURSORDOWN 0x50 +#define SCAN_INSERT 0x52 +#define SCAN_PAUSE 0xC5 +#define SCAN_ASTERISK 0x37 +#define SCAN_PAGEUP 0x49 +#define SCAN_CURSORRIGHT 0x4D +#define SCAN_PAGEDOWN 0x51 +#define SCAN_DELETE 0x53 +#define SCAN_KP_MINUS 0x4A +#define SCAN_KP_PLUS 0x4E +#define SCAN_KP_ENTER 0x1C + +#define SCAN_ESCAPE 0x01 +#define SCAN_F1 0x3B +#define SCAN_F2 0x3C +#define SCAN_F3 0x3D +#define SCAN_F4 0x3E +#define SCAN_F5 0x3F +#define SCAN_F6 0x40 +#define SCAN_F7 0x41 +#define SCAN_F8 0x42 +#define SCAN_F9 0x43 +#define SCAN_F10 0x44 +#define SCAN_F11 0x57 +#define SCAN_F12 0x58 + +#define MK_COUNT 256 +#define MK(k) SCAN_##k + +#endif diff --git a/drivers/pc/main.c b/drivers/pc/main.c new file mode 100644 index 00000000..6bdd7ce7 --- /dev/null +++ b/drivers/pc/main.c @@ -0,0 +1,553 @@ +/* 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 +#include + +#include "main.h" +#include "throttle.h" + +#include "../common/cheat.h" + +#include "input.h" +#include "dface.h" + +extern int32 fps_scale; + +int CloseGame(void); + +static char *soundrecfn=0; /* File name of sound recording. */ + +static int ntsccol=0,ntschue=0,ntsctint=0; +int soundvol=100; +long soundq=0; +int _sound=1; +long soundrate=48000; +#ifdef WIN32 +long soundbufsize=52; +#else +long soundbufsize=24; +#endif + +#ifdef FRAMESKIP +static int frameskip=0; +#endif +static int inited=0; +static int isloaded=0; // Is game loaded? + +int srendlinev[2]={8,0}; +int erendlinev[2]={231,239}; + + +static uint8 *DrBaseDirectory; + +int eoptions=0; + +static void DriverKill(void); +static int DriverInitialize(FCEUGI *gi); +int gametype; + +FCEUGI *CurGame=NULL; + +static void ParseGI(FCEUGI *gi) +{ + ParseGIInput(gi); + gametype=gi->type; +} + +#ifndef EXTGUI +void FCEUD_PrintError(char *s) +{ + puts(s); +} + +void FCEUD_Message(char *s) +{ + fputs(s,stdout); +} +#endif + +static char *cpalette=0; +static void LoadCPalette(void) +{ + uint8 tmpp[192]; + FILE *fp; + + if(!(fp=FCEUD_UTF8fopen(cpalette,"rb"))) + { + printf(" Error loading custom palette from file: %s\n",cpalette); + return; + } + fread(tmpp,1,192,fp); + FCEUI_SetPaletteArray(tmpp); + fclose(fp); +} +#ifdef EXTGUI +extern CFGSTRUCT GUIConfig; +#endif +static CFGSTRUCT fceuconfig[]={ + AC(soundrate), + AC(soundq), + AC(_sound), + AC(soundvol), + AC(soundbufsize), + ACS(cpalette), + AC(ntsctint), + AC(ntschue), + AC(ntsccol), + AC(eoptions), + ACA(srendlinev), + ACA(erendlinev), + ADDCFGSTRUCT(InputConfig), + ADDCFGSTRUCT(DriverConfig), + #ifdef EXTGUI + ADDCFGSTRUCT(GUIConfig), + #endif + ENDCFGSTRUCT +}; + +static void SaveConfig(void) +{ + char tdir[2048]; + sprintf(tdir,"%s"PSS"fceu98.cfg",DrBaseDirectory); + FCEUI_GetNTSCTH(&ntsctint, &ntschue); + SaveFCEUConfig(tdir,fceuconfig); +} + +static void LoadConfig(void) +{ + char tdir[2048]; + sprintf(tdir,"%s"PSS"fceu98.cfg",DrBaseDirectory); + FCEUI_GetNTSCTH(&ntsctint, &ntschue); /* Get default settings for if + no config file exists. */ + LoadFCEUConfig(tdir,fceuconfig); + InputUserActiveFix(); +} + +static void CreateDirs(void) +{ + char *subs[7]={"fcs","fcm","snaps","gameinfo","sav","cheats","movie"}; + char tdir[2048]; + int x; + + #ifdef WIN32 + mkdir(DrBaseDirectory); + for(x=0;x<6;x++) + { + sprintf(tdir,"%s"PSS"%s",DrBaseDirectory,subs[x]); + mkdir(tdir); + } + #else + mkdir(DrBaseDirectory,S_IRWXU); + for(x=0;x<6;x++) + { + sprintf(tdir,"%s"PSS"%s",DrBaseDirectory,subs[x]); + mkdir(tdir,S_IRWXU); + } + #endif +} + +#ifndef WIN32 +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); +} +#endif + +static void DoArgs(int argc, char *argv[]) +{ + int x; + + static ARGPSTRUCT FCEUArgs[]={ + {"-soundbufsize",0,&soundbufsize,0}, + {"-soundrate",0,&soundrate,0}, + {"-soundq",0,&soundq,0}, +#ifdef FRAMESKIP + {"-frameskip",0,&frameskip,0}, +#endif + {"-sound",0,&_sound,0}, + {"-soundvol",0,&soundvol,0}, + {"-cpalette",0,&cpalette,0x4001}, + {"-soundrecord",0,&soundrecfn,0x4001}, + + {"-ntsccol",0,&ntsccol,0}, + {"-pal",0,&eoptions,0x8000|EO_PAL}, + + {"-lowpass",0,&eoptions,0x8000|EO_LOWPASS}, + {"-gg",0,&eoptions,0x8000|EO_GAMEGENIE}, + {"-no8lim",0,&eoptions,0x8001}, + {"-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}, + {0,(int *)InputArgs,0,0}, + {0,(int *)DriverArgs,0,0}, + {0,0,0,0} + }; + + ParseArguments(argc, argv, FCEUArgs); + if(cpalette) + { + if(cpalette[0]=='0') + if(cpalette[1]==0) + { + free(cpalette); + cpalette=0; + } + } + FCEUI_SetVidSystem((eoptions&EO_PAL)?1:0); + FCEUI_SetGameGenie((eoptions&EO_GAMEGENIE)?1:0); + FCEUI_SetLowPass((eoptions&EO_LOWPASS)?1:0); + + FCEUI_DisableSpriteLimitation(eoptions&1); + 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; + } + + FCEUI_SetRenderedLines(srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]); + DoDriverArgs(); +} + +#include "usage.h" + +/* Loads a game, given a full path/filename. The driver code must be + initialized after the game is loaded, because the emulator code + provides data necessary for the driver code(number of scanlines to + render, what virtual input devices to use, etc.). +*/ +int LoadGame(const char *path) +{ + FCEUGI *tmp; + + CloseGame(); + if(!(tmp=FCEUI_LoadGame(path,1))) + return 0; + CurGame=tmp; + ParseGI(tmp); + RefreshThrottleFPS(); + + if(!DriverInitialize(tmp)) + return(0); + if(soundrecfn) + { + if(!FCEUI_BeginWaveRecord(soundrecfn)) + { + free(soundrecfn); + soundrecfn=0; + } + } + isloaded=1; + #ifdef EXTGUI + if(eoptions&EO_AUTOHIDE) GUI_Hide(1); + #endif + + FCEUD_NetworkConnect(); + return 1; +} + +/* Closes a game. Frees memory, and deinitializes the drivers. */ +int CloseGame(void) +{ + if(!isloaded) return(0); + FCEUI_CloseGame(); + DriverKill(); + isloaded=0; + CurGame=0; + + if(soundrecfn) + FCEUI_EndWaveRecord(); + + #ifdef EXTGUI + GUI_Hide(0); + #endif + InputUserActiveFix(); + return(1); +} + +void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count); + +void DoFun(void) +{ + uint8 *gfx; + int32 *sound; + int32 ssize; + static int fskipc=0; + static int opause=0; + + #ifdef FRAMESKIP + fskipc=(fskipc+1)%(frameskip+1); + #endif + + if(NoWaiting) {gfx=0;} + FCEUI_Emulate(&gfx, &sound, &ssize, fskipc); + FCEUD_Update(gfx, sound, ssize); + + if(opause!=FCEUI_EmulationPaused()) + { + opause=FCEUI_EmulationPaused(); + SilenceSound(opause); + } +} + +int CLImain(int argc, char *argv[]) +{ + int ret; + + if(!(ret=FCEUI_Initialize())) + return(0); + + DrBaseDirectory=GetBaseDirectory(); + FCEUI_SetBaseDirectory(DrBaseDirectory); + + CreateDirs(); + + #ifdef EXTGUI + if(argc==2 && !strcmp(argv[1],"-help")) // I hope no one has a game named "-help" :b + #else + if(argc<=1) + #endif + { + ShowUsage(argv[0]); + return(0); + } + + LoadConfig(); + DoArgs(argc-2,&argv[1]); + FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue); + if(cpalette) + LoadCPalette(); + + /* All the config files and arguments are parsed now. */ + #ifdef EXTGUI + return(1); + + #else + if(!LoadGame(argv[argc-1])) + { + DriverKill(); + return(0); + } + + while(CurGame) + DoFun(); + + #if(0) + { + int x; + for(x=1;x= GetMaxSound() && fps_scale<=256) uflow=1; /* Go into massive underflow mode. */ + + if(can > Count) can=Count; + else uflow=0; + + WriteSound(Buffer,can); + + //if(uflow) puts("Underflow"); + tmpcan = GetWriteSound(); + // don't underflow when scaling fps + if(fps_scale>256 || ((tmpcan < Count*0.90) && !uflow)) + { + if(XBuf && (inited&4) && !(NoWaiting & 2)) + BlitScreen(XBuf); + Buffer+=can; + Count-=can; + if(Count) + { + if(NoWaiting) + { + can=GetWriteSound(); + if(Count>can) Count=can; + WriteSound(Buffer,Count); + } + else + { + while(Count>0) + { + WriteSound(Buffer,(Count= (Count * 1.8))) + { + if(Count > tmpcan) Count=tmpcan; + while(tmpcan > 0) + { +// printf("Overwrite: %d\n", (Count <= tmpcan)?Count : tmpcan); + WriteSound(Buffer, (Count <= tmpcan)?Count : tmpcan); + tmpcan -= Count; + } + } + #endif + + } + else + { + if(!NoWaiting && (!(eoptions&EO_NOTHROTTLE) || FCEUI_EmulationPaused())) + SpeedThrottle(); + if(XBuf && (inited&4)) + { + BlitScreen(XBuf); + } + } + FCEUD_UpdateInput(); + //if(!Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE)) + // SpeedThrottle(); + //if(XBuf && (inited&4)) + //{ + // BlitScreen(XBuf); + //} + //if(Count) + // WriteSound(Buffer,Count,NoWaiting); + //FCEUD_UpdateInput(); +} + + +/* Maybe ifndef WXWINDOWS would be better? ^_^ */ +#ifndef EXTGUI +FILE *FCEUD_UTF8fopen(const char *fn, const char *mode) +{ + return(fopen(fn,mode)); +} + + +#endif diff --git a/drivers/pc/main.h b/drivers/pc/main.h new file mode 100644 index 00000000..505eaf04 --- /dev/null +++ b/drivers/pc/main.h @@ -0,0 +1,55 @@ +/* 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 + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../driver.h" +#include "../common/config.h" +#include "../common/args.h" + +extern int eoptions; +#define EO_NO8LIM 1 +#define EO_SUBASE 2 +#define EO_CLIPSIDES 8 +#define EO_SNAPNAME 16 +#define EO_NOFOURSCORE 32 +#define EO_NOTHROTTLE 64 +#define EO_GAMEGENIE 128 +#define EO_PAL 256 +#define EO_LOWPASS 512 +#define EO_AUTOHIDE 1024 + +extern int srendlinev[2],erendlinev[2]; +extern int NoWaiting; + +extern int soundvol; +extern long soundq; +extern int _sound; +extern long soundrate; +extern long soundbufsize; + +int CLImain(int argc, char *argv[]); + +#ifdef __cplusplus +} +#endif + diff --git a/drivers/pc/sdl-icon.h b/drivers/pc/sdl-icon.h new file mode 100644 index 00000000..3a563d0b --- /dev/null +++ b/drivers/pc/sdl-icon.h @@ -0,0 +1,134 @@ +static const struct { + unsigned int width; + unsigned int height; + unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */ + uint8 pixel_data[32 * 32 * 3 + 1]; +} fceu_playicon = { + 32, 32, 3, + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223" + "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223" + "\373\\\223\373\\\223\373\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\267\317\373" + "\246\304\373\260\312\373\222\267\373\246\304\373\\\223\373\\\223\373\\\223" + "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373" + "\267\317\373\246\304\373\260\312\373\210\261\373\246\304\373\\\223\373\\" + "\223\373\210\261\373\222\267\373\267\317\373\241\301\373\\\223\373\\\223" + "\373\0\0\0\0\0\0\\\223\373\\\223\373\227\272\373\227\272\373\227\272\373" + "\227\272\373\227\272\373\227\272\373\\\223\373\\\223\373z`sr\242\373\227" + "\272\373\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\213\261\373" + "z\247\373\213\261\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\" + "\223\373\\\223\373\313i=\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40" + "\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40" + "\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\257T*\\\223\373\\\223\373\\\223" + "\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40" + "\355\235\203\355\235\203\341\232\205\341\232\205\365\255\233\355\235\203" + "\355\235\203\350\250\232\365\255\233\355\235\203\307L\14\307L\14\307L\14" + "\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373" + "\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373" + "\\\223\373\315Z\40\273zc\233l_\325\225\205\325\225\205\325\225\205\273\212" + "\201\325\225\205\237qd\325\225\205\317\231\216\307L\14\307L\14\307L\14\307" + "L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373\\" + "\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\" + "\223\373\315Z\40\344\232\203\301\215\201\344\232\203\273\212\201\325\225" + "\205\2114\10\344\232\203\350\250\232\325\225\205\333\230\205\307L\14\307" + "L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256" + "B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223" + "\373\\\223\373\\\223\373\315Z\40\2259\11}0\10\2259\11}0\10}0\10\307L\14\225" + "9\11d&\6}0\10}0\10\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14" + "\307L\14\307L\14\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373" + "\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\355\235\203" + "\355\233\201\355\235\203\355\235\203\355\235\203\365\255\233\355\235\203" + "\341\232\205\355\235\203\355\235\203\307L\14\365\255\233\355\235\203\365" + "\255\233\355\235\203\355\235\203\355\235\203\355\235\203\355\235\203\307" + "L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373" + "\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\311\221\204\311\221\204" + "\325\225\205\311\221\204\325\225\205\311\221\204\325\225\205\325\225\205" + "\311\221\204\307L\14\325\225\205\311\221\204\325\225\205\311\221\204\325" + "\225\205\311\221\204\325\225\205\311\221\204\307L\14\256B\12\\\223\373\\" + "\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\" + "\223\373\315Z\40\325\225\205\325\225\205\325\225\205\325\225\205\325\225" + "\205\325\225\205\317\231\216\325\225\205\325\225\205\325\225\205\307L\14" + "\325\225\205\317\231\216\325\225\205\317\231\216\325\225\205\325\225\205" + "\273zc\241n_\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0" + "\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325" + "\225\205\325\225\205\365\255\233\333\243\231\325\225\205\333\230\205\325" + "\225\205\325\225\205\325\225\205\307L\14\325\225\205\317\223\204\325\225" + "\205\333\230\205\325\225\205\325\225\205\333\230\205\317\223\204\307L\14" + "\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\" + "\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325\225\205\325\225\205" + "\325\225\205\311\221\204\325\225\205\325\225\205\325\225\205\344\232\203" + "\273\212\201\307L\14\325\225\205\273\212\201\325\225\205\325\225\205\344" + "\232\203\273\212\201\344\232\203\273\212\201\341\232\205\256B\12\\\223\373" + "\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373" + "\\\223\373\257T*d&\6d&\6d&\6d&\6d&\6d&\6d&\6d&\6}0\10d&\6\256B\12d&\6p+\7" + "d&\6d&\6}0\10d&\6}0\10d&\6d&\6\223@\26\\\223\373\\\223\373\\\223\373\\\223" + "\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223" + "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\234\243" + "\335\213\237\344\237\244\333\251\247\326\237\244\333\\\223\373\267\252\317" + "\222\241\341\267\252\317\210\237\346\241\245\332\267\252\317\246\246\327" + "\246\246\327\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223" + "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0" + "\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223" + "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\\\223\373\\\223\373\\\223\373\257hT\\\223\373\213\261\373\\\223" + "\373\241\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312" + "\373\\\223\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223" + "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\246\304\373\\\223\373\241" + "\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312\373\\\223" + "\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373\\\223\373" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373" + "\\\223\373\\\223\373D\203\270D\203\270\\\223\373\\\223\373\\\223\373\\\223" + "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0" + "\0\0\0\0\\\223\373\\\223\373(\211n\0\247\0\0n\0(\211n\\\223\373\\\223\373" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223" + "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373" + "\0\0\0\0\0\0\\\223\373(\211n\0\247\0\0\247\0\0\247\0\0\247\0(\211n\\\223" + "\373\\\223\373\\\223\373\\\223\373\210\261\373\246\304\373\241\301\373z\247" + "\373\\\223\373\227\272\373\227\272\373\227\272\373\227\272\373\227\272\373" + "\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373" + "\\\223\373\\\223\373\0\0\0\0\0\0(\211n\0\247\0\0n\0\0\247\0\\\215\12fs\16" + "\0\247\0(\211n\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\" + "\223\373\\\223\373Z\231Z[\230SZ\231Z[\230SZ\231Z[\230S\\\223\373\0\0\0\0" + "\0\0\0\247\0\0\247\0\0\247\0\0\247\0vy\7p|\7\0\247\0\0\247\0(\211n\\\223" + "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373" + "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373b\237L\200\317\20\200\317" + "\20\200\317\20\200\317\20\200\317\20\200\317\20[\223H\0\0\0\0\0\0\230P.\323" + "d0\230P.\323d0\221M&\313`%\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323" + "d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323" + "d0\230P.\323d0\230P.\323d0\0\0\0\0\0\0\0\0\0\237N(\225E\35\237N(\225E\35" + "\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237" + "N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(" + "\225E\35\237N(\225E\35\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", +}; + diff --git a/drivers/pc/sdl-joystick.c b/drivers/pc/sdl-joystick.c new file mode 100644 index 00000000..97f121f1 --- /dev/null +++ b/drivers/pc/sdl-joystick.c @@ -0,0 +1,99 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2002 Paul Kuliniewicz + * + * 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 + */ + +/* PK: SDL joystick input stuff */ + +#include +#include +#include +#include + +#include "sdl.h" + +#define MAX_JOYSTICKS 32 +static SDL_Joystick *Joysticks[MAX_JOYSTICKS] = {NULL}; + +int DTestButtonJoy(ButtConfig *bc) +{ + int x; + + for(x=0;xNumC;x++) + { + if(bc->ButtonNum[x]&0x8000) /* Axis "button" */ + { + int pos; + pos = SDL_JoystickGetAxis(Joysticks[bc->DeviceNum[x]], bc->ButtonNum[x]&16383); + if ((bc->ButtonNum[x]&0x4000) && pos <= -16383) + return(1); + else if (!(bc->ButtonNum[x]&0x4000) && pos >= 16363) + return(1); + } + else if(bc->ButtonNum[x]&0x2000) /* Hat "button" */ + { + if( SDL_JoystickGetHat(Joysticks[bc->DeviceNum[x]],(bc->ButtonNum[x]>>8)&0x1F) & (bc->ButtonNum[x]&0xFF)) + return(1); + } + else + if(SDL_JoystickGetButton(Joysticks[bc->DeviceNum[x]], bc->ButtonNum[x] )) + return(1); + } + return(0); +} + +static int jinited=0; + +/* Cleanup opened joysticks. */ +int KillJoysticks (void) +{ + int n; /* joystick index */ + + if(!jinited) return(0); + for (n = 0; n < MAX_JOYSTICKS; n++) + { + if (Joysticks[n] != 0) + SDL_JoystickClose(Joysticks[n]); + Joysticks[n]=0; + } + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + return(1); +} + +/* Initialize joysticks. */ +int InitJoysticks (void) +{ + int n; /* joystick index */ + int total; + + SDL_InitSubSystem(SDL_INIT_JOYSTICK); + total=SDL_NumJoysticks(); + if(total>MAX_JOYSTICKS) total=MAX_JOYSTICKS; + + for (n = 0; n < total; n++) + { + /* Open the joystick under SDL. */ + Joysticks[n] = SDL_JoystickOpen(n); + //printf("Could not open joystick %d: %s.\n", + //joy[n] - 1, SDL_GetError()); + continue; + } + jinited=1; + return(1); +} diff --git a/drivers/pc/sdl-netplay.c b/drivers/pc/sdl-netplay.c new file mode 100644 index 00000000..83de4ba5 --- /dev/null +++ b/drivers/pc/sdl-netplay.c @@ -0,0 +1,224 @@ +#include "sdl.h" +#include +#include "sdl-netplay.h" + +char *ServerHost; + +static int LocalPortTCP=0xFCE; +static int LocalPortUDP=0xFCE; +static int RemotePortTCP=0xFCE; + +static int RemotePortUDP; /* Not configurable, figured out during handshake. */ + +static TCPsocket Socket; +static UDPsocket UDPSocket; +static SDLNet_SocketSet set; + + +static void en32(uint8 *buf, uint32 morp) +{ + buf[0]=morp; + buf[1]=morp>>8; + buf[2]=morp>>16; + buf[3]=morp>>24; +} + +static uint32 de32(uint8 *morp) +{ + return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24)); +} + + + +int FCEUD_NetworkConnect(void) +{ + IPaddress rip; + + SDLNet_Init(); + + if(netplay==1) /* Be a server. */ + { + TCPsocket tmp; + Uint16 p=LocalPortUDP; + + SDLNet_ResolveHost(&rip,NULL,LocalPortTCP); + + UDPSocket=SDLNet_UDP_Open(&p); + + tmp=SDLNet_TCP_Open(&rip); + Socket=SDLNet_TCP_Accept(&tmp); + + memcpy(&rip,SDLNet_TCP_GetPeerAddress(Socket),sizeof(IPaddress)); + + { + uint8 buf[12]; + uint32 player=1; + + magic=SDL_GetTicks(); + + SDLNet_Write32(buf,uport); + SDLNet_Write32(buf+4,1); + SDLNet_Write32(buf+8,magic); + + SDLNet_TCP_Send(Socket, buf, 12); + + /* Get the UDP port the client is waiting for data on. */ + SDLNet_TCP_Recv(Socket, buf, 2); + RemotePortUDP=de32(buf); + } + } + else /* Be a client */ + { + SDLNet_ResolveHost(&rip,ServerHost,RemotePortTCP); + Socket=SDLNet_TCP_Open(&rip); + + { + Uint16 p=LocalPortUDP; + uint8 buf[12]; + + UDPSocket=SDLNet_UDP_Open(&p); + + /* Now, tell the server what local UDP port it should send to. */ + en32(buf,p); + SDLNet_TCP_Send(Socket, buf, 4); + + /* Get the UDP port from the server we should send data to. */ + SDLNet_TCP_Recv(Socket, buf, 12); + RemotePortUDP=de32(buf); + magic=de32(buf+8); + } + set=SDLNet_AllocSocketSet(1); + SDLNet_TCP_AddSocket(set,TCPSocket); + SDLNet_UDP_AddSocket(set,UDPSocket); + } // End client connect code. + + rip.port=RemotePortUDP; + SDLNet_UDP_Bind(UDPSocket, 0, &rip); +} + + + + +static int CheckUDP(uint8 *packet, int32 len, int32 alt) +{ + uint32 crc; + uint32 repcrc; + + crc=FCEUI_CRC32(0,packet+4,len+8); + repcrc=de32(packet); + + if(crc!=repcrc) return(0); /* CRC32 mismatch, bad packet. */ + packet+=4; + + if(de32(packet)!=magic) /* Magic number mismatch, bad or spoofed packet. */ + return(0); + + packet+=4; + if(alt) + { + if(de32(packet) +#include +#include +#else +#include +#include +#include +#endif +#include +#include + +#include "sdl.h" +#include "sdl-opengl.h" +#include "../common/vidblit.h" + +#ifndef APIENTRY +#define APIENTRY +#endif + +static GLuint textures[2]={0,0}; // Normal image, scanline overlay. + +static int left,right,top,bottom; // right and bottom are not inclusive. +static int scanlines; +static void *HiBuffer; + +void APIENTRY (*p_glBindTexture)(GLenum target,GLuint texture); +void APIENTRY (*p_glColorTableEXT)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +void APIENTRY (*p_glTexImage2D)( GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ); +void APIENTRY (*p_glBegin)(GLenum mode); +void APIENTRY (*p_glVertex2f)(GLfloat x, GLfloat y); +void APIENTRY (*p_glTexCoord2f)(GLfloat s, GLfloat t); +void APIENTRY (*p_glEnd)(void); +void APIENTRY (*p_glEnable)(GLenum cap); +void APIENTRY (*p_glBlendFunc)(GLenum sfactor, GLenum dfactor); +const GLubyte* APIENTRY (*p_glGetString)(GLenum name); +void APIENTRY (*p_glViewport)(GLint x, GLint y,GLsizei width, GLsizei height); +void APIENTRY (*p_glGenTextures)(GLsizei n, GLuint *textures); +void APIENTRY (*p_glDeleteTextures)(GLsizei n,const GLuint *textures); +void APIENTRY (*p_glTexParameteri)(GLenum target, GLenum pname, GLint param); +void APIENTRY (*p_glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +void APIENTRY (*p_glLoadIdentity)(void); +void APIENTRY (*p_glClear)(GLbitfield mask); +void APIENTRY (*p_glMatrixMode)(GLenum mode); +void APIENTRY (*p_glDisable)(GLenum cap); + +void SetOpenGLPalette(uint8 *data) +{ + if(!HiBuffer) + { + p_glBindTexture(GL_TEXTURE_2D, textures[0]); + p_glColorTableEXT(GL_TEXTURE_2D,GL_RGB,256,GL_RGBA,GL_UNSIGNED_BYTE,data); + } + else + SetPaletteBlitToHigh((uint8*)data); +} + +void BlitOpenGL(uint8 *buf) +{ + p_glBindTexture(GL_TEXTURE_2D, textures[0]); + if(HiBuffer) + { + static int xo=0; + xo=(xo+1)&3; + Blit8ToHigh(buf,(uint8*)HiBuffer,256,240,256*4,1,1); + if(!xo) + p_glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,256,256, 0, GL_RGBA,GL_UNSIGNED_BYTE, + HiBuffer); + } + else + { + //glPixelStorei(GL_UNPACK_ROW_LENGTH, 256); + p_glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, 256, 256, 0, + GL_COLOR_INDEX,GL_UNSIGNED_BYTE,buf); + } + + p_glBegin(GL_QUADS); + p_glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of our picture. + p_glVertex2f(-1.0f, -1.0f); // Bottom left of target. + + p_glTexCoord2f(1.0f*right/256, 1.0f*bottom/256); // Bottom right of our picture. + p_glVertex2f( 1.0f, -1.0f); // Bottom right of target. + + p_glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture. + p_glVertex2f( 1.0f, 1.0f); // Top right of target. + + p_glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture. + p_glVertex2f(-1.0f, 1.0f); // Top left of target. + p_glEnd(); + + //glDisable(GL_BLEND); + if(scanlines) + { + p_glEnable(GL_BLEND); + + p_glBindTexture(GL_TEXTURE_2D, textures[1]); + p_glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); + + p_glBegin(GL_QUADS); + + p_glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of our picture. + p_glVertex2f(-1.0f, -1.0f); // Bottom left of target. + + p_glTexCoord2f(1.0f*right/256, 1.0f*bottom/256); // Bottom right of our picture. + p_glVertex2f( 1.0f, -1.0f); // Bottom right of target. + + p_glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture. + p_glVertex2f( 1.0f, 1.0f); // Top right of target. + + p_glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture. + p_glVertex2f(-1.0f, 1.0f); // Top left of target. + + p_glEnd(); + p_glDisable(GL_BLEND); + } + SDL_GL_SwapBuffers(); +} + +void KillOpenGL(void) +{ + if(textures[0]) + p_glDeleteTextures(2, &textures[0]); + textures[0]=0; + if(HiBuffer) + { + free(HiBuffer); + HiBuffer=0; + } +} +/* Rectangle, left, right(not inclusive), top, bottom(not inclusive). */ + +int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate, + int stretchx, int stretchy, SDL_Surface *screen) +{ + const char *extensions; + + #define LFG(x) if(!(p_##x = SDL_GL_GetProcAddress(#x))) return(0); + + #define LFGN(x) p_##x = SDL_GL_GetProcAddress(#x) + + LFG(glBindTexture); + LFGN(glColorTableEXT); + LFG(glTexImage2D); + LFG(glBegin); + LFG(glVertex2f); + LFG(glTexCoord2f); + LFG(glEnd); + LFG(glEnable); + LFG(glBlendFunc); + LFG(glGetString); + LFG(glViewport); + LFG(glGenTextures); + LFG(glDeleteTextures); + LFG(glTexParameteri); + LFG(glClearColor); + LFG(glLoadIdentity); + LFG(glClear); + LFG(glMatrixMode); + LFG(glDisable); + + left=l; + right=r; + top=t; + bottom=b; + + HiBuffer=0; + + extensions=(const char*)p_glGetString(GL_EXTENSIONS); + + if((efx&2) || !extensions || !p_glColorTableEXT || !strstr(extensions,"GL_EXT_paletted_texture")) + { + if(!(efx&2)) // Don't want to print out a warning message in this case... + FCEU_printf("Paletted texture extension not found. Using slower texture format..."); + HiBuffer=malloc(4*256*256); + memset(HiBuffer,0x00,4*256*256); + #ifndef LSB_FIRST + InitBlitToHigh(4,0xFF000000,0xFF0000,0xFF00,efx&2,0); + #else + InitBlitToHigh(4,0xFF,0xFF00,0xFF0000,efx&2,0); + #endif + } + + { + int rw=(r-l)*xscale; + int rh=(b-t)*yscale; + int sx=(screen->w-rw)/2; // Start x + int sy=(screen->h-rh)/2; // Start y + + if(stretchx) { sx=0; rw=screen->w; } + if(stretchy) { sy=0; rh=screen->h; } + p_glViewport(sx, sy, rw, rh); + } + p_glGenTextures(2, &textures[0]); + scanlines=0; + + if(efx&1) + { + uint8 *buf; + int x,y; + + scanlines=1; + + p_glBindTexture(GL_TEXTURE_2D, textures[1]); + p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST); + p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST); + + buf=(uint8*)malloc(256*(256*2)*4); + + for(y=0;y<(256*2);y++) + for(x=0;x<256;x++) + { + buf[y*256*4+x*4]=0; + buf[y*256*4+x*4+1]=0; + buf[y*256*4+x*4+2]=0; + buf[y*256*4+x*4+3]=(y&1)?0x00:0xFF; //?0xa0:0xFF; // <-- Pretty + //buf[y*256+x]=(y&1)?0x00:0xFF; + } + p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, (scanlines==2)?256*4:512, 0, + GL_RGBA,GL_UNSIGNED_BYTE,buf); + free(buf); + } + p_glBindTexture(GL_TEXTURE_2D, textures[0]); + + p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST); + p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST); + p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); + p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); + p_glEnable(GL_TEXTURE_2D); + p_glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black. + p_glMatrixMode(GL_MODELVIEW); + + p_glClear(GL_COLOR_BUFFER_BIT); + p_glLoadIdentity(); + + return(1); +} diff --git a/drivers/pc/sdl-opengl.h b/drivers/pc/sdl-opengl.h new file mode 100644 index 00000000..ca786f53 --- /dev/null +++ b/drivers/pc/sdl-opengl.h @@ -0,0 +1,6 @@ +void SetOpenGLPalette(uint8 *data); +void BlitOpenGL(uint8 *buf); +void KillOpenGL(void); +int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate, + int stretchx, int stretchy, SDL_Surface *screen); + diff --git a/drivers/pc/sdl-sound.c b/drivers/pc/sdl-sound.c new file mode 100644 index 00000000..f0b522c1 --- /dev/null +++ b/drivers/pc/sdl-sound.c @@ -0,0 +1,373 @@ +/* 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 "sdl.h" + +#ifdef USE_SEXYAL + +#include "../sexyal/sexyal.h" + +static SexyAL *Interface; +static SexyAL_device *Output; +static SexyAL_format format; +static SexyAL_buffering buffering; + +uint32 GetMaxSound(void) +{ + return(buffering.totalsize); +} + +uint32 GetWriteSound(void) +{ + return(Output->CanWrite(Output)); +} + +void WriteSound(int32 *Buffer, int Count) +{ + //printf("%d\n",Output->CanWrite(Output)); + Output->Write(Output, Buffer, Count); +} + +int InitSound(FCEUGI *gi) +{ + if(!_sound) return(0); + + memset(&format,0,sizeof(format)); + memset(&buffering,0,sizeof(buffering)); + + FCEUI_SetSoundVolume(soundvol); + FCEUI_SetSoundQuality(soundq); + + Interface=SexyAL_Init(0); + + format.sampformat=SEXYAL_FMT_PCMS32S16; + format.channels=gi->soundchan?gi->soundchan:1; + format.rate=gi->soundrate?gi->soundrate:soundrate; + buffering.fragcount=buffering.fragsize=0; + buffering.ms=soundbufsize; + + FCEUI_printf("\nInitializing sound..."); + if(!(Output=Interface->Open(Interface,SEXYAL_ID_UNUSED,&format,&buffering))) + { + FCEUD_PrintError("Error opening a sound device."); + Interface->Destroy(Interface); + Interface=0; + return(0); + } + + if(soundq && format.rate!=48000 && format.rate!=44100 && format.rate!=96000) + { + FCEUD_PrintError("Set sound playback rate neither 44100, 48000, nor 96000, but needs to be when in high-quality sound mode."); + KillSound(); + return(0); + } + + if(format.rate<8192 || format.rate > 96000) + { + FCEUD_PrintError("Set rate is out of range [8192-96000]"); + KillSound(); + return(0); + } + FCEUI_printf("\n Bits: %u\n Rate: %u\n Channels: %u\n Byte order: CPU %s\n Buffer size: %u sample frames(%f ms)\n",(format.sampformat>>4)*8,format.rate,format.channels,format.byteorder?"Reversed":"Native",buffering.totalsize,(double)buffering.totalsize*1000/format.rate); + + format.sampformat=SEXYAL_FMT_PCMS32S16; + format.channels=gi->soundchan?gi->soundchan:1; + format.byteorder=0; + + //format.rate=gi->soundrate?gi->soundrate:soundrate; + + Output->SetConvert(Output,&format); + + FCEUI_Sound(format.rate); + return(1); +} + +void SilenceSound(int n) +{ + +} + +int KillSound(void) +{ + FCEUI_Sound(0); + if(Output) + Output->Close(Output); + if(Interface) + Interface->Destroy(Interface); + Interface=0; + if(!Output) return(0); + Output=0; + return(1); +} + +#elif USE_JACKACK /* Use JACK Audio Connection Kit */ + +#include +#include + +static jack_port_t *output_port = NULL; +static jack_client_t *client = NULL; +static jack_ringbuffer_t *tmpbuf = NULL; +static unsigned int BufferSize; + +static int process(jack_nframes_t nframes, void *arg) +{ + jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer(output_port, nframes); + size_t canread; + + canread = jack_ringbuffer_read_space(tmpbuf) / sizeof(jack_default_audio_sample_t); + + if(canread > nframes) + canread = nframes; + + jack_ringbuffer_read(tmpbuf, out,canread * sizeof(jack_default_audio_sample_t)); + nframes -= canread; + + if(nframes) /* Buffer underflow. Hmm. */ + { + + } + +} + +uint32 GetMaxSound(void) +{ + return(BufferSize); +} + +uint32 GetWriteSound(void) +{ + return(jack_readbuffer_write_space / sizeof(jack_default_audio_sample_t)); +} + + +static void DeadSound(void *arg) +{ + puts("AGH! Sound server hates us! Let's go on a rampage."); +} + +int InitSound(FCEUGI *gi) +{ + const char **ports; + + client = jack_client_new("FCE Ultra"); + + jack_set_process_callback(client, process, 0); + jack_on_shutdown(client, DeadSound, 0); + + printf("%ld\n",jack_get_sample_rate(client)); + + output_port = jack_port_register(client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + + BufferSize = soundbufsize * soundrate / 1000; + + tmpbuf = jack_ringbuffer_create(BufferSize * sizeof(jack_default_audio_sample_t)); + + jack_activate(client); + + + ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical | JackPortIsInput); + jack_connect(client, jack_port_name(output_port), ports[0]); + free(ports); +} + +void WriteSound(int32 *buf, int Count) +{ + jack_default_audio_sample_t jbuf[Count]; + int x; + + for(x=0;x>= 1; + + while(len) + { + int16 sample = 0; + if(BufferIn) + { + sample = Buffer[BufferRead]; + BufferRead = (BufferRead + 1) % BufferSize; + BufferIn--; + } + else sample = 0; + + *tmps = sample; + tmps++; + len--; + } +} + +int InitSound(FCEUGI *gi) +{ + SDL_AudioSpec spec; + if(!_sound) return(0); + + memset(&spec,0,sizeof(spec)); + if(SDL_InitSubSystem(SDL_INIT_AUDIO)<0) + { + puts(SDL_GetError()); + KillSound(); + return(0); + } + + spec.freq = soundrate; + spec.format = AUDIO_S16SYS; + spec.channels = 1; + spec.samples = 256; + spec.callback = fillaudio; + spec.userdata = 0; + + BufferSize = soundbufsize * soundrate / 1000; + + BufferSize -= spec.samples * 2; /* SDL uses at least double-buffering, so + multiply by 2. */ + + if(BufferSize < spec.samples) BufferSize = spec.samples; + + Buffer = malloc(sizeof(int) * BufferSize); + BufferRead = BufferWrite = BufferIn = 0; + + //printf("SDL Size: %d, Internal size: %d\n",spec.samples,BufferSize); + + if(SDL_OpenAudio(&spec,0)<0) + { + puts(SDL_GetError()); + KillSound(); + return(0); + } + SDL_PauseAudio(0); + FCEUI_Sound(soundrate); + return(1); +} + + +uint32 GetMaxSound(void) +{ + return(BufferSize); +} + +uint32 GetWriteSound(void) +{ + return(BufferSize - BufferIn); +} + +void WriteSound(int32 *buf, int Count) +{ + while(Count) + { + while(BufferIn == BufferSize) SDL_Delay(1); + Buffer[BufferWrite] = *buf; + Count--; + BufferWrite = (BufferWrite + 1) % BufferSize; + BufferIn++; + buf++; + } +} + +void SilenceSound(int n) +{ + SDL_PauseAudio(n); +} + +int KillSound(void) +{ + FCEUI_Sound(0); + SDL_CloseAudio(); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + if(Buffer) + { + free(Buffer); + Buffer = 0; + } + return(0); +} + + +#endif + + +static int mute=0; +static int soundvolume=100; +void FCEUD_SoundVolumeAdjust(int n) +{ + switch(n) + { + case -1: soundvolume-=10; if(soundvolume<0) soundvolume=0; break; + case 0: soundvolume=100; break; + case 1: soundvolume+=10; if(soundvolume>150) soundvolume=150; break; + } + mute=0; + FCEUI_SetSoundVolume(soundvolume); + FCEU_DispMessage("Sound volume %d.", soundvolume); +} +void FCEUD_SoundToggle(void) +{ + if(mute) + { + mute=0; + FCEUI_SetSoundVolume(soundvolume); + FCEU_DispMessage("Sound mute off."); + } + else + { + mute=1; + FCEUI_SetSoundVolume(0); + FCEU_DispMessage("Sound mute on."); + } +} diff --git a/drivers/pc/sdl-throttle.c b/drivers/pc/sdl-throttle.c new file mode 100644 index 00000000..253ad885 --- /dev/null +++ b/drivers/pc/sdl-throttle.c @@ -0,0 +1,86 @@ +#include "sdl.h" +#include "throttle.h" + +static uint64 tfreq; +static uint64 desiredfps; + +static int32 fps_scale_table[]= +{ 3, 3, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 2048 }; +int32 fps_scale = 256; + +#define fps_table_size (sizeof(fps_scale_table)/sizeof(fps_scale_table[0])) + +void RefreshThrottleFPS(void) +{ + desiredfps=FCEUI_GetDesiredFPS()>>8; + desiredfps=(desiredfps*fps_scale)>>8; + tfreq=10000000; + tfreq<<=16; /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */ +} + +void SpeedThrottle(void) +{ + static uint64 ttime,ltime=0; + + waiter: + + ttime=SDL_GetTicks(); + ttime*=10000; + + if( (ttime-ltime) < (tfreq/desiredfps) ) + { + int64 delay; + delay=(tfreq/desiredfps)-(ttime-ltime); + if(delay>0) + SDL_Delay(delay/10000); + //printf("%d\n",(tfreq/desiredfps)-(ttime-ltime)); + //SDL_Delay((tfreq/desiredfps)-(ttime-ltime)); + goto waiter; + } + if( (ttime-ltime) >= (tfreq*4/desiredfps)) + ltime=ttime; + else + ltime+=tfreq/desiredfps; +} + +void IncreaseEmulationSpeed(void) +{ + int i; + for(i=1; fps_scale_table[i]>8); +} + +void DecreaseEmulationSpeed(void) +{ + int i; + for(i=1; fps_scale_table[i]>8); +} + +void FCEUD_SetEmulationSpeed(int cmd) +{ + switch(cmd) + { + case EMUSPEED_SLOWEST: fps_scale=fps_scale_table[0]; break; + case EMUSPEED_SLOWER: DecreaseEmulationSpeed(); break; + case EMUSPEED_NORMAL: fps_scale=256; break; + case EMUSPEED_FASTER: IncreaseEmulationSpeed(); break; + case EMUSPEED_FASTEST: fps_scale=fps_scale_table[fps_table_size-1]; break; + default: + return; + } + + RefreshThrottleFPS(); + + FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8); +} diff --git a/drivers/pc/sdl-video.c b/drivers/pc/sdl-video.c new file mode 100644 index 00000000..5886f0fb --- /dev/null +++ b/drivers/pc/sdl-video.c @@ -0,0 +1,432 @@ +/* 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 "sdl.h" +#include "sdl-opengl.h" +#include "../common/vidblit.h" + +#include "sdl-icon.h" +#include "dface.h" + +SDL_Surface *screen; +SDL_Surface *BlitBuf; // Used as a buffer when using hardware-accelerated blits. +SDL_Surface *IconSurface=NULL; + +static int curbpp; +static int srendline,erendline; +static int tlines; +static int inited=0; + +#ifdef OPENGL +extern int sdlhaveogl; +static int usingogl; +static double exs,eys; +#else +static int exs,eys; +#endif +static int eefx; + +#define NWIDTH (256-((eoptions&EO_CLIPSIDES)?16:0)) +#define NOFFSET (eoptions&EO_CLIPSIDES?8:0) + + +static int paletterefresh; + +/* Return 1 if video was killed, 0 otherwise(video wasn't initialized). */ +int KillVideo(void) +{ + if(IconSurface) + { + SDL_FreeSurface(IconSurface); + IconSurface=0; + } + + if(inited&1) + { + #ifdef OPENGL + if(usingogl) + KillOpenGL(); + else + #endif + if(curbpp>8) + KillBlitToHigh(); + SDL_QuitSubSystem(SDL_INIT_VIDEO); + inited&=~1; + return(1); + } + inited=0; + return(0); +} + +static int sponge; + +int InitVideo(FCEUGI *gi) +{ + const SDL_VideoInfo *vinf; + int flags=0; + + FCEUI_printf("Initializing video..."); + + FCEUI_GetCurrentVidSystem(&srendline,&erendline); + + if(_fullscreen) sponge=Settings.specialfs; + else sponge=Settings.special; + + + #ifdef OPENGL + usingogl=0; + if(_opengl && sdlhaveogl && !sponge) + { + flags=SDL_OPENGL; + usingogl=1; + } + #endif + + #ifdef EXTGUI + GUI_SetVideo(_fullscreen, 0, 0); + #endif + + if(!(SDL_WasInit(SDL_INIT_VIDEO)&SDL_INIT_VIDEO)) + if(SDL_InitSubSystem(SDL_INIT_VIDEO)==-1) + { + FCEUD_PrintError(SDL_GetError()); + return(0); + } + inited|=1; + + SDL_ShowCursor(0); + tlines=erendline-srendline+1; + + vinf=SDL_GetVideoInfo(); + + if(vinf->hw_available) + flags|=SDL_HWSURFACE; + + if(_fullscreen) + flags|=SDL_FULLSCREEN; + + flags|=SDL_HWPALETTE; + + //flags|=SDL_DOUBLEBUF; + #ifdef OPENGL + if(usingogl) + { + FCEU_printf("\n Initializing with OpenGL(Use \"-opengl 0\" to disable).\n"); + if(_doublebuf) + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + } + else + #endif + if(_doublebuf && (flags&SDL_HWSURFACE)) + flags|=SDL_DOUBLEBUF; + + if(_fullscreen) + { + int desbpp=_bpp; + + exs=_xscalefs; + eys=_yscalefs; + eefx=_efxfs; + + #ifdef OPENGL + if(!usingogl) {exs=(int)exs;eys=(int)eys;} + else desbpp=0; + + if(sponge) + { + exs=eys=2; + if(sponge == 3 || sponge == 4) exs = eys = 3; + eefx=0; + if(sponge == 1 || sponge == 3) desbpp = 32; + } + + + if( (usingogl && !_stretchx) || !usingogl) + #endif + if(_xres= 3) exs=eys=3; + eefx=0; + // SDL's 32bpp->16bpp code is slighty faster than mine, at least :/ + if(sponge == 1 || sponge == 3) desbpp=32; + } + + #ifdef OPENGL + if(!usingogl) {exs=(int)exs;eys=(int)eys;} + if(exs <= 0.01) + { + FCEUD_PrintError("xscale out of bounds."); + KillVideo(); + return(0); + } + if(eys <= 0.01) + { + FCEUD_PrintError("yscale out of bounds."); + KillVideo(); + return(0); + } + #endif + + #ifdef EXTGUI + GUI_SetVideo(_fullscreen, (NWIDTH*exs), tlines*eys); + #endif + + screen = SDL_SetVideoMode((NWIDTH*exs), tlines*eys, desbpp, flags); + } + curbpp=screen->format->BitsPerPixel; + if(!screen) + { + FCEUD_PrintError(SDL_GetError()); + KillVideo(); + return(0); + } + //BlitBuf=SDL_CreateRGBSurface(SDL_HWSURFACE,256,240,screen->format->BitsPerPixel,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,0); + + inited=1; + + FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n",screen->w,screen->h,screen->format->BitsPerPixel,_fullscreen?"full screen":""); + if(curbpp!=16 && curbpp!=24 && curbpp!=8 && curbpp!=32) + { + FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n",curbpp); + KillVideo(); + return(0); + } + + if(gi->name) + SDL_WM_SetCaption(gi->name,gi->name); + else + SDL_WM_SetCaption("FCE Ultra","FCE Ultra"); + + #ifdef LSB_FIRST + IconSurface=SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,32,32,24,32*3,0xFF,0xFF00,0xFF0000,0x00); + #else + IconSurface=SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,32,32,24,32*3,0xFF0000,0xFF00,0xFF,0x00); + #endif + + SDL_WM_SetIcon(IconSurface,0); + + paletterefresh=1; + + if(curbpp>8) + #ifdef OPENGL + if(!usingogl) + #endif + InitBlitToHigh(curbpp>>3,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,eefx,sponge); + #ifdef OPENGL + if(usingogl) + if(!InitOpenGL((eoptions&EO_CLIPSIDES)?8:0,256-((eoptions&EO_CLIPSIDES)?8:0),srendline,erendline+1,exs,eys,eefx,_openglip,_stretchx,_stretchy,screen)) + { + FCEUD_PrintError("Error initializing OpenGL."); + KillVideo(); + return(0); + } + #endif + return 1; +} + +void ToggleFS(void) +{ + extern FCEUGI *CurGame; + KillVideo(); + _fullscreen=!_fullscreen; + + if(!InitVideo(CurGame)) + { + _fullscreen=!_fullscreen; + InitVideo(CurGame); + } +} + +static SDL_Color psdl[256]; +void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b) +{ + psdl[index].r=r; + psdl[index].g=g; + psdl[index].b=b; + + paletterefresh=1; +} + +void FCEUD_GetPalette(uint8 index, uint8 *r, uint8 *g, uint8 *b) +{ + *r=psdl[index].r; + *g=psdl[index].g; + *b=psdl[index].b; +} + +static void RedoPalette(void) +{ + #ifdef OPENGL + if(usingogl) + SetOpenGLPalette((uint8*)psdl); + else + #endif + { + if(curbpp>8) + SetPaletteBlitToHigh((uint8*)psdl); + else + { + SDL_SetPalette(screen,SDL_PHYSPAL,psdl,0,256); + } + } +} + +void LockConsole(){} +void UnlockConsole(){} +void BlitScreen(uint8 *XBuf) +{ + SDL_Surface *TmpScreen; + uint8 *dest; + int xo=0,yo=0; + + if(!screen) return; + + if(paletterefresh) + { + RedoPalette(); + paletterefresh=0; + } + + #ifdef OPENGL + if(usingogl) + { + BlitOpenGL(XBuf); + return; + } + #endif + + XBuf+=srendline*256; + + if(BlitBuf) TmpScreen=BlitBuf; + else TmpScreen=screen; + + if(SDL_MUSTLOCK(TmpScreen)) + if(SDL_LockSurface(TmpScreen)) + { + return; + } + + dest=(uint8*)TmpScreen->pixels; + + if(_fullscreen) + { + xo=(((TmpScreen->w-NWIDTH*exs))/2); + dest+=xo*(curbpp>>3); + if(TmpScreen->h>(tlines*eys)) + { + yo=((TmpScreen->h-tlines*eys)/2); + dest+=yo*TmpScreen->pitch; + } + } + + if(curbpp>8) + { + if(BlitBuf) + Blit8ToHigh(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,1,1); + else + Blit8ToHigh(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,exs,eys); + } + else + { + if(BlitBuf) + Blit8To8(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,1,1,0,sponge); + else + Blit8To8(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,exs,eys,eefx,sponge); + } + if(SDL_MUSTLOCK(TmpScreen)) + SDL_UnlockSurface(TmpScreen); + + if(BlitBuf) + { + SDL_Rect srect; + SDL_Rect drect; + + srect.x=0; + srect.y=0; + srect.w=NWIDTH; + srect.h=tlines; + + drect.x=0; + drect.y=0; + drect.w=exs*NWIDTH; + drect.h=eys*tlines; + + SDL_BlitSurface(BlitBuf, &srect,screen,&drect); + } + + SDL_UpdateRect(screen, xo, yo, NWIDTH*exs, tlines*eys); + + if(screen->flags&SDL_DOUBLEBUF) + SDL_Flip(screen); +} + +uint32 PtoV(uint16 x, uint16 y) +{ + y=(double)y/eys; + x=(double)x/exs; + if(eoptions&EO_CLIPSIDES) + x+=8; + y+=srendline; + return(x|(y<<16)); +} diff --git a/drivers/pc/sdl-video.h b/drivers/pc/sdl-video.h new file mode 100644 index 00000000..4a4f056d --- /dev/null +++ b/drivers/pc/sdl-video.h @@ -0,0 +1 @@ +uint32 PtoV(uint16 x, uint16 y); diff --git a/drivers/pc/sdl.c b/drivers/pc/sdl.c new file mode 100644 index 00000000..c2e939fc --- /dev/null +++ b/drivers/pc/sdl.c @@ -0,0 +1,429 @@ +#include +#include +#include + +#include "sdl.h" +#include "sdl-video.h" +#ifdef NETWORK +#include "unix-netplay.h" +#endif + +DSETTINGS Settings; +CFGSTRUCT DriverConfig[]={ + #ifdef OPENGL + AC(_stretchx), + AC(_stretchy), + AC(_opengl), + AC(_openglip), + #endif + AC(Settings.special), + AC(Settings.specialfs), + AC(_doublebuf), + AC(_xscale), + AC(_yscale), + AC(_xscalefs), + AC(_yscalefs), + AC(_bpp), + AC(_efx), + AC(_efxfs), + AC(_fullscreen), + AC(_xres), + AC(_yres), + #ifdef NETWORK + ACS(netplaynick), + AC(netlocalplayers), + AC(tport), + ACS(netpassword), + ACS(netgamekey), + #endif + 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(Real numbers >0 with OpenGL, otherwise integers >0).\n\ +-yscale(fs) x Multiply height by x(Real numbers >0 with OpenGL, otherwise integers >0).\n\ +-bpp(fs) x Bits per pixel for SDL surface(and video mode in fs). 8, 16, 32.\n\ +-opengl x Enable OpenGL support if x is 1.\n\ +-openglip x Enable OpenGL linear interpolation if x is 1.\n\ +-doublebuf x \n\ +-special(fs) x Specify special scaling filter.\n\ +-stretch(x/y) x Stretch to fill surface on x or y axis(fullscreen, only with OpenGL).\n\ +-efx(fs) x Enable special effects. Logically OR the following together:\n\ + 1 = scanlines(for yscale>=2).\n\ + 2 = TV blur(for bpp of 16 or 32).\n\ +-fs x Select full screen mode if x is non zero.\n\ +-connect s Connect to server 's' for TCP/IP network play.\n\ +-netnick s Set the nickname to use in network play.\n\ +-netgamekey s Use key 's' to create a unique session for the game loaded.\n\ +-netpassword s Password to use for connecting to the server.\n\ +-netlocalplayers x Set the number of local players.\n\ +-netport x Use TCP/IP port x for network play."; + +ARGPSTRUCT DriverArgs[]={ + #ifdef OPENGL + {"-opengl",0,&_opengl,0}, + {"-openglip",0,&_openglip,0}, + {"-stretchx",0,&_stretchx,0}, + {"-stretchy",0,&_stretchy,0}, + #endif + {"-special",0,&Settings.special,0}, + {"-specialfs",0,&Settings.specialfs,0}, + {"-doublebuf",0,&_doublebuf,0}, + {"-bpp",0,&_bpp,0}, + {"-xscale",0,&_xscale,2}, + {"-yscale",0,&_yscale,2}, + {"-efx",0,&_efx,0}, + {"-xscalefs",0,&_xscalefs,2}, + {"-yscalefs",0,&_yscalefs,2}, + {"-efxfs",0,&_efxfs,0}, + {"-xres",0,&_xres,0}, + {"-yres",0,&_yres,0}, + {"-fs",0,&_fullscreen,0}, + //{"-fshack",0,&_fshack,0x4001}, + #ifdef NETWORK + {"-connect",0,&netplayhost,0x4001}, + {"-netport",0,&tport,0}, + {"-netlocalplayers",0,&netlocalplayers,0}, + {"-netnick",0,&netplaynick,0x4001}, + {"-netpassword",0,&netpassword,0x4001}, + #endif + {0,0,0,0} +}; + +static void SetDefaults(void) +{ + Settings.special=Settings.specialfs=0; + _bpp=8; + _xres=640; + _yres=480; + _fullscreen=0; + _xscale=2.50; + _yscale=2; + _xscalefs=_yscalefs=2; + _efx=_efxfs=0; + //_fshack=_fshacksave=0; +#ifdef OPENGL + _opengl=1; + _stretchx=1; + _stretchy=0; + _openglip=1; +#endif +} + +void DoDriverArgs(void) +{ + #ifdef BROKEN + if(_fshack) + { + if(_fshack[0]=='0') + if(_fshack[1]==0) + { + free(_fshack); + _fshack=0; + } + } + #endif +} + +int InitMouse(void) +{ + return(0); +} + +void KillMouse(void){} + +void GetMouseData(uint32 *d) +{ + if(FCEUI_IsMovieActive()<0) + return; + + int x,y; + uint32 t; + + t=SDL_GetMouseState(&x,&y); + #ifdef EXTGUI + GUI_GetMouseState(&t,&x,&y); + #endif + + d[2]=0; + if(t&SDL_BUTTON(1)) + d[2]|=1; + if(t&SDL_BUTTON(3)) + d[2]|=2; + t=PtoV(x,y); + d[0]=t&0xFFFF; + d[1]=(t>>16)&0xFFFF; +} + +int InitKeyboard(void) +{ + return(1); +} + +int UpdateKeyboard(void) +{ + return(1); +} + +void KillKeyboard(void) +{ + +} + + +void UpdatePhysicalInput(void) +{ + SDL_Event event; + + while(SDL_PollEvent(&event)) + { + switch(event.type) + { + //case SDL_SYSWMEVENT: puts("Nifty keen");break; + //case SDL_VIDEORESIZE: puts("Okie dokie");break; + case SDL_QUIT: CloseGame();puts("Quit");break; + } + //printf("Event: %d\n",event.type); + //fflush(stdout); + } + //SDL_PumpEvents(); +} + +static uint8 *KeyState=NULL; +char *GetKeyboard(void) +{ + KeyState=SDL_GetKeyState(0); + #ifdef EXTGUI + { char *tmp=GUI_GetKeyboard(); if(tmp) KeyState=tmp; } + #endif + return((char *)KeyState); +} + +#ifdef WIN32 +#include + + /* Stupid SDL */ + #ifdef main + #undef main + #endif +#endif + +#ifndef EXTGUI +uint8 *GetBaseDirectory(void) +{ + uint8 *ol; + uint8 *ret; + + ol=getenv("HOME"); + + if(ol) + { + ret=malloc(strlen(ol)+1+strlen("./fceultra")); + strcpy(ret,ol); + strcat(ret,"/.fceultra"); + } + else + { + #ifdef WIN32 + char *sa; + + ret=malloc(MAX_PATH+1); + GetModuleFileName(NULL,ret,MAX_PATH+1); + + sa=strrchr(ret,'\\'); + if(sa) + *sa = 0; + #else + ret=malloc(1); + ret[0]=0; + #endif + printf("%s\n",ret); + } + return(ret); +} +#endif + +#ifdef OPENGL +int sdlhaveogl; +#endif + + +int DTestButton(ButtConfig *bc) +{ + int x; + + for(x=0;xNumC;x++) + { + if(bc->ButtType[x]==BUTTC_KEYBOARD) + { + if(KeyState[bc->ButtonNum[x]]) + return(1); + } + else if(bc->ButtType[x]==BUTTC_JOYSTICK) + { + if(DTestButtonJoy(bc)) + return(1); + } + } + return(0); +} + +static int bcpv,bcpj; + +int ButtonConfigBegin(void) +{ + SDL_Surface *screen; + SDL_QuitSubSystem(SDL_INIT_VIDEO); + bcpv=KillVideo(); + bcpj=KillJoysticks(); + + if(!(SDL_WasInit(SDL_INIT_VIDEO)&SDL_INIT_VIDEO)) + if(SDL_InitSubSystem(SDL_INIT_VIDEO)==-1) + { + FCEUD_Message(SDL_GetError()); + return(0); + } + + screen = SDL_SetVideoMode(300, 1, 8, 0); + SDL_WM_SetCaption("Button Config",0); + InitJoysticks(); + + return(1); +} + +void ButtonConfigEnd(void) +{ + extern FCEUGI *CurGame; + KillJoysticks(); + SDL_QuitSubSystem(SDL_INIT_VIDEO); + if(bcpv) InitVideo(CurGame); + if(bcpj) InitJoysticks(); +} + +int DWaitButton(const uint8 *text, ButtConfig *bc, int wb) +{ + SDL_Event event; + static int32 LastAx[64][64]; + int x,y; + + SDL_WM_SetCaption(text,0); + #ifndef EXTGUI + puts(text); + #endif + for(x=0;x<64;x++) + for(y=0;y<64;y++) + LastAx[x][y]=0x100000; + + while(SDL_WaitEvent(&event)) + { + switch(event.type) + { + case SDL_KEYDOWN:bc->ButtType[wb]=BUTTC_KEYBOARD; + bc->DeviceNum[wb]=0; + bc->ButtonNum[wb]=event.key.keysym.sym; + return(1); + case SDL_JOYBUTTONDOWN:bc->ButtType[wb]=BUTTC_JOYSTICK; + bc->DeviceNum[wb]=event.jbutton.which; + bc->ButtonNum[wb]=event.jbutton.button; + return(1); + case SDL_JOYHATMOTION:if(event.jhat.value != SDL_HAT_CENTERED) + { + bc->ButtType[wb]=BUTTC_JOYSTICK; + bc->DeviceNum[wb]=event.jhat.which; + bc->ButtonNum[wb]=0x2000|((event.jhat.hat&0x1F)<<8)|event.jhat.value; + return(1); + } + break; + case SDL_JOYAXISMOTION: + if(LastAx[event.jaxis.which][event.jaxis.axis]==0x100000) + { + if(abs(event.jaxis.value)<1000) + LastAx[event.jaxis.which][event.jaxis.axis]=event.jaxis.value; + } + else + { + if(abs(LastAx[event.jaxis.which][event.jaxis.axis]-event.jaxis.value)>=8192) + { + bc->ButtType[wb]=BUTTC_JOYSTICK; + bc->DeviceNum[wb]=event.jaxis.which; + bc->ButtonNum[wb]=0x8000|(event.jaxis.axis)|((event.jaxis.value<0)?0x4000:0); + return(1); + } + } + break; + } + } + + return(0); +} + +#ifdef EXTGUI +int FCEUSDLmain(int argc, char *argv[]) +#else +int main(int argc, char *argv[]) +#endif +{ + FCEUD_Message("\nStarting FCE Ultra "FCEU_VERSION"...\n"); + + #ifdef WIN32 + /* Taken from win32 sdl_main.c */ + SDL_SetModuleHandle(GetModuleHandle(NULL)); + #endif + + if(SDL_Init(SDL_INIT_VIDEO)) /* SDL_INIT_VIDEO Needed for (joystick config) event processing? */ + { + printf("Could not initialize SDL: %s.\n", SDL_GetError()); + return(-1); + } + + #ifdef OPENGL + #ifdef APPLEOPENGL + sdlhaveogl = 1; /* Stupid something... Hack. */ + #else + if(!SDL_GL_LoadLibrary(0)) sdlhaveogl=1; + else sdlhaveogl=0; + #endif + #endif + + SetDefaults(); + + { + int ret=CLImain(argc,argv); + SDL_Quit(); + return(ret?0:-1); + } +} + + +uint64 FCEUD_GetTime(void) +{ + return(SDL_GetTicks()); +} + +uint64 FCEUD_GetTimeFreq(void) +{ + return(1000); +} + +// dummy functions + +#define DUMMY(f) void f(void) {FCEU_DispMessage("Not implemented.");} +DUMMY(FCEUD_HideMenuToggle) +DUMMY(FCEUD_TurboOn) +DUMMY(FCEUD_TurboOff) +DUMMY(FCEUD_SaveStateAs) +DUMMY(FCEUD_LoadStateFrom) +DUMMY(FCEUD_MovieRecordTo) +DUMMY(FCEUD_MovieReplayFrom) +DUMMY(FCEUD_ToggleStatusIcon) +DUMMY(FCEUD_AviRecordTo) +DUMMY(FCEUD_AviStop) +void FCEUI_AviVideoUpdate(const unsigned char* buffer) {FCEU_DispMessage("Not implemented.");} +int FCEUD_ShowStatusIcon(void) {FCEU_DispMessage("Not implemented."); return 0; } +int FCEUI_AviIsRecording(void) {return 0;} + diff --git a/drivers/pc/sdl.h b/drivers/pc/sdl.h new file mode 100644 index 00000000..791316a8 --- /dev/null +++ b/drivers/pc/sdl.h @@ -0,0 +1,50 @@ +#include +#include "main.h" +#include "dface.h" +#include "input.h" + +int DTestButtonJoy(ButtConfig *bc); + +typedef struct { + int xres; + int yres; + double xscale,yscale; + double xscalefs,yscalefs; + int efx,efxfs; + int bpp; + int fullscreen; + int doublebuf; + char *fshack; + char *fshacksave; + #ifdef OPENGL + int opengl; + int openglip; + int stretchx,stretchy; + #endif + int special,specialfs; +} DSETTINGS; + +extern DSETTINGS Settings; + +#define _doublebuf Settings.doublebuf +#define _bpp Settings.bpp +#define _xres Settings.xres +#define _yres Settings.yres +#define _fullscreen Settings.fullscreen +#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 _fshack Settings.fshack +#define _fshacksave Settings.fshacksave + +#ifdef OPENGL +#define _opengl Settings.opengl +#define _openglip Settings.openglip +#define _stretchx Settings.stretchx +#define _stretchy Settings.stretchy +#endif + diff --git a/drivers/pc/throttle.c b/drivers/pc/throttle.c new file mode 100644 index 00000000..422dad79 --- /dev/null +++ b/drivers/pc/throttle.c @@ -0,0 +1,41 @@ +#include +#include "main.h" +#include "throttle.h" + +static uint64 tfreq; +static uint64 desiredfps; + +void RefreshThrottleFPS(void) +{ + desiredfps=FCEUI_GetDesiredFPS()>>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); +} + +void SpeedThrottle(void) +{ + static uint64 ttime,ltime=0; + + waiter: + + ttime=GetCurTime(); + + if( (ttime-ltime) < (tfreq/desiredfps) ) + goto waiter; + if( (ttime-ltime) >= (tfreq*4/desiredfps)) + ltime=ttime; + else + ltime+=tfreq/desiredfps; +} + diff --git a/drivers/pc/throttle.h b/drivers/pc/throttle.h new file mode 100644 index 00000000..d6ca2aa8 --- /dev/null +++ b/drivers/pc/throttle.h @@ -0,0 +1,2 @@ +void RefreshThrottleFPS(void); +void SpeedThrottle(void); diff --git a/drivers/pc/unix-netplay.c b/drivers/pc/unix-netplay.c new file mode 100644 index 00000000..5bef56e2 --- /dev/null +++ b/drivers/pc/unix-netplay.c @@ -0,0 +1,292 @@ +#ifdef NETWORK +/* 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 +#include +#include +#include +#include +#include +#include "main.h" +#include "dface.h" +#include "unix-netplay.h" + +#include "../../md5.h" + +#ifndef socklen_t +#define socklen_t int +#endif + +#ifndef SOL_TCP +#define SOL_TCP IPPROTO_TCP +#endif + + +char *netplayhost=0; +char *netplaynick=0; +char *netgamekey = 0; +char *netpassword = 0; +int netlocalplayers = 1; + +int Port=0xFCE; +int FCEUDnetplay=0; + +int tport=0xFCE; + +static int Socket=-1; + +static void en32(uint8 *buf, uint32 morp) +{ + buf[0]=morp; + buf[1]=morp>>8; + buf[2]=morp>>16; + buf[3]=morp>>24; +} +/* +static uint32 de32(uint8 *morp) +{ + return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24)); +} +*/ +int FCEUD_NetworkConnect(void) +{ + struct sockaddr_in sockin; /* I want to play with fighting robots. */ + struct hostent *phostentb; + unsigned long hadr; + int TSocket; + int netdivisor; + + if(!netplayhost) return(0); + + if( (TSocket=socket(AF_INET,SOCK_STREAM,0))==-1) + { + puts("Error creating stream socket."); + FCEUD_NetworkClose(); + return(0); + } + + { + int tcpopt = 1; + #ifdef BEOS + if(setsockopt(TSocket, SOL_SOCKET, TCP_NODELAY, &tcpopt, sizeof(int))) + #else + if(setsockopt(TSocket, SOL_TCP, TCP_NODELAY, &tcpopt, sizeof(int))) + #endif + puts("Nodelay fail"); + } + + memset(&sockin,0,sizeof(sockin)); + sockin.sin_family=AF_INET; + + hadr=inet_addr(netplayhost); + + if(hadr!=INADDR_NONE) + sockin.sin_addr.s_addr=hadr; + else + { + puts("*** Looking up host name..."); + if(!(phostentb=gethostbyname((const char *)netplayhost))) + { + puts("Error getting host network information."); + close(TSocket); + FCEUD_NetworkClose(); + return(0); + } + memcpy(&sockin.sin_addr,phostentb->h_addr,phostentb->h_length); + } + + sockin.sin_port=htons(tport); + puts("*** Connecting to remote host..."); + if(connect(TSocket,(struct sockaddr *)&sockin,sizeof(sockin))==-1) + { + puts("Error connecting to remote host."); + close(TSocket); + FCEUD_NetworkClose(); + return(0); + } + Socket=TSocket; + puts("*** Sending initialization data to server..."); + { + uint8 *sendbuf; + uint8 buf[5]; + uint32 sblen; + + sblen = 4 + 16 + 16 + 64 + 1 + (netplaynick?strlen(netplaynick):0); + sendbuf = malloc(sblen); + memset(sendbuf, 0, sblen); + + en32(sendbuf, sblen - 4); + + if(netgamekey) + { + struct md5_context md5; + uint8 md5out[16]; + + md5_starts(&md5); + md5_update(&md5, CurGame->MD5, 16); + md5_update(&md5, netgamekey, strlen(netgamekey)); + md5_finish(&md5, md5out); + memcpy(sendbuf + 4, md5out, 16); + } + else + memcpy(sendbuf + 4, CurGame->MD5, 16); + + if(netpassword) + { + struct md5_context md5; + uint8 md5out[16]; + + md5_starts(&md5); + md5_update(&md5, netpassword, strlen(netpassword)); + md5_finish(&md5, md5out); + memcpy(sendbuf + 4 + 16, md5out, 16); + } + + memset(sendbuf + 4 + 16 + 16, 0, 64); + + sendbuf[4 + 16 + 16 + 64] = netlocalplayers; + + if(netplaynick) + memcpy(sendbuf + 4 + 16 + 16 + 64 + 1,netplaynick,strlen(netplaynick)); + + send(Socket, sendbuf, sblen, 0); + free(sendbuf); + + recv(Socket, buf, 1, MSG_WAITALL); + netdivisor = buf[0]; + } + + puts("*** Connection established."); + + FCEUDnetplay = 1; + FCEUI_NetplayStart(netlocalplayers, netdivisor); + return(1); +} + + +int FCEUD_SendData(void *data, uint32 len) +{ + int check; + if(!ioctl(fileno(stdin),FIONREAD,&check)) + if(check) + { + char buf[1024]; + char *f; + fgets(buf,1024,stdin); + if((f=strrchr(buf,'\n'))) + *f=0; + FCEUI_NetplayText(buf); + } + send(Socket, data, len ,0); + return(1); +} + +int FCEUD_RecvData(void *data, uint32 len) +{ + NoWaiting&=~2; + + for(;;) + { + fd_set funfun; + struct timeval popeye; + + popeye.tv_sec=0; + popeye.tv_usec=100000; + + FD_ZERO(&funfun); + FD_SET(Socket,&funfun); + + switch(select(Socket + 1,&funfun,0,0,&popeye)) + { + case 0: continue; + case -1:return(0); + } + + if(FD_ISSET(Socket,&funfun)) + { + if(recv(Socket,data,len,MSG_WAITALL) == len) + { + //unsigned long beefie; + + FD_ZERO(&funfun); + FD_SET(Socket, &funfun); + + popeye.tv_sec = popeye.tv_usec = 0; + if(select(Socket + 1, &funfun, 0, 0, &popeye) == 1) + //if(!ioctl(Socket,FIONREAD,&beefie)) + // if(beefie) + { + NoWaiting|=2; + //puts("Yaya"); + } + return(1); + } + else + return(0); + } + + } + return 0; +} + +void FCEUD_NetworkClose(void) +{ + if(Socket>0) + { + #ifdef BEOS + closesocket(Socket); + #else + close(Socket); + #endif + } + Socket=-1; + + if(FCEUDnetplay) + FCEUI_NetplayStop(); + FCEUDnetplay = 0; +} + + +void FCEUD_NetplayText(uint8 *text) +{ + char *tot = malloc(strlen(text) + 1); + char *tmp; + strcpy(tot, text); + tmp = tot; + + while(*tmp) + { + if(*tmp < 0x20) *tmp = ' '; + tmp++; + } + puts(tot); + free(tot); +} +#endif + diff --git a/drivers/pc/unix-netplay.h b/drivers/pc/unix-netplay.h new file mode 100644 index 00000000..dd6ed18a --- /dev/null +++ b/drivers/pc/unix-netplay.h @@ -0,0 +1,9 @@ +#ifdef NETWORK +extern char *netplaynick; +extern char *netplayhost; +extern char *netpassword; +extern char *netgamekey; +extern int tport; +extern int netlocalplayers; + +#endif diff --git a/drivers/pc/usage.h b/drivers/pc/usage.h new file mode 100644 index 00000000..b8833200 --- /dev/null +++ b/drivers/pc/usage.h @@ -0,0 +1,60 @@ +/* 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 + */ + +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 x Emulate a PAL NES if x is 1.\n\ +-sound x Sound.\n\ + 0 = Disabled.\n\ + Otherwise, x = playback rate.\n\ +-soundvol x Sound volume. x is an integral percentage value.\n\ +-soundq x Sets sound quality.\n\ + 0 = Low quality.\n\ + 1 = High quality.\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\ +-inputcfg s Configure virtual input device \"s\".\n\ +-nofs x Disables Four-Score emulation if x is 1.\n\ +-gg x Enable Game Genie emulation if x is 1.\n\ +-no8lim x Disables the 8 sprites per scanline limitation.\n\ + 0 = Limitation enabled.\n\ + 1 = Limitation disabled.\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."); +} diff --git a/drivers/pc/vgatweak.c b/drivers/pc/vgatweak.c new file mode 100644 index 00000000..a04cf94e --- /dev/null +++ b/drivers/pc/vgatweak.c @@ -0,0 +1,168 @@ +/* This file is "#include"d from dos-video.c and svga-video.c */ + +typedef struct { + uint8 p; + uint8 i; + uint8 v; +} vgareg; + +vgareg v256x224_103[25] = +{ + { 0xc2, 0x0, 0xe7}, + { 0xd4, 0x0, 0x45}, + { 0xd4, 0x1, 0x3f}, + { 0xd4, 0x2, 0x40}, + { 0xd4, 0x3, 0x86}, + { 0xd4, 0x4, 0x3f}, + { 0xd4, 0x5, 0x10}, + { 0xd4, 0x6, 0xcd}, + { 0xd4, 0x7, 0x1f}, + { 0xd4, 0x8, 0x0}, + { 0xd4, 0x9, 0x41}, + { 0xd4, 0x10, 0xc0}, + { 0xd4, 0x11, 0xac}, + { 0xd4, 0x12, 0xbf}, + { 0xd4, 0x13, 0x20}, + { 0xd4, 0x14, 0x40}, // + { 0xd4, 0x15, 0xe7}, + { 0xd4, 0x16, 0x06}, // + { 0xd4, 0x17, 0xa3}, + { 0xc4, 0x1, 0x1}, + { 0xc4, 0x4, 0xe}, // + { 0xce, 0x5, 0x40}, + { 0xce, 0x6, 0x5}, + { 0xc0, 0x10, 0x41}, + { 0xc0, 0x13, 0x0}, +}; + +vgareg v256x240[25] = +{ + { 0xc2, 0x0, 0xe3}, + { 0xd4, 0x0, 0x4f}, + { 0xd4, 0x1, 0x3f}, + { 0xd4, 0x2, 0x40}, + { 0xd4, 0x3, 0x92}, + { 0xd4, 0x4, 0x44}, + { 0xd4, 0x5, 0x10}, + { 0xd4, 0x6, 0x0a}, + { 0xd4, 0x7, 0x3e}, + { 0xd4, 0x8, 0x00}, + { 0xd4, 0x9, 0x41}, + { 0xd4, 0x10, 0xea}, + { 0xd4, 0x11, 0xac}, + { 0xd4, 0x12, 0xdf}, + { 0xd4, 0x13, 0x20}, + { 0xd4, 0x14, 0x40}, + { 0xd4, 0x15, 0xe7}, + { 0xd4, 0x16, 0x06}, + { 0xd4, 0x17, 0xa3}, + { 0xc4, 0x1, 0x1}, + { 0xc4, 0x4, 0xe}, + { 0xce, 0x5, 0x40}, + { 0xce, 0x6, 0x5}, + { 0xc0, 0x10, 0x41}, + { 0xc0, 0x13, 0x0} +}; + +vgareg v256x224S[25] = +{ + { 0xc2, 0x0, 0xe3}, + { 0xd4, 0x0, 0x5f}, + { 0xd4, 0x1, 0x3f}, + { 0xd4, 0x2, 0x40}, + { 0xd4, 0x3, 0x82}, + { 0xd4, 0x4, 0x4e}, + { 0xd4, 0x5, 0x96}, + { 0xd4, 0x6, 0x5}, + { 0xd4, 0x7, 0x1}, + { 0xd4, 0x8, 0x0}, + { 0xd4, 0x9, 0x40}, + { 0xd4, 0x10, 0xea}, + { 0xd4, 0x11, 0xac}, + { 0xd4, 0x12, 0xdf}, + { 0xd4, 0x13, 0x20}, + { 0xd4, 0x14, 0x40}, + { 0xd4, 0x15, 0xe7}, + { 0xd4, 0x16, 0x0}, + { 0xd4, 0x17, 0xe3}, + { 0xc4, 0x1, 0x1}, + { 0xc4, 0x4, 0xe}, + { 0xce, 0x5, 0x40}, + { 0xce, 0x6, 0x5}, + { 0xc0, 0x10, 0x41}, + { 0xc0, 0x13, 0x0} +}; + +vgareg v256x256[25] = +{ + { 0xc2, 0x0, 0xe7}, + { 0xd4, 0x0, 0x5f}, + { 0xd4, 0x1, 0x3f}, + { 0xd4, 0x2, 0x40}, + { 0xd4, 0x3, 0x82}, + { 0xd4, 0x4, 0x4a}, + { 0xd4, 0x5, 0x9a}, + { 0xd4, 0x6, 0x23}, + { 0xd4, 0x7, 0xb2}, + { 0xd4, 0x8, 0x0}, + { 0xd4, 0x9, 0x61}, + { 0xd4, 0x10, 0xa}, + { 0xd4, 0x11, 0xac}, + { 0xd4, 0x12, 0xff}, + { 0xd4, 0x13, 0x20}, + { 0xd4, 0x14, 0x40}, + { 0xd4, 0x15, 0x7}, + { 0xd4, 0x16, 0x1a}, + { 0xd4, 0x17, 0xa3}, + { 0xc4, 0x1, 0x1}, + { 0xc4, 0x4, 0xe}, + { 0xce, 0x5, 0x40}, + { 0xce, 0x6, 0x5}, + { 0xc0, 0x10, 0x41}, + { 0xc0, 0x13, 0x0} +}; + +vgareg v256x256S[25] = +{ + { 0xc2, 0x00, 0xe7},{ 0xd4, 0x00, 0x5F},{ 0xd4, 0x01, 0x3f}, + { 0xd4, 0x02, 0x40},{ 0xd4, 0x03, 0x82},{ 0xd4, 0x04, 0x4a}, + { 0xd4, 0x05, 0x9a},{ 0xd4, 0x06, 0x25},{ 0xd4, 0x07, 0x15}, + { 0xd4, 0x08, 0x00},{ 0xd4, 0x09, 0x60},{ 0xd4, 0x10, 0x0a}, + { 0xd4, 0x11, 0xac},{ 0xd4, 0x12, 0xff},{ 0xd4, 0x13, 0x20}, + { 0xd4, 0x14, 0x40},{ 0xd4, 0x15, 0x07},{ 0xd4, 0x16, 0x1a}, + { 0xd4, 0x17, 0xa3},{ 0xc4, 0x01, 0x01},{ 0xc4, 0x04, 0x0e}, + { 0xce, 0x05, 0x40},{ 0xce, 0x06, 0x05},{ 0xc0, 0x10, 0x41}, + { 0xc0, 0x13, 0x00} +}; + +static void VGAPortSet(vgareg R) +{ + int p,i,v; + + p=0x300|R.p; + i=R.i; + v=R.v; + + switch(p) + { + case 0x3C0: inportb(0x3DA); + outportb(0x3C0,i); + outportb(0x3C0,v); + break; + case 0x3C2: + case 0x3C3: + default: outportb(p, v); + break; + case 0x3C4: if(i==1) + { + outportw(0x3c4,0x100); + outportw(0x3c4,(v<<8)|1); + outportw(0x3c4,0x300); + break; + } + case 0x3CE: + case 0x3D4: outportw(p,i|(v<<8)); + break; + } +} +