--- unix/x11.cpp.orig	Fri Oct  6 17:02:40 2000
+++ unix/x11.cpp	Tue Nov 21 21:58:20 2000
@@ -136,7 +136,7 @@
 static XColor colors [256];
 static bool8 pseudo = TRUE;
 static bool8 grayscale = FALSE;
-static bool8 interpolate = FALSE;
+static int interpolate = 0;	/* 0 = none, 1 = TVMode, 2 = 2xSaI */
 static bool8 ImageNeedsScaling = FALSE;
 static int depth = 8;
 static int window_width = SNES_WIDTH;
@@ -189,6 +189,7 @@
 void SetupImage ();
 int ErrorHandler (Display *, XErrorEvent *);
 void TVMode (int width, int height);
+void _2xSaIBitmap (int width, int height);
 void S9xDisplayStateChange (const char *str, bool8 on);
 
 void S9xDeinitDisplay ()
@@ -1336,7 +1337,10 @@
 	    {
 		memset (DeltaScreen, 255, GFX.Pitch * snes_height);
 	    }
-	    TVMode (snes_width, snes_height);
+	    if (interpolate == 1)	
+		TVMode (snes_width, snes_height);
+	    else
+		_2xSaIBitmap (snes_width, snes_height);
 	    width = 512;
 	    if (snes_height < 240)
 		height = snes_height << 1;
@@ -2196,7 +2200,15 @@
 	Settings.SixteenBit = TRUE;
         Settings.SupportHiRes = TRUE;
         Settings.ForceTransparency = TRUE;
-        interpolate = TRUE;
+        interpolate = 1;
+    }
+    else
+    if (strcasecmp (argv [ind], "-2xsai") == 0)
+    {
+	Settings.SixteenBit = TRUE;
+        Settings.SupportHiRes = TRUE;
+        Settings.ForceTransparency = TRUE;
+        interpolate = 2;
     }
 #ifdef USE_DGA_EXTENSION
     else
@@ -2373,6 +2385,318 @@
 	while (--height);
     }
 }
+
+/*---------------------------------------------------------------------*
+ * The following (piece of) code, (part of) the 2xSaI engine,          *
+ * copyright (c) 1999 by Derek Liauw Kie Fa.                           *
+ * Non-Commercial use of the engine is allowed and is encouraged,      *
+ * provided that appropriate credit be given and that this copyright   *
+ * notice will not be removed under any circumstance.                  *
+ * You may freely modify this code, but I request                      *
+ * that any improvements to the engine be submitted to me, so          *
+ * that I can implement these improvements in newer versions of        *
+ * the engine.                                                         *
+ * If you need more information, have any comments or suggestions,     *
+ * you can e-mail me. My e-mail: derek-liauw@usa.net.                  *
+ *---------------------------------------------------------------------*/
+
+/*---------------------*/
+/* 2xSaI, version 0.50 */
+/*---------------------*/
+
+inline int GetResult1(uint32 A, uint32 B, uint32 C, uint32 D, uint32 E)
+{
+ int x = 0; 
+ int y = 0;
+ int r = 0;
+ if (A == C) x+=1; else if (B == C) y+=1;
+ if (A == D) x+=1; else if (B == D) y+=1;
+ if (x <= 1) r+=1; 
+ if (y <= 1) r-=1;
+ return r;
+}
+
+inline int GetResult2(uint32 A, uint32 B, uint32 C, uint32 D, uint32 E) 
+{
+ int x = 0; 
+ int y = 0;
+ int r = 0;
+ if (A == C) x+=1; else if (B == C) y+=1;
+ if (A == D) x+=1; else if (B == D) y+=1;
+ if (x <= 1) r-=1; 
+ if (y <= 1) r+=1;
+ return r;
+}
+
+inline uint32 RowSharpen (uint32 A, uint32 B, uint32 C)
+{
+   if (B != C || A != C)
+   {
+        register int32 GREEN_MASK = 0x07E007E0;
+        register int32 x =  (B & GREEN_MASK) >> 5;
+        register int32 y = ((A & GREEN_MASK) +
+                            (C & GREEN_MASK) >> 7);
+        x = x + (x>>1) - (y);
+        if (x < 0) x = 0;
+        else if (x > 63) x = 63;
+        GREEN_MASK = ~GREEN_MASK;
+        return ((B & GREEN_MASK) | (x << 5));
+   }
+   else return B;
+}
+
+inline uint32 INTERPOLATE(uint32 A, uint32 B)
+{
+    if (A !=B)
+    {
+       register uint32 colorMask = 0xF7DEF7DE;
+       register uint32 lowPixelMask = 0x08210821;
+       return ( ((A & colorMask) >> 1) + ((B & colorMask) >> 1) + (A & B & lowPixelMask) );
+    }
+    else return A;
+}
+
+
+inline uint32 Q_INTERPOLATE(uint32 A, uint32 B, uint32 C, uint32 D)
+{
+        register uint32 qcolorMask = 0xE79CE79C;
+        register uint32 qlowpixelMask = 0x18631863;
+        register uint32 x = ((A & qcolorMask) >> 2) +
+                            ((B & qcolorMask) >> 2) +
+                            ((C & qcolorMask) >> 2) +
+                            ((D & qcolorMask) >> 2);
+        register uint32 y = (A & qlowpixelMask) +
+                            (B & qlowpixelMask) +
+                            (C & qlowpixelMask) +
+                            (D & qlowpixelMask);
+        y = (y>>2) & qlowpixelMask;
+        return x+y;
+}
+
+#ifdef MMX
+EXTERN_C void __2xSaILine (uint8 *srcPtr, uint32 srcPitch, uint32 width,
+                        uint8* dstPtr, uint32 dstPitch);
+EXTERN_C void __2xSaISuperEagleLine (uint8 *srcPtr, uint32 srcPitch,
+			uint32 width, uint8* dstPtr, uint32 dstPitch);
+int mmx_cpu;
+#endif
+
+void _2xSaIBitmap(int width, int height)
+{
+    uint8 *srcPtr, *dstPtr;
+    //srcPtr = pointer to the beginning of the source bitmap
+    //dstPtr = pointer to the beginning of the destination bitmap
+    uint32 dstPitch = OutputPitch;
+    uint32 *dP;     //pointer to the pixels we are writing
+    uint16 *bP;     //pointer to the pixels we are reading
+
+    srcPtr = GFX.Screen;                //How many bytes to the next line (width * bytes per pixel)?
+    dstPtr = OutputScreen;              //how many bytes to the next line?
+
+#ifdef MMX
+    if (mmx_cpu)
+    {
+	for (height; height; height-=1)
+	{
+
+	    bP = (uint16 *) srcPtr;
+	    dP = (uint32 *) dstPtr;
+            __2xSaILine  ((uint8 *) bP, GFX.Pitch, width, (uint8 *) dP, dstPitch);
+            dstPtr += 2*dstPitch; //2 lines further
+	    srcPtr += GFX.Pitch;
+        }
+    }
+    else
+    {
+#endif
+
+        uint32 Nextline = GFX.Pitch >> 1; //2 bytes per pixel
+#ifdef SHARPEN
+        uint32 TempColor = 0;
+        uint32 Sharpened = 0;
+#endif
+        dstPitch >>= 2; //not really the pitch; the amount of pixels, per line
+                        //pitch / bytes per pixel. 4, not 2, cuz we're writing 2 pixels at the time
+
+        for (height; height; height-=1)
+	{
+	    bP = (uint16 *) srcPtr;
+	    dP = (uint32 *) dstPtr;
+            for (uint32 finish = width; finish; finish -= 1 )
+            {
+
+                register uint32 colorA, colorB;
+                uint32 colorC, colorD,
+                       colorE, colorF, colorG, colorH,
+                       colorI, colorJ, colorK, colorL,
+                       colorM, colorN, colorO, colorP;
+                uint32 product, product1, product2;
+
+
+//---------------------------------------
+// Map of the pixels:                    I|E F|J
+//                                       G|A B|K
+//                                       H|C D|L
+//                                       M|N O|P
+                colorI = *(bP- Nextline - 1);
+                colorE = *(bP- Nextline);
+                colorF = *(bP- Nextline + 1);
+                colorJ = *(bP- Nextline + 2);
+
+                colorG = *(bP - 1);
+                colorA = *(bP);
+                colorB = *(bP + 1);
+                colorK = *(bP + 2);
+
+                colorH = *(bP + Nextline - 1);
+                colorC = *(bP + Nextline);
+                colorD = *(bP + Nextline + 1);
+                colorL = *(bP + Nextline + 2);
+
+                colorM = *(bP + Nextline + Nextline - 1);
+                colorN = *(bP + Nextline + Nextline);
+                colorO = *(bP + Nextline + Nextline + 1);
+                colorP = *(bP + Nextline + Nextline + 2);
+
+
+                        if ((colorA == colorD) && (colorB != colorC))
+                        {
+                           if ( ((colorA == colorE) && (colorB == colorL)) ||
+                                ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ)) )
+                           {
+                              product = colorA;
+                           }
+                           else
+                           {
+                              product = INTERPOLATE(colorA, colorB);
+                           }
+
+                           if (((colorA == colorG) && (colorC == colorO)) ||
+                               ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM)) )
+                           {
+                              product1 = colorA;
+                           }
+                           else
+                           {
+                              product1 = INTERPOLATE(colorA, colorC);
+                           }
+                           product2 = colorA;
+                        }
+                        else
+                        if ((colorB == colorC) && (colorA != colorD))
+                        {
+                           if (((colorB == colorF) && (colorA == colorH)) ||
+                               ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI)) )
+                           {
+                              product = colorB;
+                           }
+                           else
+                           {
+                              product = INTERPOLATE(colorA, colorB);
+                           }
+
+                           if (((colorC == colorH) && (colorA == colorF)) ||
+                               ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI)) )
+                           {
+                              product1 = colorC;
+                           }
+                           else
+                           {
+                              product1 = INTERPOLATE(colorA, colorC);
+                           }
+                           product2 = colorB;
+                        }
+                        else
+                        if ((colorA == colorD) && (colorB == colorC))
+                        {
+                           if (colorA == colorB)
+                           {
+                              product = colorA;
+                              product1 = colorA;
+                              product2 = colorA;
+                           }
+                           else
+                           {
+                              register int r = 0;
+                              product1 = INTERPOLATE(colorA, colorC);
+                              product = INTERPOLATE(colorA, colorB);
+
+                              r += GetResult1 (colorA, colorB, colorG, colorE, colorI);
+                              r += GetResult2 (colorB, colorA, colorK, colorF, colorJ);
+                              r += GetResult2 (colorB, colorA, colorH, colorN, colorM);
+                              r += GetResult1 (colorA, colorB, colorL, colorO, colorP);
+
+                              if (r > 0)
+                                  product2 = colorA;
+                              else
+                              if (r < 0)
+                                  product2 = colorB;
+                              else
+                              {
+                                  product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD);
+                              }
+                           }
+                        }
+                        else
+                        {
+                           product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD);
+
+                           if ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ))
+                           {
+                              product = colorA;
+                           }
+                           else
+                           if ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI))
+                           {
+                              product = colorB;
+                           }
+                           else
+                           {
+                              product = INTERPOLATE(colorA, colorB);
+                           }
+
+                           if ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM))
+                           {
+                              product1 = colorA;
+                           }
+                           else
+                           if ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI))
+                           {
+                              product1 = colorC;
+                           }
+                           else
+                           {
+                              product1 = INTERPOLATE(colorA, colorC);
+                           }
+                        }
+#ifndef SHARPEN
+                        *(dP) = colorA | (product << 16);
+                        *(dP + dstPitch) = product1 | (product2 << 16);
+#else
+                        Sharpened = RowSharpen ( TempColor, colorA, product);
+                        Sharpened |= (RowSharpen ( colorA, product, colorB) << 16);
+			*(dP) = Sharpened;
+			*(dP + dstPitch) = product1| (product2 << 16);
+
+                        TempColor = product;
+#endif
+                    bP += 1;
+                    dP += 1;
+                }//end of for ( finish= width etc..)
+#ifdef SHARPEN
+            TempColor = 0;
+#endif
+
+            dstPtr += (OutputPitch << 1); //not really the pitch; the amount of pixels, per line
+            srcPtr += GFX.Pitch;
+	}; //endof: for (height; height; height--)
+#ifdef MMX
+    }
+#endif
+}
+/* End of the 2xSaI code */
+/*-----------------------------------------------------------------*/
+
 
 #ifdef __linux
 extern "C" {
