cli added for debug
authornotaz <notasas@gmail.com>
Mon, 30 Apr 2007 23:53:52 +0000 (23:53 +0000)
committernotaz <notasas@gmail.com>
Mon, 30 Apr 2007 23:53:52 +0000 (23:53 +0000)
git-svn-id: file:///home/notaz/opt/svn/fceu@122 be3aeb3a-fb24-0410-a615-afba39da0efa

37 files changed:
Makefile.cli [new file with mode: 0644]
drivers/cli/dface.h [new file with mode: 0644]
drivers/cli/dos-joystick.c [new file with mode: 0644]
drivers/cli/dos-joystick.h [new file with mode: 0644]
drivers/cli/dos-keyboard.c [new file with mode: 0644]
drivers/cli/dos-mouse.c [new file with mode: 0644]
drivers/cli/dos-sound.c [new file with mode: 0644]
drivers/cli/dos-sound.h [new file with mode: 0644]
drivers/cli/dos-video.c [new file with mode: 0644]
drivers/cli/dos-video.h [new file with mode: 0644]
drivers/cli/dos.c [new file with mode: 0644]
drivers/cli/dos.h [new file with mode: 0644]
drivers/cli/input.c [new file with mode: 0644]
drivers/cli/keyscan.h [new file with mode: 0644]
drivers/cli/lnx-joystick.c [new file with mode: 0644]
drivers/cli/lnx-joystick.h [new file with mode: 0644]
drivers/cli/main.c [new file with mode: 0644]
drivers/cli/main.h [new file with mode: 0644]
drivers/cli/sdl-joystick.c [new file with mode: 0644]
drivers/cli/sdl-netplay.c [new file with mode: 0644]
drivers/cli/sdl-netplay.h [new file with mode: 0644]
drivers/cli/sdl-sound.c [new file with mode: 0644]
drivers/cli/sdl-video.c [new file with mode: 0644]
drivers/cli/sdl-video.h [new file with mode: 0644]
drivers/cli/sdl.c [new file with mode: 0644]
drivers/cli/sdl.h [new file with mode: 0644]
drivers/cli/svga-video.c [new file with mode: 0644]
drivers/cli/svga-video.h [new file with mode: 0644]
drivers/cli/svgalib.c [new file with mode: 0644]
drivers/cli/svgalib.h [new file with mode: 0644]
drivers/cli/throttle.c [new file with mode: 0644]
drivers/cli/throttle.h [new file with mode: 0644]
drivers/cli/unix-basedir.h [new file with mode: 0644]
drivers/cli/unix-netplay.c [new file with mode: 0644]
drivers/cli/unix-netplay.h [new file with mode: 0644]
drivers/cli/usage.h [new file with mode: 0644]
drivers/cli/vgatweak.c [new file with mode: 0644]

diff --git a/Makefile.cli b/Makefile.cli
new file mode 100644 (file)
index 0000000..373e2c6
--- /dev/null
@@ -0,0 +1,46 @@
+CROSS  =
+CC     = $(CROSS)gcc
+STRIP  = $(CROSS)strip
+AS     = $(CROSS)as
+TFLAGS  = -Winline -Izlib -DGP2X=1 -DLSB_FIRST -DUNIX -DPSS_STYLE=1 -DHAVE_ASPRINTF -DZLIB -DFRAMESKIP -D_REENTRANT `sdl-config --cflags` -DSDL
+RM     = rm -f
+B      = drivers/cli/
+ifdef DEBUG
+TFLAGS += -ggdb
+LDRIVER        += -ggdb
+else
+TFLAGS += -ftracer -fstrength-reduce -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math
+TFLAGS += -O3 # -pg
+LDRIVER        += -O3 # -pg
+endif
+
+all:           fceu
+
+include zlib/Makefile
+
+OBJDRIVER      = ${B}sdl.o ${B}main.o ${B}throttle.o ${B}unix-netplay.o ${B}sdl-sound.o ${B}sdl-video.o ${B}sdl-joystick.o drivers/common/cheat.o drivers/common/config.o drivers/common/args.o drivers/common/vidblit.o ${UNZIPOBJS} ppu.o movie.o
+LDRIVER                = -lm `sdl-config --libs` -lz
+
+
+OBJDRIVER += x6502.o
+
+x6502.o: x6502.c x6502.h ops.h fce.h sound.h
+
+ncpu.o: ncpu.S ncpu.h
+       $(CC) $(TFLAGS) -c $< -o $@
+
+include Makefile.base
+
+${B}sdl-joystick.o:    ${B}sdl-joystick.c
+${B}main.o:            ${B}main.c ${B}main.h ${B}usage.h ${B}input.c ${B}keyscan.h
+${B}sdl.o:             ${B}sdl.c ${B}sdl.h
+${B}sdl-video.o:       ${B}sdl-video.c
+${B}sdl-sound.o:       ${B}sdl-sound.c
+#${B}sdl-netplay.o:    ${B}sdl-netplay.c
+${B}unix-netplay.o:    ${B}unix-netplay.c
+${B}throttle.o:         ${B}throttle.c ${B}main.h ${B}throttle.h
+
+ppu.o:                 ppu.c ppu.h
+
+include Makefile.common
+
diff --git a/drivers/cli/dface.h b/drivers/cli/dface.h
new file mode 100644 (file)
index 0000000..6ff4459
--- /dev/null
@@ -0,0 +1,32 @@
+extern CFGSTRUCT DriverConfig[];
+extern ARGPSTRUCT DriverArgs[];
+extern char *DriverUsage;
+
+void DoDriverArgs(void);
+void GetBaseDirectory(char *BaseDirectory);
+
+int InitSound(void);
+void WriteSound(int16 *Buffer, int Count, int NoWaiting);
+void KillSound(void);
+void SilenceSound(int s); /* DOS and SDL */
+
+
+int InitMouse(void);
+void KillMouse(void);
+void GetMouseData(uint32 *MouseData);
+
+int InitJoysticks(void);
+void KillJoysticks(void);
+uint32 *GetJSOr(void);
+
+int InitKeyboard(void);
+int UpdateKeyboard(void);
+char *GetKeyboard(void);
+void KillKeyboard(void);
+
+int InitVideo(void);
+void KillVideo(void);
+void BlitScreen(uint8 *XBuf);
+void LockConsole(void);
+void UnlockConsole(void);
+void ToggleFS();               /* SDL */
diff --git a/drivers/cli/dos-joystick.c b/drivers/cli/dos-joystick.c
new file mode 100644 (file)
index 0000000..3729187
--- /dev/null
@@ -0,0 +1,190 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <dpmi.h>
+#include <sys/farptr.h>
+#include <go32.h>
+#include <pc.h>
+
+#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[4];
+
+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;
+        ret=0;
+
+        if(!soundo)
+         UpdateJoyData();
+        for(y=0;y<4;y++)
+         if(joybuttons&joyBMap[y]) ret|=(1<<y)<<((joy-1)<<3);
+
+        if(joyx<=joyxcenter*.25) ret|=JOY_LEFT<<((joy-1)<<3);
+        else if(joyx>=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);
+}
+
diff --git a/drivers/cli/dos-joystick.h b/drivers/cli/dos-joystick.h
new file mode 100644 (file)
index 0000000..6cfaee5
--- /dev/null
@@ -0,0 +1,27 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2002 Ben Parnell\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+void UpdateJoyData(void);\r
+uint32 GetJSOr(void);\r
+int InitJoysticks(void);\r
+\r
+/* Variables to save in config file. */\r
+extern int joy;\r
+extern int joyBMap[4];\r
diff --git a/drivers/cli/dos-keyboard.c b/drivers/cli/dos-keyboard.c
new file mode 100644 (file)
index 0000000..22ca9e8
--- /dev/null
@@ -0,0 +1,131 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2002 Ben Parnell\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <signal.h>\r
+#include <string.h>\r
+#include <pc.h>\r
+#include <dpmi.h>\r
+#include <go32.h>\r
+#include "keyscan.h"\r
+\r
+static unsigned char lastsc;\r
+static char keybuf[256];\r
+int newk;\r
+\r
+/* Read scan code from port $60 */\r
+/* Acknowledge interrupt( output $20 to port $20) */\r
+\r
+static void ihandler(_go32_dpmi_registers *r)\r
+{\r
+ unsigned char scode=inp(0x60);        /* Get scan code. */\r
+\r
+\r
+ if(scode!=0xE0)\r
+ {\r
+  int offs=0;\r
+\r
+  /* I'm only interested in preserving the independent status of the\r
+     right ALT and CONTROL keys.\r
+  */\r
+  if(lastsc==0xE0)\r
+   if((scode&0x7F)==SCAN_LEFTALT || (scode&0x7F)==SCAN_LEFTCONTROL)\r
+    offs=0x80;\r
+  \r
+\r
+  keybuf[(scode&0x7f)|offs]=((scode&0x80)^0x80);\r
+  newk++;\r
+ }\r
+ lastsc=scode;\r
+\r
+ outp(0x20,0x20);      /* Acknowledge interrupt. */\r
+}\r
+\r
+static _go32_dpmi_seginfo KBIBack,KBIBackRM;\r
+static _go32_dpmi_seginfo KBI,KBIRM;\r
+static _go32_dpmi_registers KBIRMRegs;\r
+static int initdone=0;\r
+\r
+int InitKeyboard(void)\r
+{\r
+ /* I'll assume that the keyboard is in the correct scancode mode(translated\r
+    mode 2, I think).\r
+ */\r
+  newk=0;\r
+  memset(keybuf,0,sizeof(keybuf));\r
+  KBIRM.pm_offset=KBI.pm_offset=(int)ihandler;\r
+  KBIRM.pm_selector=KBI.pm_selector=_my_cs();\r
+\r
+  _go32_dpmi_get_real_mode_interrupt_vector(9,&KBIBackRM);\r
+  _go32_dpmi_allocate_real_mode_callback_iret(&KBIRM, &KBIRMRegs);\r
+  _go32_dpmi_set_real_mode_interrupt_vector(9,&KBIRM);\r
+\r
+  _go32_dpmi_get_protected_mode_interrupt_vector(9,&KBIBack);\r
+  _go32_dpmi_allocate_iret_wrapper(&KBI);\r
+  _go32_dpmi_set_protected_mode_interrupt_vector(9,&KBI);\r
+  lastsc=0;\r
+  initdone=1;\r
+  return(1);\r
+}\r
+\r
+void KillKeyboard(void)\r
+{\r
+ if(initdone)\r
+ {\r
+  _go32_dpmi_set_protected_mode_interrupt_vector(9,&KBIBack);\r
+  _go32_dpmi_free_iret_wrapper(&KBI);\r
+\r
+  _go32_dpmi_set_real_mode_interrupt_vector(9,&KBIBackRM);\r
+  _go32_dpmi_free_real_mode_callback(&KBIRM);\r
+  initdone=0;\r
+ }\r
+}\r
+\r
+/* In FCE Ultra, it doesn't matter if the key states change\r
+   in the middle of the keyboard handling code.  If you want\r
+   to use this code elsewhere, you may want to memcpy() keybuf\r
+   to another buffer and return that when GetKeyboard() is\r
+   called.\r
+*/\r
+\r
+char *GetKeyboard(void)\r
+{\r
+ return keybuf;\r
+}\r
+\r
+/* Returns 1 on new scan codes generated, 0 on no new scan codes. */\r
+int UpdateKeyboard(void)\r
+{\r
+ int t=newk;\r
+\r
+ if(t)\r
+ {\r
+  asm volatile(\r
+        "subl %%eax,_newk\n\t"\r
+       :\r
+       : "a" (t)\r
+  );\r
+\r
+  if(keybuf[SCAN_LEFTCONTROL] && keybuf[SCAN_C])\r
+   raise(SIGINT);\r
+  return(1);\r
+ }\r
+ return(0);\r
+}\r
diff --git a/drivers/cli/dos-mouse.c b/drivers/cli/dos-mouse.c
new file mode 100644 (file)
index 0000000..ae3e341
--- /dev/null
@@ -0,0 +1,77 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2002 Ben Parnell\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+#include <dpmi.h>\r
+#include <string.h>\r
+\r
+#include "dos.h"\r
+\r
+int InitMouse(void)\r
+{\r
+ __dpmi_regs regs;\r
+\r
+ memset(&regs,0,sizeof(regs));\r
+ regs.x.ax=0;\r
+ __dpmi_int(0x33,&regs);\r
+ if(regs.x.ax!=0xFFFF)\r
+  return(0);\r
+\r
+ memset(&regs,0,sizeof(regs));\r
+ regs.x.ax=0x7;\r
+ regs.x.cx=0;           // Min X\r
+ regs.x.dx=260;         // Max X\r
+ __dpmi_int(0x33,&regs);\r
+\r
+ memset(&regs,0,sizeof(regs));\r
+ regs.x.ax=0x8;\r
+ regs.x.cx=0;           // Min Y\r
+ regs.x.dx=260;         // Max Y\r
+ __dpmi_int(0x33,&regs);\r
+\r
+ memset(&regs,0,sizeof(regs));\r
+ regs.x.ax=0xF;\r
+ regs.x.cx=8;           // Mickey X\r
+ regs.x.dx=8;           // Mickey Y\r
+ __dpmi_int(0x33,&regs);\r
+\r
+ memset(&regs,0,sizeof(regs));\r
+ regs.x.ax=0x2;\r
+ __dpmi_int(0x33,&regs);\r
+\r
+ return(1);\r
+}\r
+\r
+uint32 GetMouseData(uint32 *x, uint32 *y)\r
+{\r
+ __dpmi_regs regs;\r
+\r
+ memset(&regs,0,sizeof(regs));\r
+ regs.x.ax=0x3;\r
+ __dpmi_int(0x33,&regs);\r
+\r
+ *x=regs.x.cx;\r
+ *y=regs.x.dx;\r
+ return(regs.x.bx&3);\r
+}\r
+\r
+void KillMouse(void)\r
+{\r
+\r
+}\r
diff --git a/drivers/cli/dos-sound.c b/drivers/cli/dos-sound.c
new file mode 100644 (file)
index 0000000..19ef271
--- /dev/null
@@ -0,0 +1,567 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2002 Ben Parnell\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <sys/farptr.h>\r
+#include <pc.h>\r
+#include <dos.h>\r
+#include <dpmi.h>\r
+#include <go32.h>\r
+#include <ctype.h>\r
+\r
+#include "dos.h"\r
+#include "dos-sound.h"\r
+#include "dos-joystick.h"\r
+\r
+\r
+static void SBIRQHandler(_go32_dpmi_registers *r);\r
+static uint32 LMBuffer;         /* Address of low memory DMA playback buffer. */\r
+static int LMSelector;\r
+\r
+static uint8 *WaveBuffer;\r
+static unsigned int IVector, SBIRQ, SBDMA, SBDMA16, SBPort;\r
+static int DSPV,hsmode;\r
+static int format;\r
+static int frags, fragsize, fragtotal;\r
+static volatile int WritePtr, ReadPtr;\r
+static volatile int hbusy;\r
+static volatile int whichbuf;\r
+\r
+\r
+static uint8 PICMask;\r
+/* Protected mode interrupt vector info. */\r
+static _go32_dpmi_seginfo SBIH,SBIHOld;\r
+\r
+/* Real mode interrupt vector info. */\r
+static _go32_dpmi_seginfo SBIHRM,SBIHRMOld;\r
+static _go32_dpmi_registers SBIHRMRegs;\r
+\r
+static int WriteDSP(uint8 V)\r
+{\r
+ int x;\r
+\r
+ for(x=65536;x;x--)\r
+ {\r
+  if(!(inportb(SBPort+0xC)&0x80))\r
+  {\r
+   outportb(SBPort+0xC,V);\r
+   return(1);\r
+  }\r
+ }\r
+ return(0);\r
+}\r
+\r
+static int ReadDSP(uint8 *V)\r
+{\r
+ int x;\r
+\r
+ for(x=65536;x;x--)             /* Should be more than enough time... */\r
+ {\r
+  if(inportb(SBPort+0xE)&0x80)\r
+  {\r
+   *V=inportb(SBPort+0xA);\r
+   return(1);\r
+  }\r
+ }\r
+ return(0);\r
+}\r
+\r
+\r
+static int SetVectors(void)\r
+{\r
+ SBIH.pm_offset=SBIHRM.pm_offset=(int)SBIRQHandler;\r
+ SBIH.pm_selector=SBIHRM.pm_selector=_my_cs();\r
+\r
+ /* Get and set real mode interrupt vector.  */\r
+ _go32_dpmi_get_real_mode_interrupt_vector(IVector,&SBIHRMOld);\r
+ _go32_dpmi_allocate_real_mode_callback_iret(&SBIHRM, &SBIHRMRegs);\r
+ _go32_dpmi_set_real_mode_interrupt_vector(IVector,&SBIHRM);  \r
+\r
+ /* Get and set protected mode interrupt vector. */\r
+ _go32_dpmi_get_protected_mode_interrupt_vector(IVector,&SBIHOld);\r
+ _go32_dpmi_allocate_iret_wrapper(&SBIH);\r
+ _go32_dpmi_set_protected_mode_interrupt_vector(IVector,&SBIH); \r
+\r
+ return(1);\r
+}\r
+\r
+static void ResetVectors(void)\r
+{\r
+ _go32_dpmi_set_protected_mode_interrupt_vector(IVector,&SBIHOld);\r
+ _go32_dpmi_free_iret_wrapper(&SBIH);\r
+ _go32_dpmi_set_real_mode_interrupt_vector(IVector,&SBIHRMOld);\r
+ _go32_dpmi_free_real_mode_callback(&SBIHRM);\r
+}\r
+\r
+int GetBLASTER(void)\r
+{\r
+ int check=0;\r
+ char *s;\r
+\r
+ if(!(s=getenv("BLASTER")))\r
+ {\r
+  puts(" Error getting BLASTER environment variable.");\r
+  return(0);\r
+ }\r
+\r
+ while(*s)\r
+ {\r
+  switch(toupper(*s))\r
+  {\r
+   case 'A': check|=(sscanf(s+1,"%x",&SBPort)==1)?1:0;break;\r
+   case 'I': check|=(sscanf(s+1,"%d",&SBIRQ)==1)?2:0;break;\r
+   case 'D': check|=(sscanf(s+1,"%d",&SBDMA)==1)?4:0;break;\r
+   case 'H': check|=(sscanf(s+1,"%d",&SBDMA16)==1)?8:0;break;\r
+  }\r
+  s++;\r
+ }\r
\r
+ if((check^7)&7 || SBDMA>=4 || (SBDMA16<=4 && check&8) || SBIRQ>15)\r
+ {\r
+  puts(" Invalid or incomplete BLASTER environment variable.");\r
+  return(0);\r
+ }\r
+ if(!(check&8))\r
+  format=0;\r
+ return(1);\r
+}\r
+\r
+static int ResetDSP(void)\r
+{\r
+ uint8 b;\r
+\r
+ outportb(SBPort+0x6,0x1);\r
+ delay(10);\r
+ outportb(SBPort+0x6,0x0);\r
+ delay(10);\r
+\r
+ if(ReadDSP(&b))\r
+  if(b==0xAA)\r
+   return(1); \r
+ return(0);\r
+}\r
+\r
+static int GetDSPVersion(void)\r
+{\r
+ int ret;\r
+ uint8 t;\r
+\r
+ if(!WriteDSP(0xE1))\r
+  return(0);\r
+ if(!ReadDSP(&t))\r
+  return(0);\r
+ ret=t<<8;\r
+ if(!ReadDSP(&t))\r
+  return(0);\r
+ ret|=t;\r
+\r
+ return(ret);\r
+}\r
+\r
+static void KillDMABuffer(void)\r
+{\r
+ __dpmi_free_dos_memory(LMSelector);\r
+}\r
+\r
+static int MakeDMABuffer(void)\r
+{\r
+ uint32 size;\r
+ int32 tmp;\r
+\r
+ size=fragsize*2;       /* Two buffers in the DMA buffer. */\r
+ size<<=format;         /* Twice the size for 16-bit than for 8-bit. */\r
+\r
+ size<<=1;              /* Double the size in case the first 2 buffers\r
+                           cross a 64KB or 128KB page boundary.\r
+                        */\r
+ size=(size+15)>>4;     /* Convert to paragraphs */\r
+\r
+ if((tmp=__dpmi_allocate_dos_memory(size,&LMSelector))<0)\r
+  return(0);\r
+\r
+ LMBuffer=tmp<<=4;\r
+\r
+ if(format)   /* Check for and fix 128KB page boundary crossing. */\r
+ {\r
+  if((LMBuffer&0x20000) != ((LMBuffer+fragsize*2*2-1)&0x20000))\r
+   LMBuffer+=fragsize*2*2;\r
+ }\r
+ else   /* Check for and fix 64KB page boundary crossing. */\r
+ {\r
+  if((LMBuffer&0x10000) != ((LMBuffer+fragsize*2-1)&0x10000))\r
+   LMBuffer+=fragsize*2;\r
+ }\r
+\r
+ DOSMemSet(LMBuffer, format?0:128, (fragsize*2)<<format);\r
+\r
+ return(1);\r
+}\r
+\r
+static void ProgramDMA(void)\r
+{\r
+ static int PPorts[8]={0x87,0x83,0x81,0x82,0,0x8b,0x89,0x8a};\r
+ uint32 tmp;\r
+\r
+ if(format)\r
+ {\r
+  outportb(0xd4,(SBDMA16&0x3)|0x4);\r
+  outportb(0xd8,0x0);\r
+  outportb(0xd6,(SBDMA16&0x3)|0x58);\r
+  tmp=((SBDMA16&3)<<2)+0xC2;\r
+ }\r
+ else\r
+ {\r
+  outportb(0xA,SBDMA|0x4);\r
+  outportb(0xC,0x0);\r
+  outportb(0xB,SBDMA|0x58);\r
+  tmp=(SBDMA<<1)+1;\r
+ }\r
+\r
+ /* Size of entire buffer. */\r
+ outportb(tmp,(fragsize*2-1));\r
+ outportb(tmp,(fragsize*2-1)>>8);\r
+\r
+ /* Page of buffer. */\r
+ outportb(PPorts[format?SBDMA16:SBDMA],LMBuffer>>16);\r
+\r
+ /* Offset of buffer within page. */\r
+ if(format)\r
+  tmp=((SBDMA16&3)<<2)+0xc0;\r
+ else\r
+  tmp=SBDMA<<1;\r
+\r
+ outportb(tmp,(LMBuffer>>format));\r
+ outportb(tmp,(LMBuffer>>(8+format)));\r
+}\r
+\r
+int InitSB(int Rate, int bittage)\r
+{\r
+ hsmode=hbusy=0;\r
+ whichbuf=1;\r
+ puts("Initializing Sound Blaster...");\r
+\r
+ format=bittage?1:0;\r
+ frags=8;\r
+\r
+ if(Rate<=11025)\r
+  fragsize=1<<5;\r
+ else if(Rate<=22050)\r
+  fragsize=1<<6;\r
+ else\r
+  fragsize=1<<7;\r
+\r
+ fragtotal=frags*fragsize;\r
+ WaveBuffer=malloc(fragtotal<<format);\r
+\r
+ if(format)\r
+  memset(WaveBuffer,0,fragtotal*2);\r
+ else\r
+  memset(WaveBuffer,128,fragtotal);\r
+\r
+ WritePtr=ReadPtr=0;\r
+\r
+ if((Rate<8192) || (Rate>65535))\r
+ {\r
+  printf(" Unsupported playback rate: %d samples per second\n",Rate);\r
+  return(0);\r
+ }\r
+\r
+ if(!GetBLASTER())\r
+  return(0);\r
\r
+ /* Disable IRQ line in PIC0 or PIC1 */\r
+ if(SBIRQ>7)\r
+ {\r
+  PICMask=inportb(0xA1);\r
+  outportb(0xA1,PICMask|(1<<(SBIRQ&7)));\r
+ }\r
+ else\r
+ {\r
+  PICMask=inportb(0x21);\r
+  outportb(0x21,PICMask|(1<<SBIRQ));\r
+ }\r
+ if(!ResetDSP())\r
+ {\r
+  puts(" Error resetting the DSP.");\r
+  return(0);\r
+ }\r
\r
+ if(!(DSPV=GetDSPVersion()))\r
+ {\r
+  puts(" Error getting the DSP version.");\r
+  return(0);\r
+ }\r
+\r
+ printf(" DSP Version: %d.%d\n",DSPV>>8,DSPV&0xFF);\r
+ if(DSPV<0x201)\r
+ {\r
+  printf(" DSP version number is too low.\n");\r
+  return(0);\r
+ }\r
+\r
+ if(DSPV<0x400)\r
+  format=0;\r
+ if(!MakeDMABuffer())\r
+ {\r
+  puts(" Error creating low-memory DMA buffer.");\r
+  return(0);\r
+ }\r
+\r
+ if(SBIRQ>7) IVector=SBIRQ+0x68;\r
+ else IVector=SBIRQ+0x8;\r
+\r
+ if(!SetVectors())\r
+ {\r
+  puts(" Error setting interrupt vectors.");\r
+  KillDMABuffer();\r
+  return(0);\r
+ }\r
+\r
+ /* Reenable IRQ line. */\r
+ if(SBIRQ>7)\r
+  outportb(0xA1,PICMask&(~(1<<(SBIRQ&7))));\r
+ else\r
+  outportb(0x21,PICMask&(~(1<<SBIRQ)));\r
+\r
+ ProgramDMA();\r
+\r
+ /* Note that the speaker must always be turned on before the mode transfer\r
+    byte is sent to the DSP if we're going into high-speed mode, since\r
+    a real Sound Blaster(at least my SBPro) won't accept DSP commands(except\r
+    for the reset "command") after it goes into high-speed mode.\r
+ */\r
+ WriteDSP(0xD1);                 // Turn on DAC speaker\r
+\r
+ if(DSPV>=0x400)\r
+ {\r
+  WriteDSP(0x41);                // Set sampling rate\r
+  WriteDSP(Rate>>8);             // High byte\r
+  WriteDSP(Rate&0xFF);           // Low byte\r
+  if(!format)\r
+  {\r
+   WriteDSP(0xC6);                // 8-bit output\r
+   WriteDSP(0x00);                // 8-bit mono unsigned PCM\r
+  }\r
+  else\r
+  {\r
+   WriteDSP(0xB6);                // 16-bit output\r
+   WriteDSP(0x10);                // 16-bit mono signed PCM\r
+  }\r
+  WriteDSP((fragsize-1)&0xFF);// Low byte of size\r
+  WriteDSP((fragsize-1)>>8);  // High byte of size\r
+ }\r
+ else\r
+ {\r
+  int tc,command;\r
+  if(Rate>22050)\r
+  {\r
+   tc=(65536-(256000000/Rate))>>8;\r
+   Rate=256000000/(65536-(tc<<8));\r
+   command=0x90;                  // High-speed auto-initialize DMA mode transfer\r
+   hsmode=1;\r
+  }\r
+  else\r
+  {\r
+   tc=256-(1000000/Rate);\r
+   Rate=1000000/(256-tc);\r
+   command=0x1c;                  // Auto-initialize DMA mode transfer\r
+  }\r
+  WriteDSP(0x40);       // Set DSP time constant\r
+  WriteDSP(tc);         // time constant\r
+  WriteDSP(0x48);       // Set DSP block transfer size\r
+  WriteDSP((fragsize-1)&0xFF);\r
+  WriteDSP((fragsize-1)>>8);\r
+\r
+  WriteDSP(command);\r
+ }\r
+\r
+ /* Enable DMA */\r
+ if(format)\r
+  outportb(0xd4,SBDMA16&3);\r
+ else\r
+  outportb(0xa,SBDMA);\r
+\r
+ printf(" %d hz, %d-bit\n",Rate,8<<format);\r
+ return(Rate);\r
+}\r
+\r
+extern volatile int soundjoyer;\r
+extern volatile int soundjoyeron;\r
+static int ssilence=0;\r
+\r
+static void SBIRQHandler(_go32_dpmi_registers *r)\r
+{\r
+        uint32 *src;\r
+       uint32 dest;\r
+       int32 x;\r
+\r
+\r
+        if(format)\r
+        {\r
+         uint8 status;\r
+\r
+         outportb(SBPort+4,0x82);\r
+         status=inportb(SBPort+5);\r
+         if(status&2)\r
+          inportb(SBPort+0x0F);\r
+        }\r
+        else\r
+         inportb(SBPort+0x0E);\r
+\r
+        #ifdef OLD\r
+        {\r
+         uint8 status;\r
+\r
+         outportb(SBPort+4,0x82);\r
+         status=inportb(SBPort+5);\r
+         if(status&1)\r
+          inportb(SBPort+0x0E);\r
+         else if(status&2)\r
+          inportb(SBPort+0x0F);\r
+         else\r
+          return;               // Mysterious interrupt source!  *eerie music*\r
+        }         \r
+        #endif\r
+\r
+        if(hbusy)\r
+        {\r
+         outportb(0x20,0x20);\r
+         if(SBIRQ>=8)\r
+          outportb(0xA0,0x20);\r
+         whichbuf^=1;         \r
+         return;\r
+        }\r
+        hbusy=1;\r
+\r
+        {\r
+         /* This code seems to fail on many SB emulators.  Bah.\r
+            SCREW SB EMULATORS. ^_^ */\r
+         uint32 count;\r
+        uint32 block;\r
+        uint32 port;\r
+       \r
+         if(format)\r
+          port=((SBDMA16&3)*4)+0xc2;\r
+         else\r
+          port=(SBDMA*2)+1;\r
+\r
+         count=inportb(port);\r
+         count|=inportb(port)<<8;\r
+\r
+         if(count>=fragsize)\r
+          block=1;\r
+         else\r
+          block=0;\r
+         dest=LMBuffer+((block*fragsize)<<format);\r
+\r
+         #ifdef MOO\r
+         dest=LMBuffer+((whichbuf*fragsize)<<format);\r
+         whichbuf^=1;\r
+         #endif\r
+        }\r
+\r
+        _farsetsel(_dos_ds);\r
+\r
+        src=(uint32 *)(WaveBuffer+(ReadPtr<<format));\r
+\r
+       if(ssilence)\r
+       {\r
+        uint32 sby;\r
+        if(format) sby=0;      /* 16-bit silence.  */\r
+        else sby=0x80808080;   /* 8-bit silence.   */\r
+\r
+         for(x=(fragsize<<format)>>2;x;x--,dest+=4)\r
+         {\r
+          _farnspokel(dest,sby);\r
+         }\r
+       }\r
+       else\r
+       {\r
+         for(x=(fragsize<<format)>>2;x;x--,dest+=4,src++)\r
+         {\r
+          _farnspokel(dest,*src);\r
+         }\r
+         ReadPtr=(ReadPtr+fragsize)&(fragtotal-1);\r
+       }\r
+\r
+        if(soundjoyeron)\r
+        {\r
+         static int coot=0;\r
+         if(!coot)\r
+         {\r
+          UpdateJoyData();\r
+          soundjoyer=1;\r
+         }\r
+         coot=(coot+1)&3;\r
+        }\r
+        hbusy=0;\r
+        outportb(0x20,0x20);\r
+        if(SBIRQ>=8)        \r
+         outportb(0xA0,0x20);\r
+}\r
+\r
+void SilenceSound(int s)\r
+{\r
+ ssilence=s;\r
+}\r
+\r
+void WriteSBSound(int32 *Buffer, int Count, int NoBlocking)\r
+{\r
+ int x;\r
+\r
+ if(!format)\r
+ {\r
+   for(x=0;x<Count;x++)\r
+   {\r
+    while(WritePtr==ReadPtr)\r
+     if(NoBlocking)\r
+      return;\r
+    WaveBuffer[WritePtr]=(uint8)((Buffer[x])>>8)^128;\r
+    WritePtr=(WritePtr+1)&(fragtotal-1);\r
+   }\r
+ }     \r
+ else // 16 bit\r
+ {\r
+   for(x=0;x<Count;x++)\r
+   {\r
+    while(WritePtr==ReadPtr)\r
+     if(NoBlocking)\r
+      return;\r
+    ((int16 *)WaveBuffer)[WritePtr]=Buffer[x];\r
+    WritePtr=(WritePtr+1)&(fragtotal-1);\r
+   }\r
+ }\r
+}\r
+\r
+void KillSB(void)\r
+{\r
+ if(hsmode)\r
+  ResetDSP();                   /* High-speed mode requires a DSP reset. */\r
+ else\r
+  WriteDSP(format?0xD9:0xDA);    /* Exit auto-init DMA transfer mode. */ \r
+ WriteDSP(0xD3);                /* Turn speaker off. */\r
+\r
+ outportb((SBIRQ>7)?0xA1:0x21,PICMask|(1<<(SBIRQ&7)));\r
+ ResetVectors();\r
+ outportb((SBIRQ>7)?0xA1:0x21,PICMask);\r
+ KillDMABuffer();\r
+}\r
diff --git a/drivers/cli/dos-sound.h b/drivers/cli/dos-sound.h
new file mode 100644 (file)
index 0000000..7f5185a
--- /dev/null
@@ -0,0 +1,26 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2002 Ben Parnell\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+int InitSB(int Rate, int bittage);\r
+void KillSB(void);\r
+\r
+void WriteSBSound(int32 *Buffer, int Count, int NoBlocking);\r
+void SilenceSound(int s);\r
+\r
diff --git a/drivers/cli/dos-video.c b/drivers/cli/dos-video.c
new file mode 100644 (file)
index 0000000..574c824
--- /dev/null
@@ -0,0 +1,246 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 1998 \Firebug\\r
+ *  Copyright (C) 2002 Ben Parnell\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <dpmi.h>\r
+#include <sys/farptr.h>\r
+#include <go32.h>\r
+#include <pc.h>\r
+\r
+#include "dos.h"\r
+#include "dos-video.h"\r
+\r
+#define TEXT            3\r
+#define G320x200x256    0x13\r
+\r
+static void vga_waitretrace(void)\r
+{ \r
+ while(inp(0x3da)&0x8); \r
+ while(!(inp(0x3da)&0x8));\r
+}\r
+\r
+static void vga_setmode(int mode)\r
+{\r
+ __dpmi_regs regs;\r
+\r
+ memset(&regs,0,sizeof(regs));\r
+ regs.x.ax=mode;\r
+\r
+ __dpmi_int(0x10,&regs);\r
+}\r
+\r
+void vga_setpalette(int i, int r, int g, int b)\r
+{ \r
+ outp(0x3c8,i);\r
+ outp(0x3c9,r);\r
+ outp(0x3c9,g);\r
+ outp(0x3c9,b); \r
+}\r
+\r
+int FCEUDvmode=1;\r
+\r
+static int vidready=0;\r
+\r
+/*      Part of the VGA low-level mass register setting code derived from\r
+       code by \Firebug\.\r
+*/\r
+\r
+#include "vgatweak.c"\r
+\r
+void SetBorder(void)\r
+{\r
+ inportb(0x3da);\r
+ outportb(0x3c0,(0x11|0x20));\r
+ outportb(0x3c0,0x80);\r
+}\r
+\r
+void TweakVGA(int VGAMode)\r
+{\r
+  int I;\r
+  \r
+  vga_waitretrace();\r
+\r
+  outportb(0x3C8,0x00);\r
+  for(I=0;I<768;I++) outportb(0x3C9,0x00);\r
+\r
+  outportb(0x3D4,0x11);\r
+  I=inportb(0x3D5)&0x7F;\r
+  outportb(0x3D4,0x11);\r
+  outportb(0x3D5,I);\r
+\r
+  switch(VGAMode)\r
+  {\r
+    case 1:  for(I=0;I<25;I++) VGAPortSet(v256x240[I]);break;\r
+    case 2:  for(I=0;I<25;I++) VGAPortSet(v256x256[I]);break;\r
+    case 3:  for(I=0;I<25;I++) VGAPortSet(v256x256S[I]);break;\r
+    case 6:  for(I=0;I<25;I++) VGAPortSet(v256x224S[I]);break;\r
+    case 8:  for(I=0;I<25;I++) VGAPortSet(v256x224_103[I]);break;\r
+    default: break;\r
+  }\r
+\r
+  outportb(0x3da,0);\r
+}\r
+\r
+\r
+static uint8 palettedbr[256],palettedbg[256],palettedbb[256];\r
+\r
+static void FlushPalette(void)\r
+{\r
+ int x;\r
+ for(x=0;x<256;x++)\r
+ {\r
+  int z=x;\r
+  vga_setpalette(z,palettedbr[x]>>2,palettedbg[x]>>2,palettedbb[x]>>2);\r
+ }\r
+}\r
+\r
+void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b)\r
+{\r
+  palettedbr[index]=r;\r
+  palettedbg[index]=g;\r
+  palettedbb[index]=b;\r
+  if(vidready)\r
+  {\r
+   vga_setpalette(index,r>>2,g>>2,b>>2);\r
+  }\r
+}\r
+\r
+\r
+void FCEUD_GetPalette(uint8 i, uint8 *r, uint8 *g, uint8 *b)\r
+{\r
+ *r=palettedbr[i];\r
+ *g=palettedbg[i];\r
+ *b=palettedbb[i];\r
+}\r
+\r
+static uint32 ScreenLoc;\r
+\r
+int InitVideo(void)\r
+{\r
+ vidready=0;\r
+ switch(FCEUDvmode)\r
+ {\r
+  default:\r
+  case 1:\r
+  case 2:\r
+  case 3:\r
+  case 6:\r
+  case 8:\r
+         vga_setmode(G320x200x256);\r
+        vidready|=1;\r
+         ScreenLoc=0xa0000;\r
+         TweakVGA(FCEUDvmode);\r
+         SetBorder();\r
+         DOSMemSet(ScreenLoc, 128, 256*256);\r
+         break;\r
+ }\r
+ vidready|=2;\r
+ FlushPalette();\r
+ return 1;\r
+}\r
+\r
+void KillVideo(void)\r
+{\r
+ if(vidready)\r
+ {\r
+  vga_setmode(TEXT);\r
+  vidready=0;\r
+ }\r
+}\r
+void LockConsole(void){}\r
+void UnlockConsole(void){}\r
+void BlitScreen(uint8 *XBuf)\r
+{\r
+ uint32 dest;\r
+ int tlines;\r
+\r
+ if(eoptions&4 && !NoWaiting)\r
+  vga_waitretrace();\r
+\r
+ tlines=erendline-srendline+1;\r
+\r
+ dest=ScreenLoc;\r
+\r
+ switch(FCEUDvmode)\r
+ {\r
+  case 1:dest+=(((240-tlines)>>1)<<8);break;\r
+  case 2:\r
+  case 3:dest+=(((256-tlines)>>1)<<8);break;\r
+  case 4:\r
+  case 5:dest+=(((240-tlines)>>1)*640+((640-512)>>1));break;\r
+  case 8:\r
+  case 6:if(tlines>224) tlines=224;dest+=(((224-tlines)>>1)<<8);break;\r
+ }\r
\r
+ XBuf+=(srendline<<8)+(srendline<<4);\r
+           \r
+  _farsetsel(_dos_ds);\r
+ if(eoptions&DO_CLIPSIDES)\r
+ {\r
+  asm volatile(     \r
+     "agoop1:\n\t"\r
+     "movl $30,%%eax\n\t"\r
+     "agoop2:\n\t"\r
+     "movl (%%esi),%%edx\n\t"\r
+     "movl 4(%%esi),%%ecx\n\t"\r
+     ".byte 0x64 \n\t"\r
+     "movl %%edx,(%%edi)\n\t"\r
+     ".byte 0x64 \n\t"\r
+     "movl %%ecx,4(%%edi)\n\t"\r
+     "addl $8,%%esi\n\t"\r
+     "addl $8,%%edi\n\t"\r
+     "decl %%eax\n\t"\r
+     "jne agoop2\n\t"\r
+     "addl $32,%%esi\n\t"\r
+     "addl $16,%%edi\n\t"\r
+     "decb %%bl\n\t"\r
+     "jne agoop1\n\t"\r
+     :\r
+     : "S" (XBuf+8), "D" (dest+8), "b" (tlines)\r
+     : "%eax","%cc","%edx","%ecx" );\r
+ }\r
+ else\r
+ {\r
+  asm volatile(     \r
+     "goop1:\n\t"\r
+     "movl $32,%%eax\n\t"\r
+     "goop2:\n\t"\r
+     "movl (%%esi),%%edx\n\t"\r
+     "movl 4(%%esi),%%ecx\n\t"\r
+     ".byte 0x64 \n\t"\r
+     "movl %%edx,(%%edi)\n\t"\r
+     ".byte 0x64 \n\t"\r
+     "movl %%ecx,4(%%edi)\n\t"\r
+     "addl $8,%%esi\n\t"\r
+     "addl $8,%%edi\n\t"\r
+     "decl %%eax\n\t"\r
+     "jne goop2\n\t"\r
+     "addl $16,%%esi\n\t"\r
+     "decb %%bl\n\t"\r
+     "jne goop1\n\t"\r
+     :\r
+     : "S" (XBuf), "D" (dest), "b" (tlines)\r
+     : "%eax","%cc","%edx","%ecx" );\r
+ }\r
+}\r
+\r
+\r
diff --git a/drivers/cli/dos-video.h b/drivers/cli/dos-video.h
new file mode 100644 (file)
index 0000000..ee09b51
--- /dev/null
@@ -0,0 +1,22 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2002 Ben Parnell\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+extern int FCEUDvmode;\r
+\r
diff --git a/drivers/cli/dos.c b/drivers/cli/dos.c
new file mode 100644 (file)
index 0000000..8ba1578
--- /dev/null
@@ -0,0 +1,128 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <crt0.h>
+#include <sys/farptr.h>
+#include <go32.h>
+
+#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.\n\
+-joy x          Joystick mapped to virtual joystick x(1-4).\n\
+                 0 = Disabled, reset configuration.\n\
+                 1 = Enabled.";
+
+ARGPSTRUCT DriverArgs[]={
+         {"-vmode",0,&FCEUDvmode,0},
+         {"-sound",0,&soundo,0},
+         {"-f8bit",0,&f8bit,0},
+         {"-joy",0,&joy,0},
+         {"-vsync",0,&eoptions,0x8004},
+         {0,0,0,0}
+};
+
+void DoDriverArgs(void)
+{
+        if(!joy) memset(joyBMap,0,4);
+}
+
+int InitSound(void)
+{
+ if(soundo)
+ {
+  if(soundo==1)
+   soundo=44100;
+  soundo=InitSB(soundo,f8bit?0:1);
+  FCEUI_Sound(soundo);
+ }
+ return(soundo?1:0);
+}
+
+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<count;x++)
+  _farnspokeb(A+x,V);
+}
+
+static char *arg0;
+void GetBaseDirectory(char *BaseDirectory)
+{
+ int x=0;
+
+ if(arg0)
+  for(x=strlen(arg0);x>=0;x--)
+  {
+   if(arg0[x]=='/' || arg0[x]=='\\')
+   {
+    strncpy(BaseDirectory,arg0,x);
+    break;
+   }
+  }
+
+ 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/cli/dos.h b/drivers/cli/dos.h
new file mode 100644 (file)
index 0000000..05bc8e5
--- /dev/null
@@ -0,0 +1,28 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2002 Ben Parnell\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+#include "../../driver.h"\r
+#include "main.h"\r
+\r
+extern int eoptions;\r
+extern int soundo;\r
+void DOSMemSet(uint32 A, uint8 V, uint32 count);\r
+#define DO_CLIPSIDES    1\r
+\r
diff --git a/drivers/cli/input.c b/drivers/cli/input.c
new file mode 100644 (file)
index 0000000..73e2e2f
--- /dev/null
@@ -0,0 +1,340 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define JOY_A   1
+#define JOY_B   2
+#define JOY_SELECT      4
+#define JOY_START       8
+#define JOY_UP  0x10
+#define JOY_DOWN        0x20
+#define JOY_LEFT        0x40
+#define JOY_RIGHT       0x80
+
+static void UpdateFKB(void);
+
+/* UsrInputType[] is user-specified.  InputType[] is current
+       (game loading can override user settings)
+*/
+static int UsrInputType[2]={SI_GAMEPAD,SI_GAMEPAD};
+static int InputType[2];
+
+static int UsrInputTypeFC={SI_NONE};
+static int InputTypeFC;
+
+static uint32 JSreturn;
+int NoWaiting=0;
+
+static void DoCheatSeq(void)
+{
+ #if defined(DOS) || defined(SDL)
+ if(inited&1)
+  SilenceSound(1);
+ #endif
+ KillKeyboard();
+ KillVideo();
+
+ DoConsoleCheatConfig();
+ InitVideo();
+ InitKeyboard();
+ #if defined(DOS) || defined(SDL)
+ if(inited&1)
+  SilenceSound(0);
+ #endif
+}
+
+#include "keyscan.h"
+static char *keys;
+static int DIPS=0;
+static uint8 keyonce[MK_COUNT];
+#define KEY(__a) keys[MK(__a)]
+#define keyonly(__a,__z) {if(KEY(__a)){if(!keyonce[MK(__a)]) {keyonce[MK(__a)]=1;__z}}else{keyonce[MK(__a)]=0;}}
+static int JoySwap=0;
+static int cidisabled=0;
+static int KeyboardUpdate(void)
+{
+
+ if(!UpdateKeyboard())
+   if(keys)
+    return 0;
+
+  keys=GetKeyboard();
+
+  if(InputTypeFC==SIFC_FKB)
+  {
+   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(1);
+  }
+  #ifdef SVGALIB
+  keyonly(F3,LockConsole();)
+  keyonly(F4,UnlockConsole();)
+  #elif SDL
+  keyonly(F4,ToggleFS();)
+  #endif
+  NoWaiting&=~1;
+  if(KEY(GRAVE))
+   NoWaiting|=1;
+
+  if(gametype==GIT_FDS)
+  {
+   keyonly(S,DriverInterface(DES_FDSSELECT,0);)
+   keyonly(I,DriverInterface(DES_FDSINSERT,0);)
+   keyonly(E,DriverInterface(DES_FDSEJECT,0);)
+  }
+
+ keyonly(F9,FCEUI_SaveSnapshot();)
+ if(gametype!=GIT_NSF)
+ {
+  keyonly(F2,DoCheatSeq();)
+  keyonly(F5,FCEUI_SaveState();)
+  keyonly(F7,FCEUI_LoadState();)
+ }
+ else
+ {
+  keyonly(CURSORLEFT,DriverInterface(DES_NSFDEC,0);)
+  keyonly(CURSORRIGHT,DriverInterface(DES_NSFINC,0);)
+  if( KEY(ENTER)) DriverInterface(DES_NSFRES,0);
+  if( KEY(CURSORUP)) DriverInterface(DES_NSFINC,0);
+  if( KEY(CURSORDOWN)) DriverInterface(DES_NSFDEC,0);
+ }
+
+ keyonly(F10,DriverInterface(DES_RESET,0);)
+ keyonly(F11,DriverInterface(DES_POWER,0);)
+ if(KEY(F12) || KEY(ESCAPE)) FCEUI_CloseGame();
+
+ if(gametype==GIT_VSUNI)
+ {
+   keyonly(C,DriverInterface(DES_VSUNICOIN,0);)
+   keyonly(V,DIPS^=1;DriverInterface(DES_VSUNITOGGLEDIPVIEW,0);)
+   if(!(DIPS&1)) goto DIPSless;
+   keyonly(1,DriverInterface(DES_VSUNIDIPSET,(void *)1);)
+   keyonly(2,DriverInterface(DES_VSUNIDIPSET,(void *)2);)
+   keyonly(3,DriverInterface(DES_VSUNIDIPSET,(void *)3);)
+   keyonly(4,DriverInterface(DES_VSUNIDIPSET,(void *)4);)
+   keyonly(5,DriverInterface(DES_VSUNIDIPSET,(void *)5);)
+   keyonly(6,DriverInterface(DES_VSUNIDIPSET,(void *)6);)
+   keyonly(7,DriverInterface(DES_VSUNIDIPSET,(void *)7);)
+   keyonly(8,DriverInterface(DES_VSUNIDIPSET,(void *)8);)
+ }
+ else
+ {
+  keyonly(H,DriverInterface(DES_NTSCSELHUE,0);)
+  keyonly(T,DriverInterface(DES_NTSCSELTINT,0);)
+  if(KEY(KP_MINUS) || KEY(MINUS)) DriverInterface(DES_NTSCDEC,0);
+  if(KEY(KP_PLUS) || KEY(EQUAL)) DriverInterface(DES_NTSCINC,0);
+
+  DIPSless:
+  keyonly(0,FCEUI_SelectState(0);)
+  keyonly(1,FCEUI_SelectState(1);)
+  keyonly(2,FCEUI_SelectState(2);)
+  keyonly(3,FCEUI_SelectState(3);)
+  keyonly(4,FCEUI_SelectState(4);)
+  keyonly(5,FCEUI_SelectState(5);)
+  keyonly(6,FCEUI_SelectState(6);)
+  keyonly(7,FCEUI_SelectState(7);)
+  keyonly(8,FCEUI_SelectState(8);)
+  keyonly(9,FCEUI_SelectState(9);)
+ }
+ return 1;
+}
+
+static uint32 KeyboardDodo(void)
+{
+ uint32 JS=0;
+
+ //if(gametype!=GIT_NSF)
+ {
+  int x,y;
+  x=y=0;
+  keyonly(CAPSLOCK,
+                   {
+                    char tmp[64];
+                    JoySwap=(JoySwap+8)%32;
+                    sprintf(tmp,"Joystick %d selected.",(JoySwap>>3)+1);
+                    FCEUI_DispMessage(tmp);
+                   })
+
+  if(KEY(LEFTALT) || KEY(X))        JS|=JOY_A<<JoySwap;
+  if(KEY(LEFTCONTROL) || KEY(SPACE) || KEY(Z) ) JS |=JOY_B<<JoySwap;
+  if(KEY(ENTER))       JS |= JOY_START<<JoySwap;
+  if(KEY(TAB))         JS |= JOY_SELECT<<JoySwap;
+  if(KEY(CURSORDOWN))  y|= JOY_DOWN;
+  if(KEY(CURSORUP))    y|= JOY_UP;
+  if(KEY(CURSORLEFT))  x|= JOY_LEFT;
+  if(KEY(CURSORRIGHT)) x|= JOY_RIGHT;
+  if(y!=(JOY_DOWN|JOY_UP)) JS|=y<<JoySwap;
+  if(x!=(JOY_LEFT|JOY_RIGHT)) JS|=x<<JoySwap;
+ }
+ return JS;
+}
+
+static int powerpadsc[2][12]={
+                              {
+                               MK(O),MK(P),MK(BRACKET_LEFT),
+                               MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
+                               MK(APOSTROPHE),
+                               MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
+                              },
+                              {
+                               MK(O),MK(P),MK(BRACKET_LEFT),
+                               MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
+                                MK(APOSTROPHE),
+                               MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
+                              }
+                             };
+
+static uint32 powerpadbuf[2];
+static int powerpadside=0;
+
+static uint32 UpdatePPadData(int w)
+{
+ static const char shifttableA[12]={8,9,0,1,11,7,4,2,10,6,5,3};
+ static const char shifttableB[12]={1,0,9,8,2,4,7,11,3,5,6,10};
+ uint32 r=0;
+ int *ppadtsc=powerpadsc[w];
+ int x;
+
+ if(powerpadside&(1<<w))
+ {
+  for(x=0;x<12;x++)
+   if(keys[ppadtsc[x]]) r|=1<<shifttableA[x];
+ }
+ else
+ {
+  for(x=0;x<12;x++)
+   if(keys[ppadtsc[x]]) r|=1<<shifttableB[x];
+ }
+ return r;
+}
+
+static uint32 MouseData[3];
+static uint8 fkbkeys[0x48];
+
+void FCEUD_UpdateInput(void)
+{
+  int x;
+  int t=0;
+  static uint32 KeyBJS=0;
+  uint32 JS;
+  int b;
+
+  b=KeyboardUpdate();
+
+  for(x=0;x<2;x++)
+   switch(InputType[x])
+   {
+    case SI_GAMEPAD:t|=1;break;
+    case SI_ARKANOID:t|=2;break;
+    case SI_ZAPPER:t|=2;break;
+    case SI_POWERPADA:powerpadbuf[x]=UpdatePPadData(x);break;
+   }
+
+  switch(InputTypeFC)
+  {
+   case SIFC_ARKANOID:t|=2;break;
+   case SIFC_SHADOW:t|=2;break;
+   case SIFC_FKB:if(cidisabled) UpdateFKB();break;
+  }
+
+  if(t&1)
+  {
+   if(b)
+    KeyBJS=KeyboardDodo();
+   JS=KeyBJS;
+   JS|=(uint32)GetJSOr();
+   JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
+  }
+  if(t&2)
+   GetMouseData(MouseData);
+}
+
+static void InitOtherInput(void)
+{
+   void *InputDPtr;
+
+   int t;
+   int x;
+   int attrib;
+
+   for(t=0,x=0;x<2;x++)
+   {
+    attrib=0;
+    InputDPtr=0;
+    switch(InputType[x])
+    {
+     case SI_POWERPADA:InputDPtr=&powerpadbuf[x];break;
+     case SI_GAMEPAD:InputDPtr=((uint8 *)&JSreturn)+(x<<1);break;
+     case SI_ARKANOID:InputDPtr=MouseData;t|=1;break;
+     case SI_ZAPPER:InputDPtr=MouseData;
+                                t|=1;
+                                attrib=1;
+                                break;
+    }
+    FCEUI_SetInput(x,InputType[x],InputDPtr,attrib);
+   }
+
+   attrib=0;
+   InputDPtr=0;
+   switch(InputTypeFC)
+   {
+    case SIFC_SHADOW:InputDPtr=MouseData;t|=1;attrib=1;break;
+    case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break;
+    case SIFC_FKB:InputDPtr=fkbkeys;break;
+   }
+
+   FCEUI_SetInputFC(InputTypeFC,InputDPtr,attrib);
+   FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE);
+
+   if(t && !(inited&16))
+   {
+    InitMouse();
+    inited|=16;
+   }
+}
+
+int fkbmap[0x48]=
+{
+ MK(F1),MK(F2),MK(F3),MK(F4),MK(F5),MK(F6),MK(F7),MK(F8),
+ MK(1),MK(2),MK(3),MK(4),MK(5),MK(6),MK(7),MK(8),MK(9),MK(0),
+        MK(MINUS),MK(EQUAL),MK(BACKSLASH),MK(BACKSPACE),
+ MK(ESCAPE),MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I),MK(O),
+        MK(P),MK(GRAVE),MK(BRACKET_LEFT),MK(ENTER),
+ MK(LEFTCONTROL),MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),
+        MK(L),MK(SEMICOLON),MK(APOSTROPHE),MK(BRACKET_RIGHT),MK(INSERT),
+ MK(LEFTSHIFT),MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M),MK(COMMA),
+        MK(PERIOD),MK(SLASH),MK(RIGHTALT),MK(RIGHTSHIFT),MK(LEFTALT),MK(SPACE),
+ MK(DELETE),MK(END),MK(PAGEDOWN),
+ MK(CURSORUP),MK(CURSORLEFT),MK(CURSORRIGHT),MK(CURSORDOWN)
+};
+
+static void UpdateFKB(void)
+{
+ int x;
+
+ for(x=0;x<0x48;x++)
+ {
+  fkbkeys[x]=0;
+  if(keys[fkbmap[x]])
+   fkbkeys[x]=1;
+ }
+}
diff --git a/drivers/cli/keyscan.h b/drivers/cli/keyscan.h
new file mode 100644 (file)
index 0000000..af82127
--- /dev/null
@@ -0,0 +1,166 @@
+#ifdef SVGALIB\r
+\r
+#include <vgakeyboard.h>\r
+#define SCANCODE_DELETE SCANCODE_REMOVE\r
+#define SCANCODE_KP_MINUS      SCANCODE_KEYPADMINUS\r
+#define SCANCODE_KP_PLUS       SCANCODE_KEYPADPLUS\r
+#define MK(k) SCANCODE_##k\r
+#define MK_COUNT 256\r
+#elif SDL\r
+#include <SDL.h>\r
+#define SDLK_A SDLK_a\r
+#define SDLK_B SDLK_b\r
+#define SDLK_C SDLK_c\r
+#define SDLK_D SDLK_d\r
+#define SDLK_E SDLK_e\r
+#define SDLK_F SDLK_f\r
+#define SDLK_G SDLK_g\r
+#define SDLK_H SDLK_h\r
+#define SDLK_I SDLK_i\r
+#define SDLK_J SDLK_j\r
+#define SDLK_K SDLK_k\r
+#define SDLK_L SDLK_l\r
+#define SDLK_M SDLK_m\r
+#define SDLK_N SDLK_n\r
+#define SDLK_O SDLK_o\r
+#define SDLK_P SDLK_p\r
+#define SDLK_Q SDLK_q\r
+#define SDLK_R SDLK_r\r
+#define SDLK_S SDLK_s\r
+#define SDLK_T SDLK_t\r
+#define SDLK_U SDLK_u\r
+#define SDLK_V SDLK_v\r
+#define SDLK_W SDLK_w\r
+#define SDLK_X SDLK_x\r
+#define SDLK_Y SDLK_y\r
+#define SDLK_Z SDLK_z\r
+#define SDLK_LEFTCONTROL SDLK_LCTRL\r
+#define SDLK_RIGHTCONTROL SDLK_RCTRL\r
+#define SDLK_LEFTALT SDLK_LALT\r
+#define SDLK_RIGHTALT SDLK_RALT\r
+#define SDLK_LEFTSHIFT SDLK_LSHIFT\r
+#define SDLK_RIGHTSHIFT SDLK_RSHIFT\r
+#define SDLK_CURSORDOWN SDLK_DOWN\r
+#define SDLK_CURSORUP SDLK_UP\r
+#define SDLK_CURSORLEFT SDLK_LEFT\r
+#define SDLK_CURSORRIGHT SDLK_RIGHT\r
+#define SDLK_ENTER SDLK_RETURN\r
+#define SDLK_EQUAL SDLK_EQUALS\r
+#define SDLK_APOSTROPHE SDLK_QUOTE\r
+#define SDLK_BRACKET_LEFT SDLK_LEFTBRACKET\r
+#define SDLK_BRACKET_RIGHT SDLK_RIGHTBRACKET\r
+#define SDLK_SCROLLLOCK SDLK_SCROLLOCK         /* I guess the SDL people don't like lots of Ls... */\r
+#define SDLK_GRAVE     SDLK_BACKQUOTE\r
+#define MK(k) SDLK_##k\r
+#define MK_COUNT (SDLK_LAST+1)\r
+#elif DOS\r
+\r
+#define SCAN_GRAVE     0x29\r
+#define SCAN_1         0x02\r
+#define SCAN_2         0x03\r
+#define SCAN_3         0x04\r
+#define SCAN_4          0x05\r
+#define SCAN_5          0x06\r
+#define SCAN_6          0x07\r
+#define SCAN_7          0x08\r
+#define SCAN_8          0x09\r
+#define SCAN_9          0x0A\r
+#define SCAN_0          0x0B\r
+#define SCAN_MINUS     0x0C\r
+#define SCAN_EQUAL     0x0D\r
+#define SCAN_BACKSLASH 0x2B\r
+#define SCAN_BACKSPACE 0x0E\r
+#define SCAN_TAB       0x0F\r
+#define SCAN_Q         0x10\r
+#define SCAN_W         0x11\r
+#define SCAN_E         0x12\r
+#define SCAN_R         0x13\r
+#define SCAN_T         0x14\r
+#define SCAN_Y         0x15\r
+#define SCAN_U         0x16\r
+#define SCAN_I         0x17\r
+#define SCAN_O         0x18\r
+#define SCAN_P         0x19\r
+#define SCAN_BRACKET_LEFT      0x1A\r
+#define SCAN_BRACKET_RIGHT     0x1B\r
+#define SCAN_LOWBACKSLASH      0x2B\r
+#define SCAN_CAPSLOCK  0x3A\r
+#define SCAN_A         0x1E\r
+#define SCAN_S         0x1F\r
+#define SCAN_D          0x20\r
+#define SCAN_F          0x21\r
+#define SCAN_G          0x22\r
+#define SCAN_H          0x23\r
+#define SCAN_J          0x24\r
+#define SCAN_K          0x25\r
+#define SCAN_L          0x26\r
+#define SCAN_SEMICOLON 0x27\r
+#define SCAN_APOSTROPHE        0x28\r
+#define SCAN_ENTER     0x1C\r
+#define SCAN_LEFTSHIFT 0x2A\r
+#define SCAN_Z         0x2C\r
+#define SCAN_X         0x2D\r
+#define SCAN_C          0x2E\r
+#define SCAN_V          0x2F\r
+#define SCAN_B          0x30\r
+#define SCAN_N          0x31\r
+#define SCAN_M          0x32\r
+#define SCAN_COMMA      0x33\r
+#define SCAN_PERIOD    0x34\r
+#define SCAN_SLASH     0x35\r
+#define SCAN_RIGHTSHIFT        0x36\r
+#define SCAN_LEFTCONTROL       0x1D\r
+#define SCAN_LEFTALT           0x38\r
+#define SCAN_SPACE             0x39\r
+\r
+/* Extended keys. */\r
+#define SCAN_RIGHTALT          (0x38|0x80)\r
+#define SCAN_RIGHTCONTROL      (0x1D|0x80)\r
+#define SCAN_BL_INSERT         (0x52|0x80)\r
+#define SCAN_BL_DELETE         (0x53|0x80)\r
+#define SCAN_BL_CURSORLEFT     (0x4B|0x80)\r
+#define SCAN_BL_HOME           (0x47|0x80)\r
+#define SCAN_BL_END            (0x4F|0x80)\r
+#define SCAN_BL_CURSORUP       (0x48|0x80)\r
+#define SCAN_BL_CURSORDOWN     (0x50|0x80)\r
+#define SCAN_BL_PAGEUP         (0x49|0x80)\r
+#define SCAN_BL_PAGEDOWN       (0x51|0x80)\r
+#define SCAN_BL_CURSORRIGHT    (0x4D|0x80)\r
+\r
+#define SCAN_SCROLLLOCK         0x46\r
+/* Keys in the key pad area. */\r
+#define SCAN_NUMLOCK           0x45\r
+#define SCAN_HOME              0x47\r
+#define SCAN_CURSORLEFT                0x4B\r
+#define SCAN_END               0x4F\r
+#define SCAN_SLASH             0x35\r
+#define SCAN_CURSORUP          0x48\r
+#define SCAN_CENTER            0x4C\r
+#define SCAN_CURSORDOWN                0x50\r
+#define SCAN_INSERT            0x52\r
+#define SCAN_ASTERISK          0x37\r
+#define SCAN_PAGEUP            0x49\r
+#define SCAN_CURSORRIGHT       0x4D\r
+#define SCAN_PAGEDOWN           0x51\r
+#define SCAN_DELETE          0x53\r
+#define SCAN_KP_MINUS           0x4A\r
+#define SCAN_KP_PLUS            0x4E\r
+#define SCAN_KP_ENTER           0x1C\r
+\r
+#define SCAN_ESCAPE            0x01\r
+#define SCAN_F1                        0x3B\r
+#define SCAN_F2                        0x3C\r
+#define SCAN_F3                 0x3D\r
+#define SCAN_F4                 0x3E\r
+#define SCAN_F5                 0x3F\r
+#define SCAN_F6                 0x40\r
+#define SCAN_F7                 0x41\r
+#define SCAN_F8                 0x42\r
+#define SCAN_F9                 0x43\r
+#define SCAN_F10                0x44\r
+#define SCAN_F11                0x57\r
+#define SCAN_F12                0x58\r
\r
+#define MK_COUNT 256\r
+#define MK(k) SCAN_##k\r
+#endif\r
diff --git a/drivers/cli/lnx-joystick.c b/drivers/cli/lnx-joystick.c
new file mode 100644 (file)
index 0000000..4c2ae6a
--- /dev/null
@@ -0,0 +1,201 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <linux/joystick.h>
+#include "main.h"
+#include "lnx-joystick.h"
+
+int joy[4]={0,0,0,0};
+int joyBMap[4][4];
+
+static int32 joybuttons[4]={0,0,0,0};
+static int32 joyx[4]={0,0,0,0};
+static int32 joyy[4]={0,0,0,0};
+
+static void ConfigJoystick(int z);
+static int fd[4];
+
+#define JOY_A   1
+#define JOY_B   2
+#define JOY_SELECT      4
+#define JOY_START       8
+#define JOY_UP  0x10
+#define JOY_DOWN        0x20
+#define JOY_LEFT        0x40
+#define JOY_RIGHT       0x80
+
+static void UpdateJoyData(int x)
+{
+       struct js_event e;
+
+       while(read(fd[x],&e,sizeof(struct js_event))==sizeof(struct js_event))
+       {
+        e.type&=~JS_EVENT_INIT;
+         if(e.type==JS_EVENT_BUTTON) 
+        {
+          if(e.value)
+           joybuttons[x]|=(1<<e.number);
+          else
+           joybuttons[x]&=~(1<<e.number);
+         }
+        else if(e.type==JS_EVENT_AXIS)
+        {
+         if(e.number==0)
+          joyx[x]=e.value;
+         else if(e.number==1)
+          joyy[x]=e.value;
+        }
+       }
+}
+
+uint32 GetJSOr(void)
+{
+       int x,y;
+       unsigned long ret;
+       ret=0;
+
+       for(x=0;x<4;x++)
+       {
+        int *joym=joyBMap[x];
+
+        if(!joy[x]) continue;
+        UpdateJoyData(x);
+        for(y=0;y<4;y++)
+         if(joybuttons[x]&joym[y]) ret|=(1<<y)<<(x<<3);
+        if(joyx[x]<=-16383) ret|=JOY_LEFT<<(x<<3);
+        else if(joyx[x]>=16383) ret|=JOY_RIGHT<<(x<<3);
+        if(joyy[x]<=-16383) ret|=JOY_UP<<(x<<3);
+        else if(joyy[x]>=16383) ret|=JOY_DOWN<<(x<<3);
+        }
+       return ret;
+}
+
+void KillJoysticks(void)
+{
+       int x;
+       for(x=0;x<4;x++)
+        if(joy[x]) 
+         close(fd[x]);
+}
+
+int InitJoysticks(void)
+{
+       char dbuf[64];
+       int version;
+       int z;
+
+       for(z=0;z<4;z++)
+       {
+        if(!joy[z]) continue;
+        sprintf(dbuf,"/dev/js%d",joy[z]-1);
+        if((fd[z]=open(dbuf,O_RDONLY|O_NONBLOCK))<0) 
+        {
+          printf("Could not open %s.\n",dbuf);
+          joy[z]=0;
+          continue;
+         }
+
+         if(ioctl(fd[z], JSIOCGVERSION, &version)==-1) 
+        {
+         printf("Error using ioctl JSIOCGVERSION on %s.\n",dbuf);
+         joy[z]=0;
+         close(fd[z]);
+         continue;
+        }
+
+         if(!(joyBMap[z][0]|joyBMap[z][1]|joyBMap[z][2]|joyBMap[z][3]))
+          ConfigJoystick(z);
+        }
+
+       return(joy[0]|joy[1]|joy[2]|joy[3]);
+}
+
+#define WNOINPUT(); for(;;){uint8 t; if(read(fileno(stdin),&t,1)==-1) \
+                          {break;}}
+
+static void BConfig(int z,int b)
+{
+  WNOINPUT();
+  for(;;)
+  {
+   uint8 t;
+   if(read(fileno(stdin),&t,1)==-1)
+   {
+    if(errno!=EAGAIN) break;
+   }
+   else
+    break;
+
+   {
+    struct js_event e;
+
+    while(read(fd[z],&e,sizeof(struct js_event))==sizeof(struct js_event))
+    {
+      if(e.type==JS_EVENT_BUTTON)
+      {
+       if(!e.value)
+       {
+       joyBMap[z][b]=1<<e.number;
+       goto endsa;
+       }
+      }
+    }
+   }
+
+  }
+  endsa:
+  WNOINPUT();
+}
+
+void ConfigJoystick(int z)
+{
+ int sa;
+ static char *genb="** Press button for ";
+
+ printf("\n\n Joystick button configuration:\n\n");
+ printf("   Push the button to map to the virtual joystick.\n");
+ printf("   If you do not wish to assign a button, press Enter to skip\n");
+ printf("   that button.\n\n");
+ printf("   Press enter to continue...\n");
+ getchar();
+ printf("****  Configuring joystick %d ****\n\n",z+1);
+
+ sa=fcntl(fileno(stdin),F_GETFL);
+ fcntl(fileno(stdin),F_SETFL,O_NONBLOCK);
+
+  printf("%s\"Select\".\n",genb);
+  BConfig(z,2);
+
+  printf("%s\"Start\".\n",genb);
+  BConfig(z,3);
+
+  printf("%s\"B\".\n",genb);
+  BConfig(z,1);
+
+  printf("%s\"A\".\n",genb);
+  BConfig(z,0);
+
+  fcntl(fileno(stdin),F_SETFL,sa);
+}
+
diff --git a/drivers/cli/lnx-joystick.h b/drivers/cli/lnx-joystick.h
new file mode 100644 (file)
index 0000000..a38ae77
--- /dev/null
@@ -0,0 +1,3 @@
+extern int joy[4];
+extern int joyBMap[4][4];
+
diff --git a/drivers/cli/main.c b/drivers/cli/main.c
new file mode 100644 (file)
index 0000000..168916e
--- /dev/null
@@ -0,0 +1,377 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*  This file contains or coordinates all of the code necessary to compile
+    on a UNIX system that can use svgalib, such as FreeBSD and Linux.
+    This code is not guaranteed to compile on FreeBSD, though.
+*/
+
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "main.h"
+#include "throttle.h"
+
+#include "../common/config.h"
+#include "../common/args.h"
+#include "../common/unixdsp.h"
+#include "../common/cheat.h"
+
+#include "dface.h"
+
+static int ntsccol=0,ntschue=-1,ntsctint=-1;
+/*static*/ int soundvol=100;
+static int inited=0;
+
+int srendlinev[2]={8,0};
+int erendlinev[2]={239,239};
+int srendline,erendline;
+
+
+static char BaseDirectory[2048];
+
+int eoptions=0;
+
+static void DriverKill(void);
+static int DriverInitialize(void);
+
+static int gametype;
+#include "input.c"
+
+static void ParseGI(FCEUGI *gi)
+{
+ gametype=gi->type;
+
+ InputType[0]=UsrInputType[0];
+ InputType[1]=UsrInputType[1];
+ InputTypeFC=UsrInputTypeFC;
+
+ if(gi->input[0]>=0)
+  InputType[0]=gi->input[0];
+ if(gi->input[1]>=0)
+  InputType[1]=gi->input[1];
+ if(gi->inputfc>=0)
+  InputTypeFC=gi->inputfc;
+ FCEUI_GetCurrentVidSystem(&srendline,&erendline);
+}
+
+void FCEUD_PrintError(char *s)
+{
+ puts(s);
+}
+
+static char *cpalette=0;
+static void LoadCPalette(void)
+{
+ uint8 tmpp[192];
+ FILE *fp;
+
+ if(!(fp=fopen(cpalette,"rb")))
+ {
+  printf(" Error loading custom palette from file: %s\n",cpalette);
+  return;
+ }
+ fread(tmpp,1,192,fp);
+ FCEUI_SetPaletteArray(tmpp);
+ fclose(fp);
+}
+
+static CFGSTRUCT fceuconfig[]={
+       AC(soundvol),
+       ACS(cpalette),
+       AC(ntsctint),
+       AC(ntschue),
+       AC(ntsccol),
+       AC(UsrInputTypeFC),
+       ACA(UsrInputType),
+       AC(powerpadside),
+       AC(powerpadsc),
+       AC(eoptions),
+       ACA(srendlinev),
+       ACA(erendlinev),
+       ADDCFGSTRUCT(DriverConfig),
+       ENDCFGSTRUCT
+};
+
+static void SaveConfig(void)
+{
+       char tdir[2048];
+       sprintf(tdir,"%s"PSS"fceu.cfg",BaseDirectory);
+        DriverInterface(DES_GETNTSCTINT,&ntsctint);
+        DriverInterface(DES_GETNTSCHUE,&ntschue);
+        SaveFCEUConfig(tdir,fceuconfig);
+}
+
+static void LoadConfig(void)
+{
+       char tdir[2048];
+        sprintf(tdir,"%s"PSS"fceu.cfg",BaseDirectory);
+        LoadFCEUConfig(tdir,fceuconfig);
+        if(ntsctint>=0) DriverInterface(DES_SETNTSCTINT,&ntsctint);
+        if(ntschue>=0) DriverInterface(DES_SETNTSCHUE,&ntschue);
+}
+
+static void CreateDirs(void)
+{
+ char *subs[5]={"fcs","snaps","gameinfo","sav","cheats"};
+ char tdir[2048];
+ int x;
+
+ mkdir(BaseDirectory,S_IRWXU);
+ for(x=0;x<5;x++)
+ {
+  sprintf(tdir,"%s"PSS"%s",BaseDirectory,subs[x]);
+  mkdir(tdir,S_IRWXU);
+ }
+}
+
+static void SetSignals(void (*t)(int))
+{
+  int sigs[11]={SIGINT,SIGTERM,SIGHUP,SIGPIPE,SIGSEGV,SIGFPE,SIGKILL,SIGALRM,SIGABRT,SIGUSR1,SIGUSR2};
+  int x;
+  for(x=0;x<11;x++)
+   signal(sigs[x],t);
+}
+
+static void CloseStuff(int signum)
+{
+       DriverKill();
+        printf("\nSignal %d has been caught and dealt with...\n",signum);
+        switch(signum)
+        {
+         case SIGINT:printf("How DARE you interrupt me!\n");break;
+         case SIGTERM:printf("MUST TERMINATE ALL HUMANS\n");break;
+         case SIGHUP:printf("Reach out and hang-up on someone.\n");break;
+         case SIGPIPE:printf("The pipe has broken!  Better watch out for floods...\n");break;
+         case SIGSEGV:printf("Iyeeeeeeeee!!!  A segmentation fault has occurred.  Have a fluffy day.\n");break;
+        /* So much SIGBUS evil. */
+        #ifdef SIGBUS
+        #if(SIGBUS!=SIGSEGV)
+         case SIGBUS:printf("I told you to be nice to the driver.\n");break;
+        #endif
+        #endif
+         case SIGFPE:printf("Those darn floating points.  Ne'er know when they'll bite!\n");break;
+         case SIGALRM:printf("Don't throw your clock at the meowing cats!\n");break;
+         case SIGABRT:printf("Abort, Retry, Ignore, Fail?\n");break;
+         case SIGUSR1:
+         case SIGUSR2:printf("Killing your processes is not nice.\n");break;
+        }
+        exit(1);
+}
+
+static void DoArgs(int argc, char *argv[])
+{
+        static char *cortab[5]={"none","gamepad","zapper","powerpad","arkanoid"};
+        static int cortabi[5]={SI_NONE,SI_GAMEPAD,
+                               SI_ZAPPER,SI_POWERPADA,SI_ARKANOID};
+       static char *fccortab[5]={"none","arkanoid","shadow","4player","fkb"};
+       static int fccortabi[5]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW,
+                                SIFC_4PLAYER,SIFC_FKB};
+
+       int x;
+       static char *inputa[2]={0,0};
+       static char *fcexp=0;
+       static int docheckie[4];
+
+        static ARGPSTRUCT FCEUArgs[]={
+         {"-soundvol",0,&soundvol,0},
+         {"-cpalette",0,&cpalette,0x4001},
+
+         {"-ntsccol",0,&ntsccol,0},
+         {"-pal",&docheckie[0],0,0},
+         {"-input1",0,&inputa[0],0x4001},{"-input2",0,&inputa[1],0x4001},
+         {"-fcexp",0,&fcexp,0x4001},
+
+         {"-gg",&docheckie[1],0,0},
+         {"-no8lim",0,&eoptions,0x8001},
+         {"-subase",0,&eoptions,0x8002},
+         {"-snapname",0,&eoptions,0x8000|EO_SNAPNAME},
+        {"-nofs",0,&eoptions,0x8000|EO_NOFOURSCORE},
+         {"-clipsides",0,&eoptions,0x8000|EO_CLIPSIDES},
+        {"-nothrottle",0,&eoptions,0x8000|EO_NOTHROTTLE},
+         {"-slstart",0,&srendlinev[0],0},{"-slend",0,&erendlinev[0],0},
+         {"-slstartp",0,&srendlinev[1],0},{"-slendp",0,&erendlinev[1],0},
+        {0,(void *)DriverArgs,0,0},
+        {0,0,0,0}
+        };
+
+        memset(docheckie,0,sizeof(docheckie));
+       ParseArguments(argc, argv, FCEUArgs);
+       if(cpalette)
+       {
+        if(cpalette[0]=='0')
+         if(cpalette[1]==0)
+         {
+          free(cpalette);
+          cpalette=0;
+         }
+       }
+       if(docheckie[0])
+        FCEUI_SetVidSystem(1);
+       if(docheckie[1])
+        FCEUI_SetGameGenie(1);
+
+        FCEUI_DisableSpriteLimitation(eoptions&1);
+        FCEUI_SaveExtraDataUnderBase(eoptions&2);
+       FCEUI_SetSnapName(eoptions&EO_SNAPNAME);
+
+       for(x=0;x<2;x++)
+       {
+         if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0;
+         if(erendlinev[x]<srendlinev[x] || erendlinev[x]>239) erendlinev[x]=239;
+       }
+
+        FCEUI_SetRenderedLines(srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]);
+        FCEUI_SetSoundVolume(soundvol);
+       //DriverInterface(DES_NTSCCOL,&ntsccol);
+       DoDriverArgs();
+
+       if(fcexp)
+       {
+        int y;
+         for(y=0;y<5;y++)
+         {
+          if(!strncmp(fccortab[y],fcexp,8))
+          {
+          UsrInputTypeFC=fccortabi[y];
+          break;
+          }
+         }
+        free(fcexp);
+       }
+       for(x=0;x<2;x++)
+       {
+        int y;
+
+         if(!inputa[x])
+         continue;
+
+        for(y=0;y<5;y++)
+        {
+         if(!strncmp(cortab[y],inputa[x],8))
+         {
+          UsrInputType[x]=cortabi[y];
+          if(y==3)
+          {
+           powerpadside&=~(1<<x);
+           powerpadside|=((((inputa[x][8])-'a')&1)^1)<<x;
+          }
+          free(inputa[x]);
+         }
+        }
+       }
+}
+
+#include "usage.h"
+
+int CLImain(int argc, char *argv[])
+{
+       FCEUGI *tmp;
+       int ret;
+
+       if(!(ret=FCEUI_Initialize()))
+         return(1);
+        GetBaseDirectory(BaseDirectory);
+       FCEUI_SetBaseDirectory(BaseDirectory);
+
+       CreateDirs();
+        if(argc<=1)
+        {
+         ShowUsage(argv[0]);
+         return 1;
+        }
+        LoadConfig();
+        DoArgs(argc-2,&argv[1]);
+       FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
+       if(cpalette)
+        LoadCPalette();
+       if(InitSound())
+        inited|=1;
+
+        if(!(tmp=FCEUI_LoadGame(argv[argc-1])))
+        {
+         ret=0;
+         goto dk;
+        }
+       ParseGI(tmp);
+       RefreshThrottleFPS();
+        if(!DriverInitialize())
+        {
+         ret=0;
+         goto dk;
+        }
+       InitOtherInput();
+       FCEUI_Emulate();
+
+       dk:
+       DriverKill();
+        return(ret?0:1);
+}
+
+static int DriverInitialize(void)
+{
+   SetSignals((void *)CloseStuff);
+
+   if(InitJoysticks())
+    inited|=2;
+   if(!InitVideo()) return 0;
+   inited|=4;
+   if(!InitKeyboard()) return 0;
+   inited|=8;
+   return 1;
+}
+
+static void DriverKill(void)
+{
+ SaveConfig();
+ SetSignals(SIG_IGN);
+
+ if(inited&2)
+  KillJoysticks();
+ if(inited&8)
+  KillKeyboard();
+ if(inited&4)
+  KillVideo();
+ if(inited&1)
+  KillSound();
+ if(inited&16)
+  KillMouse();
+ inited=0;
+}
+
+void FCEUD_Update(uint8 *XBuf, int16 *Buffer, int Count)
+{
+ if(!Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE))
+  SpeedThrottle();
+ BlitScreen(XBuf);
+ if(Count)
+  WriteSound(Buffer,Count,NoWaiting);
+ FCEUD_UpdateInput();
+}
+
diff --git a/drivers/cli/main.h b/drivers/cli/main.h
new file mode 100644 (file)
index 0000000..99dc5b5
--- /dev/null
@@ -0,0 +1,30 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "../../driver.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
+extern int srendline,erendline,srendlinev[2],erendlinev[2];
+extern int NoWaiting;
diff --git a/drivers/cli/sdl-joystick.c b/drivers/cli/sdl-joystick.c
new file mode 100644 (file)
index 0000000..1a3fecf
--- /dev/null
@@ -0,0 +1,200 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Ben Parnell
+ *  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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "sdl.h"
+static SDL_Joystick *jo[4] = {NULL, NULL, NULL, NULL};
+
+static void ConfigJoystick (int z);
+
+#define JOY_A          0x01
+#define JOY_B          0x02
+#define JOY_SELECT     0x04
+#define JOY_START      0x08
+#define JOY_UP         0x10
+#define JOY_DOWN       0x20
+#define JOY_LEFT       0x40
+#define JOY_RIGHT      0x80
+
+/* Gets the current joystick position information. */
+uint32 GetJSOr (void)
+{
+       int n;                  /* joystick index */
+       int b;                  /* button index */
+       int *joym;              /* pointer to a joystick's button map */
+       Sint16 pos;             /* axis position */
+       uint32 ret = 0;         /* return value */
+
+       for (n = 0; n < 4; n++)
+       {
+               if (joy[n] == 0)
+                       continue;
+               joym = joyBMap[n];
+
+               /* Axis information. */
+               pos = SDL_JoystickGetAxis(jo[n], joyAMap[n][0]);
+               if (pos <= -16383)
+                       ret |= JOY_LEFT << (n << 3);
+               else if (pos >= 16363)
+                       ret |= JOY_RIGHT << (n << 3);
+               pos = SDL_JoystickGetAxis(jo[n], joyAMap[n][1]);
+               if (pos <= -16383)
+                       ret |= JOY_UP << (n << 3);
+               else if (pos >= 16383)
+                       ret |= JOY_DOWN << (n << 3);
+
+               /* Button information. */
+               for (b = 0; b < 4; b++)
+               {
+                       if (SDL_JoystickGetButton(jo[n], joym[b]))
+                               ret |= (1 << b) << (n << 3);
+               }
+       }
+
+       return ret;
+}
+
+/* Cleanup opened joysticks. */
+void KillJoysticks (void)
+{
+       int n;                  /* joystick index */
+
+       for (n = 0; n < 4; n++)
+       {
+               if (joy[n] != 0)
+                       SDL_JoystickClose(jo[n]);
+       }
+       SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+       return;
+}
+
+/* Initialize joysticks. */
+int InitJoysticks (void)
+{
+       int n;                  /* joystick index */
+       if(!(joy[0]|joy[1]|joy[2]|joy[3]))
+        return(0);
+       SDL_InitSubSystem(SDL_INIT_JOYSTICK);
+       for (n = 0; n < 4; n++)
+       {
+               if (joy[n] == 0)
+                       continue;
+               
+               /* Open the joystick under SDL. */
+               jo[n] = SDL_JoystickOpen(joy[n] - 1);
+               if (jo[n] == NULL)
+               {
+                       printf("Could not open joystick %d: %s.\n",
+                               joy[n] - 1, SDL_GetError());
+                       joy[n] = 0;
+                       continue;
+               }
+
+               /* Check for a button map. */
+               if (!(joyBMap[n][0] | joyBMap[n][1] | joyBMap[n][2] |
+                       joyBMap[n][3]))
+               {
+                       ConfigJoystick(n);
+               }
+       }
+
+       return (1);
+}
+
+#define WNOINPUT(); for(;;){uint8 t; if(read(fileno(stdin),&t,1)==-1) \
+                       {break;}}
+
+/* Configure a joystick button. */
+static void BConfig (int n, int b)
+{
+       SDL_Event event;                /* SDL event structure */
+       WNOINPUT();
+       while (1)
+       {
+               uint8 t;
+               if (read(fileno(stdin), &t, 1) == -1)
+               {
+                       if (errno != EAGAIN)
+                               break;
+               }
+               else
+                       break;
+               
+               if (SDL_PollEvent(&event) && event.type == SDL_JOYBUTTONDOWN)
+               {
+                       joyBMap[n][b] = event.jbutton.button;
+                       goto endsa;
+               }
+       }
+
+       endsa:
+       WNOINPUT();
+
+       return;
+}
+
+/* Joystick button and axis configuration. */
+void ConfigJoystick (int n)
+{
+       int sa;                 /* buffer value */
+       char buf[128];          /* input buffer */
+
+       printf("\n\n Joystick button and axis configuration:\n\n");
+       printf("   Select the joystick axes to use for the virtual d-pad.\n");
+       printf("   If you do not wish to assign an axis, press Enter to skip\n");
+       printf("   that axis.\n");
+       printf("   Push the button to map to the virtual joystick.\n");
+       printf("   If you do not wish to assign a button, press Enter to skip\n");
+       printf("   that button.\n   Press enter to continue...\n");
+       getchar();
+       printf("****  Configuring joystick %d ****\n\n", n + 1);
+
+       printf("** Enter axis to use for the x-axis (default 0).\n");
+       fgets(buf, sizeof(buf), stdin);
+       joyAMap[n][0] = ('0' <= buf[0] && buf[9] <= '9') ? atoi(buf) : 0;
+
+       printf("** Enter axis to use for the y-axis (default 1).\n");
+       fgets(buf, sizeof(buf), stdin);
+       joyAMap[n][1] = ('0' <= buf[0] && buf[9] <= '9') ? atoi(buf) : 1;
+
+       sa = fcntl(fileno(stdin), F_GETFL);
+       fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
+
+       printf("** Press button for \"Select\".\n");
+       BConfig(n, 2);
+
+       printf("** Press button for \"Start\".\n");
+       BConfig(n, 3);
+
+       printf("** Press button for \"B\".\n");
+       BConfig(n, 1);
+
+       printf("** Press button for \"A\".\n");
+       BConfig(n, 0);
+       
+       fcntl(fileno(stdin), F_SETFL, sa);
+}
diff --git a/drivers/cli/sdl-netplay.c b/drivers/cli/sdl-netplay.c
new file mode 100644 (file)
index 0000000..38a4c81
--- /dev/null
@@ -0,0 +1,163 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2001 LULU
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "sdl.h"
+#include <SDL/SDL_net.h>
+#include "sdl-netplay.h"
+
+char *netplayhost=0;
+
+static int tonowait;
+
+int Port=0xFCE;
+int FDnetplay=0;
+
+
+static SDLNet_SocketSet socketset = NULL;
+static TCPsocket tcpsock = NULL, servsock = NULL;
+
+void cleanup(void)
+{
+    if (tcpsock != NULL) {
+        SDLNet_TCP_DelSocket(socketset, tcpsock);
+        SDLNet_TCP_Close(tcpsock);
+        tcpsock = NULL;
+    }
+    if (servsock != NULL) {
+        SDLNet_TCP_DelSocket(socketset, servsock);
+        SDLNet_TCP_Close(servsock);
+        servsock = NULL;
+    }
+    if (socketset != NULL) {
+        SDLNet_FreeSocketSet(socketset);
+        socketset = NULL;
+    }
+}
+
+int FCEUD_NetworkConnect(void)
+{
+    IPaddress serverIP;
+
+    tonowait=0;
+
+    if (netplay == 2) {
+        /* client */
+        printf("connecting to %s\n", netplayhost);
+
+        SDLNet_ResolveHost(&serverIP, netplayhost, Port);
+        if (serverIP.host == INADDR_NONE) {
+            fprintf(stderr, "Couldn't connected to %s\n", netplayhost);
+            return -1;
+        } else {
+            tcpsock = SDLNet_TCP_Open(&serverIP);
+            if (tcpsock == NULL) {
+                fprintf(stderr, "Couldn't connected to %s\n", netplayhost);
+                return -1;
+            }
+        }
+        printf("connected to %s\n", netplayhost);
+
+        socketset = SDLNet_AllocSocketSet(1);
+        if (socketset == NULL) {
+            fprintf(stderr, "Couldn't create socket set: %s\n",
+                    SDLNet_GetError());
+            return -1;
+        }
+        SDLNet_TCP_AddSocket(socketset, tcpsock);
+
+        return 1;
+    } else {
+        /* server */
+
+        SDLNet_ResolveHost(&serverIP, NULL, Port);
+        printf("Server IP: %x, %d\n", serverIP.host, serverIP.port);
+        servsock = SDLNet_TCP_Open(&serverIP);
+        if (servsock == NULL) {
+            cleanup();
+            fprintf(stderr, "Couldn't create server socket: %s\n",
+                    SDLNet_GetError());
+            return -1;
+        }
+
+        socketset = SDLNet_AllocSocketSet(2);
+        if (socketset == NULL) {
+            fprintf(stderr, "Couldn't create socket set: %s\n",
+                    SDLNet_GetError());
+            return -1;
+        }
+        SDLNet_TCP_AddSocket(socketset, servsock);
+
+        if (SDLNet_CheckSockets(socketset, ~0)) {
+            tcpsock = SDLNet_TCP_Accept(servsock);
+            if (tcpsock == NULL) {
+                return -1;
+            }
+            SDLNet_TCP_AddSocket(socketset, tcpsock);
+
+            printf("OK, connected\n");
+            return 1;
+        }
+    }
+
+    return -1;
+}
+
+void FCEUD_NetworkClose(void)
+{
+    cleanup();
+}
+
+int FCEUD_NetworkRecvData(uint8 *data, uint32 len, int block)
+{
+  if(block)
+  {
+   if(SDLNet_TCP_Recv(tcpsock, (void *) data, len)!=len)
+   {
+    cleanup();
+    return(0);
+   }
+   switch(SDLNet_CheckSockets(socketset,0))
+   {
+    case -1:return(0);
+    case 0:NoWaiting&=~2;tonowait=0;break; 
+    default:if(tonowait>=3)
+            NoWaiting|=2;
+           else tonowait++;
+           break;
+   }
+   return(1);
+  }
+  else
+  {
+   int t=SDLNet_CheckSockets(socketset,0);
+   if(t<0) return(0);
+   if(!t) return(-1);
+   return(SDLNet_TCP_Recv(tcpsock, (void *) data, len)==len);
+  }
+}
+
+/* 0 on failure, 1 on success.  This function should always block. */
+int FCEUD_NetworkSendData(uint8 *Value, uint32 len)
+{
+    if (tcpsock)
+        return(SDLNet_TCP_Send(tcpsock, (void *) Value, len)==len);
+    return 0;
+}
diff --git a/drivers/cli/sdl-netplay.h b/drivers/cli/sdl-netplay.h
new file mode 100644 (file)
index 0000000..48769f6
--- /dev/null
@@ -0,0 +1,5 @@
+extern char *netplayhost;
+extern int Port;
+extern int FDnetplay;
+#define netplay FDnetplay
+
diff --git a/drivers/cli/sdl-sound.c b/drivers/cli/sdl-sound.c
new file mode 100644 (file)
index 0000000..f8ab865
--- /dev/null
@@ -0,0 +1,148 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include "sdl.h"
+
+#ifndef DSPSOUND
+
+//#define BSIZE (32768-1024)
+
+static int32 BSIZE;
+static volatile int16 AudioBuf[32768];
+static volatile uint32 readoffs,writeoffs;
+void fillaudio(void *udata, uint8 *stream, int len)
+{
+ int16 *dest=(int16 *)stream;
+
+ len>>=1;
+ while(len)
+ {
+  *dest=AudioBuf[readoffs];
+  dest++;
+  readoffs=(readoffs+1)&32767;
+  len--;
+ }
+}
+
+void WriteSound(int16 *Buffer, int Count, int NoWaiting)
+{
+ while(Count)
+ {
+  while(writeoffs==((readoffs-BSIZE)&32767))
+   if(NoWaiting)
+    return;
+  AudioBuf[writeoffs]=*Buffer;
+  writeoffs=(writeoffs+1)&32767;
+  Buffer++;
+  Count--;
+ }
+}
+
+int InitSound(void)
+{
+ if(_sound)
+ {
+  SDL_AudioSpec spec;
+
+  if(_lbufsize<_ebufsize)
+  {
+   puts("Ack, lbufsize must not be smaller than ebufsize!");
+   return(0);
+  }
+  if(_lbufsize<6 || _lbufsize>13)
+  {
+   puts("lbufsize out of range");
+   return(0);
+  }
+  if(_ebufsize<5)
+  {
+   puts("ebufsize out of range");
+   return(0);
+  }
+  memset(&spec,0,sizeof(spec));
+  if(SDL_InitSubSystem(SDL_INIT_AUDIO)<0)
+  {
+   puts(SDL_GetError());
+   return(0);
+  }
+  if(_sound==1) _sound=44100;
+  spec.freq=_sound;
+  spec.format=AUDIO_S16;
+  spec.channels=1;
+  spec.samples=1<<_ebufsize;
+  spec.callback=fillaudio;
+  spec.userdata=0;
+
+  if(SDL_OpenAudio(&spec,0)<0)
+  {
+   puts(SDL_GetError());
+   SDL_QuitSubSystem(SDL_INIT_AUDIO);
+   return(0);
+  }
+  FCEUI_Sound(_sound);
+  BSIZE=32768-(1<<_lbufsize);
+  SDL_PauseAudio(0);
+  return(1);
+ }
+ return(0);
+}
+
+void SilenceSound(int n)
+{
+ SDL_PauseAudio(n);
+
+}
+
+void KillSound(void)
+{
+ SDL_CloseAudio();
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+}
+
+#else
+#include "../common/unixdsp.h"
+
+void WriteSound(int32 *Buffer, int Count, int NoWaiting)
+{
+  WriteUNIXDSPSound(Buffer, Count, NoWaiting);
+}
+
+int InitSound(void)
+{
+        if(_sound)
+        {
+         int rate;
+         if(_sound==1)
+          _sound=48000;
+         rate=_sound;
+         if(InitUNIXDSPSound(&rate,_f8bit?0:1,8,8))
+         {
+          FCEUI_Sound(rate);
+          return(1);
+         }
+        }
+        return(0);
+}
+void KillSound(void)
+{
+        KillUNIXDSPSound();
+}
+#endif
diff --git a/drivers/cli/sdl-video.c b/drivers/cli/sdl-video.c
new file mode 100644 (file)
index 0000000..b805a8a
--- /dev/null
@@ -0,0 +1,228 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "sdl.h"
+#include "../common/vidblit.h"
+
+#define _sline srendline
+#define _eline erendline
+
+SDL_Surface *screen;
+
+static int tlines;
+static int inited=0;
+
+static int exs,eys,eefx;
+#define NWIDTH (256-((eoptions&EO_CLIPSIDES)?16:0))
+#define NOFFSET        (32-8+(eoptions&EO_CLIPSIDES?8:0))
+
+static void CleanSurface(void)
+{
+ uint32 x;
+
+ x=screen->pitch*screen->h;
+
+ if(SDL_MUSTLOCK(screen))
+  SDL_LockSurface(screen);
+
+ memset((uint8*)screen->pixels, 0x80, x);
+
+ if(SDL_MUSTLOCK(screen))
+  SDL_UnlockSurface(screen);
+
+ SDL_UpdateRect(screen, 0, 0, 0, 0);
+}
+
+static int paletterefresh;
+
+void KillVideo(void)
+{
+ if(inited&1)
+ {
+  SDL_QuitSubSystem(SDL_INIT_VIDEO);
+ }
+ inited=0;
+}
+
+int InitVideo(void)
+{
+ const SDL_VideoInfo *vinf;
+ int flags=0;
+
+ #ifdef BROKEN
+ if(_fullscreen && _fshack)
+  setenv("SDL_VIDEODRIVER",_fshack,1);
+ else
+ {
+  if(!_fshacksave)
+   unsetenv("SDL_VIDEODRIVER");
+  else
+   setenv("SDL_VIDEODRIVER",_fshacksave,1);
+ }
+ #endif
+ if(SDL_InitSubSystem(SDL_INIT_VIDEO)==-1)
+ {
+  puts(SDL_GetError());
+  return(0);
+ }
+ inited|=1;
+
+ SDL_ShowCursor(0);
+ tlines=_eline-_sline+1;
+
+ vinf=SDL_GetVideoInfo();
+
+ if(vinf->hw_available)
+  flags|=SDL_HWSURFACE;
+
+ if(_fullscreen)
+  flags|=SDL_FULLSCREEN;
+ flags|=SDL_HWPALETTE;
+
+ if(_fullscreen)
+ {
+  exs=_xscalefs;
+  eys=_yscalefs;
+  eefx=_efxfs;
+  if(_xres<NWIDTH*exs || _yres<tlines*eys)
+  {
+   puts("xscale and/or yscale out of bounds.");
+   KillVideo();
+   return(0);
+  }
+  screen = SDL_SetVideoMode(_xres, _yres, 8, flags);
+ }
+ else
+ {
+  exs=_xscale;
+  eys=_yscale;
+  eefx=_efx;
+  screen = SDL_SetVideoMode(NWIDTH*exs, tlines*eys, 8, flags);
+ }
+ if(!screen)
+ {
+  puts(SDL_GetError());
+  KillVideo();
+  return(0);
+ }
+ inited=1;
+ CleanSurface();
+
+ SDL_WM_SetCaption("FCE Ultra","FCE Ultra");
+ paletterefresh=1;
+ return 1;
+}
+
+void ToggleFS(void)
+{
+ KillVideo();
+ _fullscreen=!_fullscreen;
+
+ if(!InitVideo())
+ {
+  _fullscreen=!_fullscreen;
+  if(!InitVideo())
+  {
+   puts("Gah, bailing out.");
+   exit(1);
+  }
+ }
+}
+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)
+{
+ SDL_SetPalette(screen,SDL_PHYSPAL,psdl,0,256);
+}
+
+void LockConsole(){}
+void UnlockConsole(){}
+void BlitScreen(uint8 *XBuf)
+{
+ uint8 *dest;
+ int xo=0,yo=0;
+
+ if(paletterefresh)
+ {
+  RedoPalette();
+  paletterefresh=0;
+ }
+
+ XBuf+=_sline*320;
+
+ if(SDL_MUSTLOCK(screen))
+  SDL_LockSurface(screen);
+
+ dest=screen->pixels;
+
+ if(_fullscreen)
+ {
+  xo=(((screen->w-NWIDTH*exs))>>1);
+  dest+=xo;
+  if(screen->h>(tlines*eys))
+  {
+   yo=((screen->h-tlines*eys)>>1);
+   dest+=yo*screen->pitch;
+  }
+ }
+
+ Blit8To8(XBuf+NOFFSET,dest, NWIDTH, tlines, screen->pitch,exs,eys,eefx);
+
+ if(SDL_MUSTLOCK(screen))
+  SDL_UnlockSurface(screen);
+
+ SDL_UpdateRect(screen, xo, yo, NWIDTH*exs, tlines*eys);
+}
+
+uint32 PtoV(uint16 x, uint16 y)
+{
+ if(_fullscreen)
+ {
+
+ }
+ else
+ {
+  if(eoptions&EO_CLIPSIDES)
+   x+=8;
+  y+=srendline;
+ }
+ return(x|(y<<16));
+}
diff --git a/drivers/cli/sdl-video.h b/drivers/cli/sdl-video.h
new file mode 100644 (file)
index 0000000..036c933
--- /dev/null
@@ -0,0 +1 @@
+uint32 PtoV(uint16 x, uint16 y);
diff --git a/drivers/cli/sdl.c b/drivers/cli/sdl.c
new file mode 100644 (file)
index 0000000..77decae
--- /dev/null
@@ -0,0 +1,216 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sdl.h"
+#include "sdl-video.h"
+#ifdef NETWORK
+#include "unix-netplay.h"
+#endif
+
+DSETTINGS Settings;
+CFGSTRUCT DriverConfig[]={
+       AC(_xscale),
+       AC(_yscale),
+       AC(_xscalefs),
+       AC(_yscalefs),
+       AC(_efx),
+       AC(_efxfs),
+        AC(_sound),
+       #ifdef DSPSOUND
+        AC(_f8bit),
+       #else
+       AC(_ebufsize),
+       AC(_lbufsize),
+       #endif
+       AC(_fullscreen),
+        AC(_xres),
+       AC(_yres),
+        ACA(joyBMap),
+       ACA(joyAMap),
+        ACA(joy),
+        //ACS(_fshack),
+        ENDCFGSTRUCT
+};
+
+//-fshack x       Set the environment variable SDL_VIDEODRIVER to \"x\" when
+//                entering full screen mode and x is not \"0\".
+
+char *DriverUsage=
+"-xres   x       Set horizontal resolution to x for full screen mode.\n\
+-yres   x       Set vertical resolution to x for full screen mode.\n\
+-xscale(fs) x  Multiply width by x.\n\
+-yscale(fs) x  Multiply height by x.\n\
+-efx(fs) x     Enable scanlines effect if x is non zero.  yscale must be >=2\n\
+               and preferably a multiple of 2.\n\
+-fs     x      Select full screen mode if x is non zero.\n\
+-joyx   y       Use joystick y as virtual joystick x.\n\
+-sound x        Sound.\n\
+                 0 = Disabled.\n\
+                 Otherwise, x = playback rate.\n\
+"
+#ifdef DSPSOUND
+"-f8bit x        Force 8-bit sound.\n\
+                 0 = Disabled.\n\
+                 1 = Enabled.\n\
+"
+#else
+"-lbufsize x   Internal FCE Ultra sound buffer size. Size = 2^x samples.\n\
+-ebufsize x    External SDL sound buffer size. Size = 2^x samples.\n\
+"
+#endif
+"-connect s      Connect to server 's' for TCP/IP network play.\n\
+-server         Be a host/server for TCP/IP network play.\n\
+-netport x      Use TCP/IP port x for network play.";
+
+//static int docheckie[2]={0,0};
+ARGPSTRUCT DriverArgs[]={
+         {"-joy1",0,&joy[0],0},{"-joy2",0,&joy[1],0},
+         {"-joy3",0,&joy[2],0},{"-joy4",0,&joy[3],0},
+        {"-xscale",0,&_xscale,0},
+        {"-yscale",0,&_yscale,0},
+        {"-efx",0,&_efx,0},
+         {"-xscalefs",0,&_xscalefs,0},
+         {"-yscalefs",0,&_yscalefs,0},
+         {"-efxfs",0,&_efxfs,0},
+        {"-xres",0,&_xres,0},
+         {"-yres",0,&_yres,0},
+         {"-fs",0,&_fullscreen,0},
+         //{"-fshack",0,&_fshack,0x4001},
+         {"-sound",0,&_sound,0},
+        #ifdef DSPSOUND
+         {"-f8bit",0,&_f8bit,0},
+        #else
+        {"-lbufsize",0,&_lbufsize,0},
+        {"-ebufsize",0,&_ebufsize,0},
+        #endif
+        #ifdef NETWORK
+         {"-connect",&docheckie[0],&netplayhost,0x4001},
+         {"-server",&docheckie[1],0,0},
+         {"-netport",0,&Port,0},
+        #endif
+         {0,0,0,0}
+};
+
+static void SetDefaults(void)
+{
+ _xres=320;
+ _yres=240;
+ _fullscreen=0;
+ _sound=48000;
+ #ifdef DSPSOUND
+ _f8bit=0;
+ #else
+ _lbufsize=10;
+ _ebufsize=8;
+ #endif
+ _xscale=_yscale=_xscalefs=_yscalefs=1;
+ _efx=_efxfs=0;
+ //_fshack=_fshacksave=0;
+ memset(joy,0,sizeof(joy));
+}
+
+void DoDriverArgs(void)
+{
+        int x;
+
+       #ifdef BROKEN
+        if(_fshack)
+        {
+         if(_fshack[0]=='0')
+          if(_fshack[1]==0)
+          {
+           free(_fshack);
+           _fshack=0;
+          }
+        }
+       #endif
+
+       #ifdef NETWORK
+        if(docheckie[0])
+         netplay=2;
+        else if(docheckie[1])
+         netplay=1;
+
+        if(netplay)
+         FCEUI_SetNetworkPlay(netplay);
+       #endif
+
+        for(x=0;x<4;x++)
+         if(!joy[x])
+        {
+         memset(joyBMap[x],0,sizeof(joyBMap[0]));
+         memset(joyAMap[x],0,sizeof(joyAMap[0]));
+        }
+}
+int InitMouse(void)
+{
+ return(0);
+}
+void KillMouse(void){}
+void GetMouseData(uint32 *d)
+{
+ int x,y;
+ uint32 t;
+
+ t=SDL_GetMouseState(&x,&y);
+ 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)
+{
+
+}
+
+char *GetKeyboard(void)
+{
+ SDL_PumpEvents();
+ return (char *)SDL_GetKeyState(0);
+}
+#include "unix-basedir.h"
+
+int CLImain(int argc, char *argv[]);
+int main(int argc, char *argv[])
+{
+        puts("\nStarting FCE Ultra "VERSION_STRING"...\n");
+       if(SDL_Init(0))
+       {
+        printf("Could not initialize SDL: %s.\n", SDL_GetError());
+        return(-1);
+       }
+       SetDefaults();
+
+       #ifdef BROKEN
+        if(getenv("SDL_VIDEODRIVER"))
+       {
+        if((_fshacksave=malloc(strlen(getenv("SDL_VIDEODRIVER"))+1)))
+         strcpy(_fshacksave,getenv("SDL_VIDEODRIVER"));
+       }
+        else
+         _fshacksave=0;
+       #endif
+
+       {
+        int ret=CLImain(argc,argv);
+        SDL_Quit();
+        return(ret);
+       }
+}
+
diff --git a/drivers/cli/sdl.h b/drivers/cli/sdl.h
new file mode 100644 (file)
index 0000000..a235951
--- /dev/null
@@ -0,0 +1,47 @@
+#include <SDL.h>
+#include "../../driver.h"
+#include "../common/args.h"
+#include "../common/config.h"
+#include "main.h"
+
+typedef struct {
+        int xres;
+        int yres;
+       int xscale,yscale;
+       int xscalefs,yscalefs;
+       int efx,efxfs;
+        int fullscreen;
+       int sound;
+       #ifdef DSPSOUND
+       int f8bit;
+       #else
+       int lbufsize,ebufsize;
+       #endif
+       int joy[4];
+       int joyAMap[4][2];
+       int joyBMap[4][4];
+       char *fshack;
+       char *fshacksave;
+} DSETTINGS;
+
+extern DSETTINGS Settings;
+
+#define _xres Settings.xres
+#define _yres Settings.yres
+#define _fullscreen Settings.fullscreen
+#define _sound Settings.sound
+#define _f8bit Settings.f8bit
+#define _xscale Settings.xscale
+#define _yscale Settings.yscale
+#define _xscalefs Settings.xscalefs
+#define _yscalefs Settings.yscalefs
+#define _efx Settings.efx
+#define _efxfs Settings.efxfs
+#define _ebufsize Settings.ebufsize
+#define _lbufsize Settings.lbufsize
+#define _fshack Settings.fshack
+#define _fshacksave Settings.fshacksave
+
+#define joyAMap Settings.joyAMap
+#define joyBMap Settings.joyBMap
+#define joy    Settings.joy
diff --git a/drivers/cli/svga-video.c b/drivers/cli/svga-video.c
new file mode 100644 (file)
index 0000000..67f4ecb
--- /dev/null
@@ -0,0 +1,497 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 1998 \Firebug\
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <vga.h>
+#include <sys/io.h>
+
+#define inportb inb
+#define outportb(port, value) outb(value, port)
+#define outportw(port, value) outw(value, port)
+
+#include "main.h"
+#include "svgalib.h"
+#include "svga-video.h"
+
+
+int vmode=1;
+
+#ifdef FRAMESKIP
+int FCEUDfskip=0;
+#endif
+
+static int vidready=0;
+static int conlock=0;
+
+void LockConsole(void)
+{
+ if(!conlock)
+ {
+  vga_lockvc();
+  conlock=1;
+  FCEUI_DispMessage("Console locked.");
+ }
+}
+
+void UnlockConsole(void)
+{
+ if(conlock)
+ {
+  vga_unlockvc();
+  conlock=0;
+  FCEUI_DispMessage("Console unlocked.");
+ }
+}
+
+void SetBorder(void)
+{
+ if(!conlock) 
+  vga_lockvc();
+ inportb(0x3da);
+ outportb(0x3c0,(0x11|0x20));
+ outportb(0x3c0,0x80);
+ if(!conlock) 
+  vga_unlockvc();
+}
+
+#include "vgatweak.c"
+
+void TweakVGA(int VGAMode)
+{
+  int I;
+
+  if(!conlock)
+   vga_lockvc();
+
+  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);
+  if(!conlock) 
+   vga_unlockvc();
+}
+
+
+static uint8 palettedbr[256],palettedbg[256],palettedbb[256];
+
+static void FlushPalette(void)
+{
+ int x;
+ for(x=0;x<256;x++)
+ {
+  int z=x;
+  if(vmode==4 || vmode==5 || vmode==7) z^=0x80;
+  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)
+  {
+   if(vmode==4 || vmode==5 || vmode==7) index^=0x80;
+   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 void vcfix(void)
+{
+ int z;
+
+ if(!conlock)
+  vga_lockvc();
+ z=inportb(0x3cc);
+ if(!conlock) 
+  vga_unlockvc();
+ if(z!=0xe3 && z!=0xe7)                // Common value in all tweaked video modes(and not in 320x200 mode).
+ {
+  TweakVGA(vmode);
+  SetBorder();
+  FlushPalette();
+ }
+}
+
+static uint8 *ScreenLoc;
+
+int InitVideo(void)
+{
+ #ifdef DUMMY
+ return(1);
+ #endif
+ vidready=0;
+
+ if(vmode<=3 || vmode==6 || vmode==8)
+ {
+  if(vga_getcurrentchipset()==FBDEV)
+  {
+   puts("Tweaked VGA video modes will not work.  Using a 320x240 video mode instead...");
+   vmode=7;
+  }
+ }
+
+ switch(vmode)
+ {
+  default:
+  case 1:
+  case 2:
+  case 3:
+  case 6:
+  case 8:
+        vga_setmode(G320x200x256);
+        vidready|=1;
+         ScreenLoc=vga_getgraphmem();
+         TweakVGA(vmode);
+         SetBorder();
+         memset(ScreenLoc,128,256*256);
+         break;
+  case 4:
+  case 5:
+         if(!(vga_getmodeinfo(G640x480x256)->flags & CAPABLE_LINEAR))
+         {
+          puts("Video:  No linear addressing mode available!");
+          return 0;
+         }
+         if(vga_setmode(G640x480x256)==-1)
+         {
+          puts("Video:  Could not set 640x480x8bpp video mode!");
+          return 0;
+         }
+        vidready|=1;
+
+         vga_setpage(0);
+         if(vga_setlinearaddressing()!=-1)
+          ScreenLoc=vga_getgraphmem();
+         else
+         {
+          puts("Video:  Could not set linear addressing!");
+          return 0;
+         }
+         memset(ScreenLoc,0,640*480);
+         break;
+  case 7:
+         if(!(vga_getmodeinfo(G320x240x256V)->flags & CAPABLE_LINEAR))
+         {
+          puts("Video:  No linear addressing mode available!");
+          return 0;
+         }
+         if(vga_setmode(G320x240x256V)==-1)
+         {
+          puts("Video:  Could not set 320x240x8bpp video mode!");
+          return 0;
+         }
+         vidready|=1;
+
+         vga_setpage(0);
+         if(vga_setlinearaddressing()!=-1)
+          ScreenLoc=vga_getgraphmem();
+         else
+         {
+          puts("Video:  Could not set linear addressing!");
+          return 0;
+         }
+         memset(ScreenLoc,0,320*240);
+         break;
+ }
+ vidready|=2;
+ FlushPalette(); // Needed for cheat console code(and it isn't a bad thing to do anyway...).
+ return 1;
+}
+
+void KillVideo(void)
+{
+ if(vidready)
+ {
+  vga_setmode(TEXT);
+  vidready=0;
+ }
+}
+
+
+void BlitScreen(uint8 *XBuf)
+{
+ static int conto=0;
+ uint8 *dest;
+ int tlines;
+ #ifdef DUMMY
+ return;
+ #endif
+ #ifdef FRAMESKIP
+ FCEUI_FrameSkip(FCEUDfskip);
+ #endif
+
+ if(doptions&DO_VSYNC && !NoWaiting)
+ {
+  vga_waitretrace();
+ }
+
+ tlines=erendline-srendline+1;
+
+ dest=ScreenLoc;
+
+ if(vmode!=4 && vmode!=5 && vmode!=7)
+ {
+  conto=(conto+1)&0x3F;
+  if(!conto) vcfix();
+ }
+ switch(vmode)
+ {
+  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;
+  case 7:dest+=(((240-tlines)>>1)*320)+32;break;
+ }
+
+ XBuf+=(srendline<<8)+(srendline<<4);
+
+ if(eoptions&EO_CLIPSIDES)
+ {
+  if(vmode==5)
+  {
+   asm volatile(
+     "xorl %%edx, %%edx\n\t"
+     "ckoop1:\n\t"
+     "movb $120,%%al     \n\t"
+     "ckoop2:\n\t"
+     "movb 1(%%esi),%%dl\n\t"
+     "shl  $16,%%edx\n\t"
+     "movb (%%esi),%%dl\n\t"
+     "xorl $0x00800080,%%edx\n\t"
+     "movl %%edx,(%%edi)\n\t"
+     "addl $2,%%esi\n\t"
+     "addl $4,%%edi\n\t"
+     "decb %%al\n\t"
+     "jne ckoop2\n\t"
+
+     "addl $32,%%esi\n\t"
+     "addl $800,%%edi\n\t"
+     "decb %%bl\n\t"
+     "jne ckoop1\n\t"
+     :
+     : "S" (XBuf+8), "D" (dest+8), "b" (tlines)
+     : "%al", "%edx", "%cc" );
+  }
+  else if(vmode==4)
+  {
+   asm volatile(
+     "cyoop1:\n\t"
+     "movb $120,%%al     \n\t"
+     "cyoop2:\n\t"
+     "movb 1(%%esi),%%dh\n\t"
+     "movb %%dh,%%dl\n\t"
+     "shl  $16,%%edx\n\t"
+     "movb (%%esi),%%dl\n\t"
+     "movb %%dl,%%dh\n\t"               // Ugh
+     "xorl $0x80808080,%%edx\n\t"
+     "movl %%edx,(%%edi)\n\t"
+     "addl $2,%%esi\n\t"
+     "addl $4,%%edi\n\t"
+     "decb %%al\n\t"
+     "jne cyoop2\n\t"
+
+     "addl $32,%%esi\n\t"
+     "addl $800,%%edi\n\t"
+     "decb %%bl\n\t"
+     "jne cyoop1\n\t"
+     :
+     : "S" (XBuf+8), "D" (dest+8), "b" (tlines)
+     : "%al", "%edx", "%cc" );
+  }
+  else if(vmode==7)
+  {
+   asm volatile(
+     "cgoop81:\n\t"
+     "movl $30,%%eax\n\t"
+     "cgoop82:\n\t"
+     "movl (%%esi),%%edx\n\t"
+     "movl 4(%%esi),%%ecx\n\t"
+     "xorl $0x80808080,%%edx\n\t"
+     "xorl $0x80808080,%%ecx\n\t"
+     "movl %%edx,(%%edi)\n\t"
+     "movl %%ecx,4(%%edi)\n\t"
+     "addl $8,%%esi\n\t"
+     "addl $8,%%edi\n\t"
+     "decl %%eax\n\t"
+     "jne cgoop82\n\t"
+     "addl $80,%%edi\n\t"
+     "addl $32,%%esi\n\t"
+     "decb %%bl\n\t"
+     "jne cgoop81\n\t"
+     :
+     : "S" (XBuf+8), "D" (dest+8), "b" (tlines)
+     : "%eax","%cc","%edx","%ecx" );
+  }
+  else
+  {
+   asm volatile(
+     "cgoop1:\n\t"
+     "movl $30,%%eax\n\t"
+     "cgoop2:\n\t"
+     "movl (%%esi),%%edx\n\t"
+     "movl 4(%%esi),%%ecx\n\t"
+     "movl %%edx,(%%edi)\n\t"
+     "movl %%ecx,4(%%edi)\n\t"
+     "addl $8,%%esi\n\t"
+     "addl $8,%%edi\n\t"
+     "decl %%eax\n\t"
+     "jne cgoop2\n\t"
+     "addl $32,%%esi\n\t"
+     "addl $16,%%edi\n\t"
+     "decb %%bl\n\t"
+     "jne cgoop1\n\t"
+     :
+     : "S" (XBuf+8), "D" (dest+8), "b" (tlines)
+     : "%eax","%cc","%edx","%ecx" );
+  }
+ }
+ else
+ {
+  if(vmode==5)
+  {
+   asm volatile(
+     "xorl %%edx, %%edx\n\t"
+     "koop1:\n\t"
+     "movb $128,%%al     \n\t"
+     "koop2:\n\t"
+     "movb 1(%%esi),%%dl\n\t"
+     "shl  $16,%%edx\n\t"
+     "movb (%%esi),%%dl\n\t"
+     "xorl $0x00800080,%%edx\n\t"
+     "movl %%edx,(%%edi)\n\t"
+     "addl $2,%%esi\n\t"
+     "addl $4,%%edi\n\t"
+     "decb %%al\n\t"
+     "jne koop2\n\t"
+
+     "addl $16,%%esi\n\t"
+     "addl $768,%%edi\n\t"
+     "decb %%bl\n\t"
+     "jne koop1\n\t"
+     :
+     : "S" (XBuf), "D" (dest), "b" (tlines)
+     : "%al", "%edx", "%cc" );
+  }
+  else if(vmode==4)
+  {
+   asm volatile(
+     "yoop1:\n\t"
+     "movb $128,%%al     \n\t"
+     "yoop2:\n\t"
+     "movb 1(%%esi),%%dh\n\t"
+     "movb %%dh,%%dl\n\t"
+     "shl  $16,%%edx\n\t"
+     "movb (%%esi),%%dl\n\t"
+     "movb %%dl,%%dh\n\t"               // Ugh
+     "xorl $0x80808080,%%edx\n\t"
+     "movl %%edx,(%%edi)\n\t"
+     "addl $2,%%esi\n\t"
+     "addl $4,%%edi\n\t"
+     "decb %%al\n\t"
+     "jne yoop2\n\t"
+
+     "addl $16,%%esi\n\t"
+     "addl $768,%%edi\n\t"
+     "decb %%bl\n\t"
+     "jne yoop1\n\t"
+     :
+     : "S" (XBuf), "D" (dest), "b" (tlines)
+     : "%al", "%edx", "%cc" );
+  }
+  else if(vmode==7)
+  {
+   asm volatile(
+     "goop81:\n\t"
+     "movl $32,%%eax\n\t"
+     "goop82:\n\t"
+     "movl (%%esi),%%edx\n\t"
+     "movl 4(%%esi),%%ecx\n\t"
+     "xorl $0x80808080,%%edx\n\t"
+     "xorl $0x80808080,%%ecx\n\t"
+     "movl %%edx,(%%edi)\n\t"
+     "movl %%ecx,4(%%edi)\n\t"
+     "addl $8,%%esi\n\t"
+     "addl $8,%%edi\n\t"
+     "decl %%eax\n\t"
+     "jne goop82\n\t"
+     "addl $64,%%edi\n\t"
+     "addl $16,%%esi\n\t"
+     "decb %%bl\n\t"
+     "jne goop81\n\t"
+     :
+     : "S" (XBuf), "D" (dest), "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"
+     "movl %%edx,(%%edi)\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/cli/svga-video.h b/drivers/cli/svga-video.h
new file mode 100644 (file)
index 0000000..e0a991b
--- /dev/null
@@ -0,0 +1,32 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+extern int vmode;
+
+#ifdef FRAMESKIP
+extern int FCEUDfskip;
+#endif
+
+void LockConsole(void);
+void UnlockConsole(void);
+int InitVideo(void);
+void KillVideo(void);
+void FCEUD_BlitScreen(uint8 *XBuf);
+
diff --git a/drivers/cli/svgalib.c b/drivers/cli/svgalib.c
new file mode 100644 (file)
index 0000000..7d293e9
--- /dev/null
@@ -0,0 +1,178 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vga.h>
+#include <vgamouse.h>
+#include <vgakeyboard.h>
+
+#include "../../driver.h"
+#include "../common/args.h"
+#include "../common/config.h"
+#include "../common/unixdsp.h"
+
+#include "svgalib.h"
+#include "svga-video.h"
+#include "lnx-joystick.h"
+#include "unix-netplay.h"
+
+static int soundo=48000;
+static int f8bit=0;
+static int sfragsize=7,snfrags=8;
+
+int doptions=0;
+
+CFGSTRUCT DriverConfig[]={
+        NAC("sound",soundo),
+       AC(doptions),
+        AC(f8bit),
+        AC(vmode),
+        NACA("joybmap",joyBMap),
+        ACA(joy),
+        AC(snfrags),
+        AC(sfragsize),
+       ENDCFGSTRUCT
+};
+
+
+char *DriverUsage=
+"-vmode x        Select video mode(all are 8 bpp).\n\
+                 1 = 256x240                 5 = 640x480(\"1 per 4\")\n\
+                 2 = 256x256                 6 = 256x224(with scanlines)\n\
+                 3 = 256x256(with scanlines) 7 = 320x240\n\
+                 4 = 640x480(with scanlines) 8 = 256x224\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\
+-joyx y         Joystick mapped to virtual joystick x(1-4).\n\
+                 0 = Disabled, reset configuration.\n\
+                 Otherwise, y(1-inf) = joystick number.\n\
+-sound x        Sound.\n\
+                 0 = Disabled.\n\
+                 Otherwise, x = playback rate.\n\
+-sfragsize x    Set sound fragment size to 2^x samples.\n\
+-snfrags x      Set number of sound fragments to x.\n\
+-f8bit x        Force 8-bit sound.\n\
+                 0 = Disabled.\n\
+                 1 = Enabled.\n\
+-connect s      Connect to server 's' for TCP/IP network play.\n\
+-server         Be a host/server for TCP/IP network play.\n\
+-netport x      Use TCP/IP port x for network play.";
+
+
+static int docheckie[2]={0,0};
+ARGPSTRUCT DriverArgs[]={
+         {"-joy1",0,&joy[0],0},{"-joy2",0,&joy[1],0},
+         {"-joy3",0,&joy[2],0},{"-joy4",0,&joy[3],0},
+         {"-snfrags",0,&snfrags,0},{"-sfragsize",0,&sfragsize,0},
+        {"-vmode",0,&vmode,0},
+         {"-vsync",0,&doptions,0x8000|DO_VSYNC},
+        {"-sound",0,&soundo,0},
+         {"-f8bit",0,&f8bit,0},
+         {"-connect",&docheckie[0],&netplayhost,0x4001},
+         {"-server",&docheckie[1],0,0},
+         {"-netport",0,&Port,0},
+        {0,0,0,0}
+};
+
+void DoDriverArgs(void)
+{
+       int x;
+
+        if(docheckie[0])
+         netplay=2;
+        else if(docheckie[1])
+         netplay=1;
+
+        if(netplay)
+         FCEUI_SetNetworkPlay(netplay);
+
+        for(x=0;x<4;x++)
+         if(!joy[x]) memset(joyBMap[x],0,4*sizeof(int));
+}
+
+int InitSound(void)
+{
+        if(soundo)
+        {
+         int rate;
+         if(soundo==1)
+          soundo=48000;
+         rate=soundo;
+         if(InitUNIXDSPSound(&rate,f8bit?0:1,sfragsize,snfrags))
+        {
+         FCEUI_Sound(rate);
+         return(1);
+        }
+        }
+       return(0);
+}
+
+void WriteSound(int32 *Buffer, int Count, int NoWaiting)
+{
+       WriteUNIXDSPSound(Buffer,Count,NoWaiting);
+}
+
+void KillSound(void)
+{
+       KillUNIXDSPSound();
+}
+
+int InitMouse(void)
+{
+    vga_setmousesupport(1);
+    mouse_setxrange(0,260);
+    mouse_setyrange(0,260);
+    mouse_setscale(1);
+    return(1);
+}
+
+void KillMouse(void)
+{
+ mouse_close();
+}
+
+void GetMouseData(uint32 *MouseData)
+{
+ int z;
+ mouse_update();
+ MouseData[0]=mouse_getx();
+ MouseData[1]=mouse_gety();
+ z=mouse_getbutton();
+ MouseData[2]=((z&MOUSE_LEFTBUTTON)?1:0)|((z&MOUSE_RIGHTBUTTON)?2:0);
+}
+
+#include "unix-basedir.h"
+
+int InitKeyboard(void)
+{
+  if(keyboard_init()==-1)
+  {
+   puts("Error initializing keyboard.");
+   return 0;
+  }
+  keyboard_translatekeys(TRANSLATE_CURSORKEYS | TRANSLATE_DIAGONAL);
+  return 1;
+}
+
+int UpdateKeyboard(void)
+{
+ return(keyboard_update());
+}
+
+char *GetKeyboard(void)
+{
+ return(keyboard_getstate());
+}
+
+void KillKeyboard(void)
+{
+ keyboard_close();
+}
+
+int main(int argc, char *argv[])
+{
+        puts("\nStarting FCE Ultra "VERSION_STRING"...\n");
+        vga_init();
+       return(CLImain(argc,argv));
+}
diff --git a/drivers/cli/svgalib.h b/drivers/cli/svgalib.h
new file mode 100644 (file)
index 0000000..8f18b74
--- /dev/null
@@ -0,0 +1,2 @@
+#define DO_VSYNC        1
+extern int doptions;
diff --git a/drivers/cli/throttle.c b/drivers/cli/throttle.c
new file mode 100644 (file)
index 0000000..33941bb
--- /dev/null
@@ -0,0 +1,45 @@
+#include <sys/time.h>
+#include <unistd.h>
+#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;
+
+ waiter:
+
+ ttime=GetCurTime();
+
+ if( (ttime-ltime) < (tfreq/desiredfps) )
+ {
+  usleep(1000);
+  goto waiter;
+ }
+ if( (ttime-ltime) >= (tfreq*4/desiredfps))
+  ltime=ttime;
+ else
+  ltime+=tfreq/desiredfps;
+}
+
diff --git a/drivers/cli/throttle.h b/drivers/cli/throttle.h
new file mode 100644 (file)
index 0000000..0b0ad9f
--- /dev/null
@@ -0,0 +1,2 @@
+void RefreshThrottleFPS(void);
+void SpeedThrottle(void);
diff --git a/drivers/cli/unix-basedir.h b/drivers/cli/unix-basedir.h
new file mode 100644 (file)
index 0000000..4f6808c
--- /dev/null
@@ -0,0 +1,15 @@
+#include <stdlib.h>
+void GetBaseDirectory(char *BaseDirectory)
+{
+ char *ol;
+
+ ol=getenv("HOME");
+ BaseDirectory[0]=0;
+ if(ol)
+ {
+  strncpy(BaseDirectory,ol,2047);
+  BaseDirectory[2047]=0;
+  strcat(BaseDirectory,"/.fceultra");
+ }
+}
+
diff --git a/drivers/cli/unix-netplay.c b/drivers/cli/unix-netplay.c
new file mode 100644 (file)
index 0000000..747fa00
--- /dev/null
@@ -0,0 +1,159 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <errno.h>
+
+#ifndef socklen_t
+#define socklen_t int
+#endif
+
+static int Socket=-1;
+#include "main.h"
+#include "unix-netplay.h"
+
+char *netplayhost=0;
+int Port=0xFCE;
+int netplay=0;
+
+int FCEUD_NetworkConnect(void)
+{
+ struct sockaddr_in sockn;
+ int TSocket;
+
+ memset(&sockn,0,sizeof(sockn));
+ sockn.sin_family=AF_INET;
+ sockn.sin_port=htons(Port);
+
+ if((TSocket=socket(AF_INET, SOCK_STREAM, 0))<0)
+ {
+  puts("Error creating socket.");
+  return(0);
+ }
+
+ if(netplay==1)                /* Be a server. */
+ {
+  sockn.sin_addr.s_addr=INADDR_ANY;
+  if(bind(TSocket, (struct sockaddr *)&sockn, sizeof(sockn))<0)
+  {
+   close(TSocket);
+   puts("Error binding to socket.");
+   return(0);
+  }
+  if(listen(TSocket, 1)<0)
+  {
+   puts("Error listening on socket.");
+   close(TSocket);
+   return(0);
+  }
+  {
+   socklen_t len=sizeof(sockn);
+
+   printf("Accepting connection on port %d...\n",Port);
+   if((Socket=accept(TSocket,(struct sockaddr *)&sockn,&len))<0 )
+   {
+    puts("Error accepting a connection.");
+    close(TSocket);
+    return(0);
+   }
+   close(TSocket);
+  }
+
+ }
+ else /* Connect as a client if not a server. */
+ {
+  struct hostent *Host;
+
+  if((sockn.sin_addr.s_addr=inet_addr(netplayhost))==INADDR_NONE)
+  {
+   if(!(Host=gethostbyname(netplayhost)))
+   {
+    puts("Error getting network host entry.");
+    return(0);
+   }
+   memcpy(&sockn.sin_addr,Host->h_addr,Host->h_length);
+  }
+  printf("Attempting to connect to %s...\n",netplayhost);
+  if( connect(TSocket, (struct sockaddr *)&sockn, sizeof(sockn)) <0 )
+  {
+   puts("Error connecting to remote host.");
+   close(TSocket);
+   return(0);
+  }
+  Socket=TSocket;
+ }
+ return(1);
+}
+
+/* 0 on failure, 1 on success, -1 if it would block and blocking is not
+   specified.
+*/
+
+int FCEUD_NetworkRecvData(uint8 *data, uint32 len, int block)
+{
+  if(block)
+  {
+   int t;
+   uint8 temp[32];
+   t=recv(Socket,temp,32,MSG_PEEK|MSG_DONTWAIT);
+   if(t==-1)
+   {
+    if(errno!=EAGAIN) return(0);
+   }
+   else if(t==32)
+    NoWaiting|=2;
+   else
+    NoWaiting&=~2;
+   return(recv(Socket,data,len,0)==len);
+  }
+  else
+  {
+   int t=recv(Socket,data,len,MSG_DONTWAIT);
+   if(t==-1)
+   {
+    if(errno==EAGAIN)   // Would block
+     return(-1);
+    return(0);
+   }
+   return(1);
+  }
+}
+
+/* 0 on failure, 1 on success.  This function should always block. */
+
+int FCEUD_NetworkSendData(uint8 *Value, uint32 len)
+{
+ return(send(Socket,Value,len,0)==len);
+}
+
+void FCEUD_NetworkClose(void)
+{
+ if(Socket>0)
+  close(Socket);
+ Socket=-1;
+}
+
diff --git a/drivers/cli/unix-netplay.h b/drivers/cli/unix-netplay.h
new file mode 100644 (file)
index 0000000..48769f6
--- /dev/null
@@ -0,0 +1,5 @@
+extern char *netplayhost;
+extern int Port;
+extern int FDnetplay;
+#define netplay FDnetplay
+
diff --git a/drivers/cli/usage.h b/drivers/cli/usage.h
new file mode 100644 (file)
index 0000000..425a907
--- /dev/null
@@ -0,0 +1,56 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Ben Parnell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+void ShowUsage(char *prog)
+{
+printf("\nUsage is as follows:\n%s <options> filename\n\n",prog);
+puts("Options:");
+puts(DriverUsage);
+puts("-cpalette x     Load a custom global palette from file x.\n\
+-ntsccol x      Emulate an NTSC's TV's colors.\n\
+                 0 = Disabled.\n\
+                 1 = Enabled.\n\
+-pal            Emulate a PAL NES.\n\
+-soundvol x    Sound volume. x is an integral percentage value.\n\
+-inputx str    Select device mapped to virtual input port x(1-2).\n\
+                str may be: none, gamepad, zapper, powerpada, powerpadb,\n\
+                            arkanoid\n\
+-fcexp str     Select Famicom expansion port device.\n\
+                str may be: none, shadow, arkanoid, 4player, fkb\n\
+-nofs x                Disables Four-Score emulation if x is 1.\n\
+-gg             Enable Game Genie emulation.\n\
+-no8lim x       Disables the 8 sprites per scanline limitation.\n\
+                 0 = Limitation enabled.\n\
+                 1 = Limitation disabled.\n\
+-subase x       Save extra game data files under the base directory if enabled.\n\
+                 0 = Disabled.\n\
+                1 = Enabled.\n\
+-snapname x    Selects what type of file name snapshots will have.\n\
+                0 = Numeric(0.png)\n\
+                1 = File base and numeric(mario-0.png)\n\
+-nothrottle x  Disable artificial speed throttling if x is non-zero.\n\
+-clipsides x   Clip leftmost and rightmost 8 columns of pixels of video output.\n\
+                 0 = No clipping.\n\
+                 1 = Clipping.\n\
+-slstart x     Set the first drawn emulated scanline.  Valid values for x are\n\
+               0 through 239.\n\
+-slend x       Set the last drawn emulated scanline.  Valid values for x are\n\
+               0 through 239.");
+}
diff --git a/drivers/cli/vgatweak.c b/drivers/cli/vgatweak.c
new file mode 100644 (file)
index 0000000..a04cf94
--- /dev/null
@@ -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;
+  }
+}
+