gpfce patch part3
[fceu.git] / drivers / pc / svga-video.c
diff --git a/drivers/pc/svga-video.c b/drivers/pc/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" );
+  }
+ }
+}
+
+