/*********************************************************************************************

              RECT.CPP
              
*********************************************************************************************/

#include "tde.h"

// _asm directive only available for W11
#define WATCOM106

#ifdef WATCOM106

void iTde_vFastBlit(long W, long H, long lP, long *src, long *dest)
{
    short           si, sj;
    TDE_tdxPixel    usSpritePixel;
    TDE_tdxPixel    *p_usDest, *p_usSrc;

    p_usDest = (TDE_tdxPixel *)(dest);
    p_usSrc = (TDE_tdxPixel *)(src);    
    
    for (sj=0; sj<H; sj++)
    {
        for (si=0; si<W; si++)
        {
            usSpritePixel = *p_usSrc;            
            *p_usDest = usSpritePixel;            
            p_usDest++;
            p_usSrc++;
        }
        p_usDest += lP;
    }    
}

void iTde_vFastBlit_NZ(long W, long H, long lP, long MC, long *src, long *dest)
{
    short           si, sj;
    TDE_tdxPixel    usSpritePixel;
    TDE_tdxPixel    *p_usDest, *p_usSrc;

    p_usDest = (TDE_tdxPixel *)(dest);
    p_usSrc = (TDE_tdxPixel *)(src);    
    
    for (sj=0; sj<H; sj++)
    {                     
        for (si=0; si<W; si++)
        {
            usSpritePixel = *p_usSrc;            
            if (usSpritePixel!=MC)
              *p_usDest = usSpritePixel;
            p_usDest++;
            p_usSrc++;
        }
        p_usDest += lP;
    }    
}

#else

void iTde_vFastBlit(long W, long H, long lP, long *src, long *dest)
{
    long End_Of_Line1, End_Of_Line4, End_Of_Line, Cmpt1, Cmpt2, Cmpt3, NbLines;
    // Watcom uses the registers as following : 
    // eax = W
    // edx = H
    // ebx = lP
    // ecx = *src
    _asm{
            mov             esi,ecx     
            mov             edi,dest

            mov             ecx,dest
            and             ecx,0xFFFFFFFC
            add             ecx,4
            mov             End_Of_Line1,ecx
            sub             ecx,edi
            shr             ecx,1
            mov             Cmpt1,ecx
    
            lea             ecx,[edi+eax*2]
            mov             End_Of_Line,ecx
            and             ecx,0xFFFFFFFC
            mov             End_Of_Line4,ecx
            sub             ecx,End_Of_Line1
            shr             ecx,2
            mov             Cmpt2,ecx
            mov             ecx,End_Of_Line
            sub             ecx,End_Of_Line4
            shr             ecx,1
            mov             Cmpt3,ecx
Line_Loop :
            mov             ecx,Cmpt1
            cmp             ecx,0
            je              No_Align    
Align1 :
            mov             ax,word ptr[esi]
            add             esi,2
            mov             word ptr[edi],ax
            add             edi,2
            dec             ecx
            jnz             Align1    
No_Align :
            mov             ecx,Cmpt2
            cmp             ecx,0
            je              No_4x4    
L4x4 :
            mov             eax,dword ptr[esi]
            add             esi,4
            mov             dword ptr[edi],eax
            add             edi,4
            dec             ecx
            jnz             L4x4    
No_4x4 :
            mov             ecx,Cmpt3
            cmp             ecx,0
            je              EndOfLine
    
Align2 :
            mov             ax,word ptr[esi]
            add             esi,2
            mov             word ptr[edi],ax
            add             edi,2
            dec             ecx
            jnz             Align2
    
EndOfLine :
            lea             edi,[edi+ebx*2]
            dec             edx
            jnz             Line_Loop   
    }
}

void iTde_vFastBlit_NZ(long W, long H, long lP, long MC, long *src, long *dest)
{
     long End_Of_Line1, End_Of_Line4, End_Of_Line, Cmpt1, Cmpt2, Cmpt3, NbLines;

     lP*=2;
     _asm{
            mov             eax,W
            mov             ebx,H
            mov             ecx,lP
            mov             edx,MC
            mov             esi,src
            mov             edi,dest                     
    
            mov             NbLines,ebx
            mov             ebx,edi
            and             ebx,0FFFFFFFCh
            add             ebx,4
            mov             End_Of_Line1,ebx
            sub             ebx,edi
            shr             ebx,1
            mov             Cmpt1,ebx
    
            lea             ebx,[edi+eax*2]
            mov             End_Of_Line,ebx
            and             ebx,0FFFFFFFCh
            mov             End_Of_Line4,ebx
            sub             ebx,End_Of_Line1
            shr             ebx,2
            mov             Cmpt2,ebx
    
            mov             ebx,End_Of_Line
            sub             ebx,End_Of_Line4
            shr             ebx,1
            mov             Cmpt3,ebx
    
            mov             ebx,edx
            shl             ebx,16
            mov             bx,dx               // ebx = [ MagicColor | MagicColor ]
    
Line_Loop :
    
            mov             edx,Cmpt1
            cmp             edx,0
            je              No_Align
    
Align1 :
            mov             ax,word ptr[esi]
            cmp             ax,bx
            je              NoAff1
            mov             word ptr[edi],ax
NoAff1 :
            add             edi,2
            add             esi,2
            dec             edx
            jnz             Align1
    
No_Align :
            mov             edx,Cmpt2
            cmp             edx,0
            je              No_4x4
    
L4x4 :
            mov             eax,dword ptr[esi]
            mov             ecx,eax              // [ c1 | c2 ] XOR [ MC | MC ]
            xor             ecx,ebx              // c1 = MC, c2 = MC
            jz              Nada                 //
            cmp             ecx,0x010000         // at least one visible
            jb              Right                // if lower, c1 = MC -> draw c2
            test            ecx,0xFFFF           // here, c1 visible. c2 ?
            jz              Left                 // c2 non visible
                                                 // here -> both are visible
Both :
            mov             dword ptr[edi],eax
            jmp             Nada
    
Right :
            mov             word ptr[edi],ax
            jmp             Nada
    
Left :
            shr             eax,16
            mov             word ptr[edi+2],ax
    
Nada :
            add             edi,4
            add             esi,4
            dec             edx
            jnz             L4x4
    
No_4x4 :
            mov             edx,Cmpt3
            cmp             edx,0
            je              EndOfLine
    
Align2 :
            mov             ax,word ptr[esi]
            cmp             ax,bx
            je              NoAff2
            mov             word ptr[edi],ax
NoAff2 :
            add             edi,2
            add             esi,2
            dec             edx
            jnz             Align2
    
EndOfLine :           
            add             edi,lP
            dec             NbLines
            jnz             Line_Loop    
     }
}

#endif


void iTde_vFastBlit_Invert(long W, long H, long lP, long MC, long *src, long *dest)
{
    short           si, sj;
    TDE_tdxPixel    usSpritePixel;
    TDE_tdxPixel    *p_usDest, *p_usSrc;

    p_usDest = (TDE_tdxPixel *)(dest);
    p_usSrc = (TDE_tdxPixel *)(src);    
    
    for (sj=0; sj<H; sj++)
    {                     
        for (si=0; si<W; si++)
        {
            usSpritePixel = *p_usSrc;            
            if (usSpritePixel!=MC)
              *p_usDest = ~usSpritePixel;
            else
              *p_usDest = usSpritePixel;
            p_usDest++;
            p_usSrc++;
        }
        p_usDest += lP;
    }    
}

void iTde_vFastBlit_Invert_NZ(long W, long H, long lP, long MC, long *src, long *dest)
{
    short           si, sj;
    TDE_tdxPixel    usSpritePixel;
    TDE_tdxPixel    *p_usDest, *p_usSrc;

    p_usDest = (TDE_tdxPixel *)(dest);
    p_usSrc = (TDE_tdxPixel *)(src);    
    
    for (sj=0; sj<H; sj++)
    {                     
        for (si=0; si<W; si++)
        {
            usSpritePixel = *p_usSrc;            
            if (usSpritePixel!=MC)
              *p_usDest = ~usSpritePixel;
            p_usDest++;
            p_usSrc++;
        }
        p_usDest += lP;
    }    
}

void iTde_vFastBlitClip_Invert(long W, long H, long SrcJ, long MC, long lP, long *src, long *dest)
{
    short           si, sj;
    TDE_tdxPixel    usSpritePixel;
    TDE_tdxPixel    *p_usDest, *p_usSrc, *p_usLine;

    p_usDest = (TDE_tdxPixel *)(dest);
    p_usSrc = p_usLine = (TDE_tdxPixel *)(src);    
    
    for (sj=0; sj<H; sj++)
    {
        p_usSrc = p_usLine;
        for (si=0; si<W; si++)
        {
            usSpritePixel = *p_usSrc;
            if (usSpritePixel!=MC)
               *p_usDest = ~usSpritePixel;
            else
               *p_usDest = usSpritePixel;
            p_usDest++;
            p_usSrc++;
        }
        p_usDest += lP;
        p_usLine += SrcJ;
    }    
}

void iTde_vFastBlitClip(long W, long H, long SrcJ, long lP, long *src, long *dest)
{
    short           si, sj;
    TDE_tdxPixel    usSpritePixel;
    TDE_tdxPixel    *p_usDest, *p_usSrc, *p_usLine;

    p_usDest = (TDE_tdxPixel *)(dest);
    p_usSrc = p_usLine = (TDE_tdxPixel *)(src);    
    
    for (sj=0; sj<H; sj++)
    {
        p_usSrc = p_usLine;
        for (si=0; si<W; si++)
        {
            usSpritePixel = *p_usSrc;            
            *p_usDest = usSpritePixel;            
            p_usDest++;
            p_usSrc++;
        }
        p_usDest += lP;
        p_usLine += SrcJ;
    }    
}

void iTde_vFastBlitClip_NZ(long W, long H, long SrcJ, long MC, long lP, long *src, long *dest)
{
    short           si, sj;
    TDE_tdxPixel    usSpritePixel;
    TDE_tdxPixel    *p_usDest, *p_usSrc, *p_usLine;

    p_usDest = (TDE_tdxPixel *)(dest);
    p_usSrc = p_usLine = (TDE_tdxPixel *)(src);    
    
    for (sj=0; sj<H; sj++)
    {
        p_usSrc = p_usLine;
        for (si=0; si<W; si++)
        {
            usSpritePixel = *p_usSrc;
            if (usSpritePixel!=MC)
               *p_usDest = usSpritePixel;            
            p_usDest++;
            p_usSrc++;
        }
        p_usDest += lP;
        p_usLine += SrcJ;
    }    
}

void iTde_vFastBlitClip_Invert_NZ(long W, long H, long SrcJ, long MC, long lP, long *src, long *dest)
{
    short           si, sj;
    TDE_tdxPixel    usSpritePixel;
    TDE_tdxPixel    *p_usDest, *p_usSrc, *p_usLine;

    p_usDest = (TDE_tdxPixel *)(dest);
    p_usSrc = p_usLine = (TDE_tdxPixel *)(src);    
    
    for (sj=0; sj<H; sj++)
    {
        p_usSrc = p_usLine;
        for (si=0; si<W; si++)
        {
            usSpritePixel = *p_usSrc;
            if (usSpritePixel!=MC)
               *p_usDest = ~usSpritePixel;
            p_usDest++;
            p_usSrc++;
        }
        p_usDest += lP;
        p_usLine += SrcJ;
    }    
}

void iTDE_vFillsRect(TDE_tdsRect *Rect, TDE_tdxValue xCornerX, TDE_tdxValue xCornerY, TDE_tdxValue xWidth, TDE_tdxValue xHeight)
{
    (*Rect).tdsSommet[0].xX = xCornerX;
    (*Rect).tdsSommet[0].xY = xCornerY;

    (*Rect).tdsSommet[1].xX = xCornerX + xWidth-1;
    (*Rect).tdsSommet[1].xY = xCornerY;
            
    (*Rect).tdsSommet[2].xX = xCornerX + xWidth-1;
    (*Rect).tdsSommet[2].xY = xCornerY + xHeight-1;

    (*Rect).tdsSommet[3].xX = xCornerX;
    (*Rect).tdsSommet[3].xY = xCornerY + xHeight-1;
}

void iTDE_vFillsLRect(TDE_tdsRect *Rect, TDE_tdxValue xCornerX, TDE_tdxValue xCornerY, TDE_tdxValue xWidth, TDE_tdxValue xHeight)
{
    (*Rect).tdsSommet[0].xX = xCornerX;
    (*Rect).tdsSommet[0].xY = xCornerY;

    (*Rect).tdsSommet[1].xX = xCornerX + xWidth-1;
    (*Rect).tdsSommet[1].xY = xCornerY;
            
    (*Rect).tdsSommet[2].xX = xCornerX + xWidth-1;
    (*Rect).tdsSommet[2].xY = xCornerY + xHeight-1;

    (*Rect).tdsSommet[3].xX = xCornerX;
    (*Rect).tdsSommet[3].xY = xCornerY + xHeight-1;
}

void iTDE_vPercentToAbsoluteRect(TDE_tdsRect *Rect, GLD_tdpstViewportAttributes p_stViewAttrib)
{
    short si;

    for (si=0; si<4; si++)
    {
        (*Rect).tdsSommet[si].xX = TDE_M_Mul( (*Rect).tdsSommet[si].xX , p_stViewAttrib->dwWidth );
        (*Rect).tdsSommet[si].xY = TDE_M_Mul( (*Rect).tdsSommet[si].xY , p_stViewAttrib->dwHeight );
    }

}

void iTDE_vMoveRect(TDE_tdsRect *Rect, TDE_tdxValue xTx, TDE_tdxValue xTy)
{
    (*Rect).tdsSommet[0].xX += xTx;
    (*Rect).tdsSommet[0].xY += xTy;

    (*Rect).tdsSommet[1].xX += xTx;
    (*Rect).tdsSommet[1].xY += xTy;
            
    (*Rect).tdsSommet[2].xX += xTx;
    (*Rect).tdsSommet[2].xY += xTy;

    (*Rect).tdsSommet[3].xX += xTx;
    (*Rect).tdsSommet[3].xY += xTy;    
}

void iTDE_vChangeRectCorner(TDE_tdsRect *Rect, TDE_tdxValue xCornerX, TDE_tdxValue xCornerY)
{
    TDE_tdxValue xW, xH;

    xW = ((*Rect).tdsSommet[1].xX) - ((*Rect).tdsSommet[0].xX);
    xH = ((*Rect).tdsSommet[3].xY) - ((*Rect).tdsSommet[0].xY);
    
    (*Rect).tdsSommet[0].xX = xCornerX;
    (*Rect).tdsSommet[0].xY = xCornerY;

    (*Rect).tdsSommet[1].xX = xCornerX + xW;
    (*Rect).tdsSommet[1].xY = xCornerY;
            
    (*Rect).tdsSommet[2].xX = xCornerX + xW;
    (*Rect).tdsSommet[2].xY = xCornerY + xH;

    (*Rect).tdsSommet[3].xX = xCornerX;
    (*Rect).tdsSommet[3].xY = xCornerY + xH;
}


void iTDE_vAdjustRectToFlip(TDE_tdsRect *Rect, TDE_tdsRect *FlippedRect, char cFlip)
{
    switch (cFlip)
    {
        case 0:  // no flip
             *FlippedRect = *Rect;
             return;
        case 1:  // left|right
             (*FlippedRect).tdsSommet[1] = (*Rect).tdsSommet[0];
             (*FlippedRect).tdsSommet[0] = (*Rect).tdsSommet[1];
             (*FlippedRect).tdsSommet[3] = (*Rect).tdsSommet[2];
             (*FlippedRect).tdsSommet[2] = (*Rect).tdsSommet[3];
             (*FlippedRect).p_usPointer = (*Rect).p_usPointer;
             (*FlippedRect).lPitch = (*Rect).lPitch;
             return;
        case 2:  // up|down
             (*FlippedRect).tdsSommet[3] = (*Rect).tdsSommet[0];
             (*FlippedRect).tdsSommet[2] = (*Rect).tdsSommet[1];
             (*FlippedRect).tdsSommet[1] = (*Rect).tdsSommet[2];
             (*FlippedRect).tdsSommet[0] = (*Rect).tdsSommet[3];
             (*FlippedRect).p_usPointer = (*Rect).p_usPointer;
             (*FlippedRect).lPitch = (*Rect).lPitch;        
             return;
        case 3:   // left|right & up|down
             (*FlippedRect).tdsSommet[2] = (*Rect).tdsSommet[0];
             (*FlippedRect).tdsSommet[3] = (*Rect).tdsSommet[1];
             (*FlippedRect).tdsSommet[0] = (*Rect).tdsSommet[2];
             (*FlippedRect).tdsSommet[1] = (*Rect).tdsSommet[3];
             (*FlippedRect).p_usPointer = (*Rect).p_usPointer;
             (*FlippedRect).lPitch = (*Rect).lPitch;                
             return;
    }
}


void iTDE_vAdjustScreenRectForClip(TDE_tdsRect *Rect, TDE_tdsRect *ClippedRect, long lViewPortW, long lViewPortH)
{
     *ClippedRect = *Rect;
     
     if ( Rect->tdsSommet[0].xX<0 )
         (*ClippedRect).tdsSommet[0].xX = (*ClippedRect).tdsSommet[3].xX = 0;
     if ( Rect->tdsSommet[1].xX>lViewPortW )
         (*ClippedRect).tdsSommet[1].xX = (*ClippedRect).tdsSommet[2].xX = lViewPortW;

     if ( Rect->tdsSommet[0].xY<0 )
         (*ClippedRect).tdsSommet[0].xY = (*ClippedRect).tdsSommet[1].xY = 0;
     if ( Rect->tdsSommet[3].xY>lViewPortH )
         (*ClippedRect).tdsSommet[3].xY = (*ClippedRect).tdsSommet[2].xY = lViewPortH;
} 


void iTDE_vAdjustScreenRectToClipRect(TDE_tdsRect *Rect, TDE_tdsRect *ClippedRect, TDE_tdsRect *stClipSq)
{
     *ClippedRect = *Rect;
     
     if ( Rect->tdsSommet[0].xX < stClipSq->tdsSommet[0].xX )
         (*ClippedRect).tdsSommet[0].xX = (*ClippedRect).tdsSommet[3].xX = stClipSq->tdsSommet[0].xX;
     if ( Rect->tdsSommet[1].xX > stClipSq->tdsSommet[1].xX )
         (*ClippedRect).tdsSommet[1].xX = (*ClippedRect).tdsSommet[2].xX = stClipSq->tdsSommet[1].xX;

     if ( Rect->tdsSommet[0].xY < stClipSq->tdsSommet[0].xY )
         (*ClippedRect).tdsSommet[0].xY = (*ClippedRect).tdsSommet[1].xY = stClipSq->tdsSommet[0].xY;
     if ( Rect->tdsSommet[3].xY > stClipSq->tdsSommet[3].xY )
         (*ClippedRect).tdsSommet[3].xY = (*ClippedRect).tdsSommet[2].xY = stClipSq->tdsSommet[3].xY;
} 


void iTDE_vAdjustSourceRectForClip(TDE_tdsRect *ScreenRect, TDE_tdsRect *SrcRect, TDE_tdsRect *SrcClippedRect, long lViewPortW, long lViewPortH)
{
    TDE_tdxValue xScaledSourceW, xScaledSourceH, xScaledSpriteW, xScaledSpriteH, xDec;

    *SrcClippedRect = *SrcRect;
    
    // Signed source dimensions
    xScaledSourceW = (*SrcRect).tdsSommet[1].xX - (*SrcRect).tdsSommet[0].xX;
    xScaledSourceH = (*SrcRect).tdsSommet[3].xY - (*SrcRect).tdsSommet[0].xY;
        
    // Screen sprite dimensions
    xScaledSpriteW = (*ScreenRect).tdsSommet[1].xX - (*ScreenRect).tdsSommet[0].xX;
    xScaledSpriteH = (*ScreenRect).tdsSommet[3].xY - (*ScreenRect).tdsSommet[0].xY;

    // Adjust source rectangle for clipping
    if ( (*ScreenRect).tdsSommet[0].xX<0 )
    {
        xDec = ((*ScreenRect).tdsSommet[0].xX * xScaledSourceW / xScaledSpriteW);
        (*SrcClippedRect).tdsSommet[0].xX -= xDec;
        (*SrcClippedRect).tdsSommet[3].xX -= xDec;
    }

    if ( (*ScreenRect).tdsSommet[1].xX>lViewPortW )
    {
        xDec = (((*ScreenRect).tdsSommet[1].xX - lViewPortW) * xScaledSourceW / xScaledSpriteW);
        (*SrcClippedRect).tdsSommet[1].xX -= xDec;
        (*SrcClippedRect).tdsSommet[2].xX -= xDec;
    }

    if ( (*ScreenRect).tdsSommet[0].xY<0 )
    {
        xDec = ((*ScreenRect).tdsSommet[0].xY * xScaledSourceH / xScaledSpriteH);
        (*SrcClippedRect).tdsSommet[0].xY -= xDec;
        (*SrcClippedRect).tdsSommet[1].xY -= xDec;
    }

    if ( (*ScreenRect).tdsSommet[3].xY>lViewPortH )
    {
        xDec = (((*ScreenRect).tdsSommet[3].xY - lViewPortH) * xScaledSourceH / xScaledSpriteH);
        (*SrcClippedRect).tdsSommet[2].xY -= xDec;
        (*SrcClippedRect).tdsSommet[3].xY -= xDec;
    }
    
}

void iTDE_vBlit(TDE_tdsRect *RectSource, TDE_tdsRect *RectDest)
{
    short           si, sj;
    TDE_tdxPixel    *p_usDest, *p_usSource, usSpritePixel;
    long            lScaledSpriteW, lScaledSpriteH,
                     ldE, lE, lF, ldF, lPitchSrc, lPitchDest;
    TDE_tdxValue     xScaledSpriteW, xScaledSpriteH, xScaledSourceW, xScaledSourceH;
    TDE_tdl1616      lHorzOrigin, lVertOrigin, lHorzIncrement, lVertIncrement, lU;

    p_usSource = RectSource->p_usPointer;
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);    
    
    xScaledSpriteW = RectDest->tdsSommet[1].xX - RectDest->tdsSommet[0].xX;
    xScaledSpriteH = RectDest->tdsSommet[3].xY - RectDest->tdsSommet[0].xY;
    lScaledSpriteW = TDE_M_ValueToLong( xScaledSpriteW );
    lScaledSpriteH = TDE_M_ValueToLong( xScaledSpriteH );    
    xScaledSourceW = RectSource->tdsSommet[1].xX - RectSource->tdsSommet[0].xX;
    xScaledSourceH = RectSource->tdsSommet[3].xY - RectSource->tdsSommet[0].xY;
        
    lHorzIncrement = TDE_M_ValueTo1616( TDE_M_Div( xScaledSourceW , xScaledSpriteW) );   
    lVertIncrement = TDE_M_ValueTo1616( TDE_M_Div( xScaledSourceH , xScaledSpriteH) );    
    lHorzOrigin = lU =  TDE_M_ValueTo1616( RectSource->tdsSommet[0].xX);
    lVertOrigin = TDE_M_ValueTo1616( RectSource->tdsSommet[0].xY);          

    lPitchSrc = RectSource->lPitch;
    lPitchDest = (RectDest->lPitch)-lScaledSpriteW;
    
    lE = lPitchSrc*(lVertOrigin>>16);
    ldE = lPitchSrc*(lVertIncrement>>16);
    lF = (lVertOrigin>>1)&0x7FFF;
    ldF = (lVertIncrement>>1)&0x7FFF;
          
    for (sj=0; sj<lScaledSpriteH; sj++)
    {        
        for (si=0; si<lScaledSpriteW; si++)
        {
            usSpritePixel = *(p_usSource+lE+(lU>>16));            
            //if (usSpritePixel>0)
               *p_usDest = usSpritePixel;
            p_usDest++;
            lU += lHorzIncrement;
        }
        lU = lHorzOrigin;
        lE += ldE;
        lF += ldF;
        if (lF&0x8000) 
        { 
            lF &= 0x7FFF; 
            lE += lPitchSrc; 
        }
        
        p_usDest += lPitchDest;        
    }    
}

void iTDE_vBlitFast(TDE_tdsRect *RectSource, TDE_tdsRect *RectDest)
{
    short           si, sj;
    TDE_tdxPixel    *p_usDest, *p_usSource, usSpritePixel;
    long            lScaledSpriteW, lScaledSpriteH, lSrcIncr, lDestIncr;
    
    lScaledSpriteW = TDE_M_ValueToLong( RectDest->tdsSommet[1].xX - RectDest->tdsSommet[0].xX );
    lScaledSpriteH = TDE_M_ValueToLong( RectDest->tdsSommet[3].xY - RectDest->tdsSommet[0].xY );    
    
    p_usSource = (RectSource->p_usPointer) + (long)((RectSource->lPitch)*(RectSource->tdsSommet[0].xY) + (RectSource->tdsSommet[0].xX));
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);    

    lDestIncr = RectDest->lPitch - lScaledSpriteW;
    lSrcIncr = RectSource->lPitch - lScaledSpriteW;
                  
    for (sj=0; sj<lScaledSpriteH; sj++)
    {        
        for (si=0; si<lScaledSpriteW; si++)
        {
            usSpritePixel = *p_usSource;            
            if (usSpritePixel>0) *p_usDest = usSpritePixel;
            p_usDest++;
            p_usSource++;
        }
        p_usDest += lDestIncr;
        p_usSource += lSrcIncr;
    }    
}

void iTDE_vBlitFastMemory(TDE_tdsMemZone *Source, TDE_tdsRect *RectDest)
{
    TDE_tdxPixel    *p_usDest, *p_usSource;
    long            lScaledSpriteW, lScaledSpriteH, lDestIncr;
        
    lScaledSpriteW = TDE_M_ValueToLong( Source->stDim.xX );
    lScaledSpriteH = TDE_M_ValueToLong( Source->stDim.xY );
    
    p_usSource = (Source->p_usPointer);
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);

    lDestIncr = RectDest->lPitch - lScaledSpriteW;
    
    iTde_vFastBlit(lScaledSpriteW, lScaledSpriteH, lDestIncr, (long *)p_usSource, (long *)p_usDest);
}

void iTDE_vBlitClipMemory(TDE_tdsMemZone *Source, TDE_tdsRect *RectDest)
{
    TDE_tdxPixel    *p_usDest, *p_usSource;
    long            lScreenSpriteW, lScreenSpriteH, lSrcJump, lDestIncr;
        
    lScreenSpriteW = TDE_M_ValueToLong( RectDest->tdsSommet[1].xX - RectDest->tdsSommet[0].xX + 1);
    lScreenSpriteH = TDE_M_ValueToLong( RectDest->tdsSommet[3].xY - RectDest->tdsSommet[0].xY + 1);
    lSrcJump = TDE_M_ValueToLong( Source->stDim.xX);
    
    p_usSource = (Source->p_usPointer);
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);

    lDestIncr = RectDest->lPitch - lScreenSpriteW;
    
    iTde_vFastBlitClip(lScreenSpriteW, lScreenSpriteH, lSrcJump, lDestIncr, (long *)p_usSource, (long *)p_usDest);
}

// clipping along a rectangle
void iTDE_vBlitClipMemory2(TDE_tdsMemZone *Source, TDE_tdsRect *RectDest)
{
    TDE_tdxPixel    *p_usDest, *p_usSource;
    long            lScreenSpriteW, lScreenSpriteH, lSrcJump, lDestIncr;
        
    lScreenSpriteW = TDE_M_ValueToLong( RectDest->tdsSommet[1].xX - RectDest->tdsSommet[0].xX + 1);
    lScreenSpriteH = TDE_M_ValueToLong( RectDest->tdsSommet[3].xY - RectDest->tdsSommet[0].xY + 1);
    lSrcJump = TDE_M_ValueToLong( Source->stDim.xX);
    
    p_usSource = (Source->p_usPointer);
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);

    lDestIncr = RectDest->lPitch - lScreenSpriteW;
    
    iTde_vFastBlitClip(lScreenSpriteW, lScreenSpriteH, lSrcJump, lDestIncr, (long *)p_usSource, (long *)p_usDest);
}


void iTDE_vBlitClipMemory_NZ(TDE_tdsMemZone *Source, TDE_tdsRect *RectDest)
{
    TDE_tdxPixel    *p_usDest, *p_usSource, xMagicColor;
    long            lScreenSpriteW, lScreenSpriteH, lSrcJump, lDestIncr;
        
    lScreenSpriteW = TDE_M_ValueToLong( RectDest->tdsSommet[1].xX - RectDest->tdsSommet[0].xX + 1 );
    lScreenSpriteH = TDE_M_ValueToLong( RectDest->tdsSommet[3].xY - RectDest->tdsSommet[0].xY + 1 );
    lSrcJump = TDE_M_ValueToLong( Source->stDim.xX );
    xMagicColor = Source->xMagicColor;
    
    p_usSource = (Source->p_usPointer);
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);

    lDestIncr = RectDest->lPitch - lScreenSpriteW;
    
    iTde_vFastBlitClip_NZ(lScreenSpriteW, lScreenSpriteH, lSrcJump, (long) xMagicColor, lDestIncr, (long *)p_usSource, (long *)p_usDest);
}

void iTDE_vBlitClipMemory_Invert(TDE_tdsMemZone *Source, TDE_tdsRect *RectDest)
{
    TDE_tdxPixel    *p_usDest, *p_usSource, xMagicColor;
    long            lScreenSpriteW, lScreenSpriteH, lSrcJump, lDestIncr;
        
    lScreenSpriteW = TDE_M_ValueToLong( RectDest->tdsSommet[1].xX - RectDest->tdsSommet[0].xX + 1 );
    lScreenSpriteH = TDE_M_ValueToLong( RectDest->tdsSommet[3].xY - RectDest->tdsSommet[0].xY + 1 );
    lSrcJump = TDE_M_ValueToLong( Source->stDim.xX );
    xMagicColor = Source->xMagicColor;
    
    p_usSource = (Source->p_usPointer);
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);

    lDestIncr = RectDest->lPitch - lScreenSpriteW;
    
    iTde_vFastBlitClip_Invert(lScreenSpriteW, lScreenSpriteH, lSrcJump, (long) xMagicColor, lDestIncr, (long *)p_usSource, (long *)p_usDest);
}

void iTDE_vBlitClipMemory_Invert_NZ(TDE_tdsMemZone *Source, TDE_tdsRect *RectDest)
{
    TDE_tdxPixel    *p_usDest, *p_usSource, xMagicColor;
    long            lScreenSpriteW, lScreenSpriteH, lSrcJump, lDestIncr;
        
    lScreenSpriteW = TDE_M_ValueToLong( RectDest->tdsSommet[1].xX - RectDest->tdsSommet[0].xX + 1 );
    lScreenSpriteH = TDE_M_ValueToLong( RectDest->tdsSommet[3].xY - RectDest->tdsSommet[0].xY + 1 );
    lSrcJump = TDE_M_ValueToLong( Source->stDim.xX );
    xMagicColor = Source->xMagicColor;
    
    p_usSource = (Source->p_usPointer);
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);

    lDestIncr = RectDest->lPitch - lScreenSpriteW;
    
    iTde_vFastBlitClip_Invert_NZ(lScreenSpriteW, lScreenSpriteH, lSrcJump, (long) xMagicColor, lDestIncr, (long *)p_usSource, (long *)p_usDest);
}

void iTDE_vBlitFastMemory_NZ(TDE_tdsMemZone *Source, TDE_tdsRect *RectDest)
{
    TDE_tdxPixel    *p_usDest, *p_usSource;
    TDE_tdxPixel    usMagicColor;
    long            lScaledSpriteW, lScaledSpriteH, lDestIncr;
        
    lScaledSpriteW = TDE_M_ValueToLong( Source->stDim.xX );
    lScaledSpriteH = TDE_M_ValueToLong( Source->stDim.xY );
    
    p_usSource = (Source->p_usPointer);
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);

    lDestIncr = RectDest->lPitch - lScaledSpriteW;
    usMagicColor = Source->xMagicColor;
    
    iTde_vFastBlit_NZ(lScaledSpriteW, lScaledSpriteH, lDestIncr, (long)(usMagicColor), (long *)p_usSource, (long *)p_usDest);    
}

void iTDE_vBlitFastMemory_Invert(TDE_tdsMemZone *Source, TDE_tdsRect *RectDest)
{
    TDE_tdxPixel    *p_usDest, *p_usSource;
    TDE_tdxPixel    usMagicColor;
    long            lScaledSpriteW, lScaledSpriteH, lDestIncr;
        
    lScaledSpriteW = TDE_M_ValueToLong( Source->stDim.xX );
    lScaledSpriteH = TDE_M_ValueToLong( Source->stDim.xY );
    
    p_usSource = (Source->p_usPointer);
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);

    lDestIncr = RectDest->lPitch - lScaledSpriteW;
    usMagicColor = Source->xMagicColor;
    
    iTde_vFastBlit_Invert(lScaledSpriteW, lScaledSpriteH, lDestIncr, (long)(usMagicColor), (long *)p_usSource, (long *)p_usDest);    
}

void iTDE_vBlitFastMemory_Invert_NZ(TDE_tdsMemZone *Source, TDE_tdsRect *RectDest)
{
    TDE_tdxPixel    *p_usDest, *p_usSource;
    TDE_tdxPixel    usMagicColor;
    long            lScaledSpriteW, lScaledSpriteH, lDestIncr;
        
    lScaledSpriteW = TDE_M_ValueToLong( Source->stDim.xX );
    lScaledSpriteH = TDE_M_ValueToLong( Source->stDim.xY );
    
    p_usSource = (Source->p_usPointer);
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);

    lDestIncr = RectDest->lPitch - lScaledSpriteW;
    usMagicColor = Source->xMagicColor;
    
    iTde_vFastBlit_Invert_NZ(lScaledSpriteW, lScaledSpriteH, lDestIncr, (long)(usMagicColor), (long *)p_usSource, (long *)p_usDest);    
}


void iTDE_vBlit_Transparency(TDE_tdsRect *RectSource, TDE_tdsRect *RectDest, TDE_tdxValue xAlpha)
{
    short           si, sj;
    TDE_tdxPixel     *p_usDest, *p_usSource, usSpritePixel, usBackPixel;
    long            lScaledSpriteW, lScaledSpriteH,
                     ldE, lE, lF, ldF, lPitchSrc, lPitchDest;
    TDE_tdxValue     xScaledSpriteW, xScaledSpriteH, xScaledSourceW, xScaledSourceH;
    TDE_tdl1616      lHorzOrigin, lVertOrigin, lHorzIncrement, lVertIncrement, lU;

    // Variables for alpha-transparency
    short sBlueMask = 0x001F;   // 0000 0000 0001 1111  -> obtain blue component
    short sGreenMask = 0x7E0;   // 0000 0111 1110 0000  -> obtain green component
//    short sRedMask  = 0xF800;   // 1111 1000 0000 0000  -> obtain red component
    short sB, sG, sR;
    char cIndix1, cIndix2;
    unsigned char *p_cAcc15, *p_cAcc25, *p_cAcc16, *p_cAcc26;

    p_usSource = RectSource->p_usPointer;
    p_usDest = RectDest->p_usPointer +
       (TDE_M_ValueToLong(RectDest->lPitch)) * (TDE_M_ValueToLong(RectDest->tdsSommet[0].xY)) + TDE_M_ValueToLong(RectDest->tdsSommet[0].xX);    
    
    xScaledSpriteW = RectDest->tdsSommet[1].xX - RectDest->tdsSommet[0].xX;
    xScaledSpriteH = RectDest->tdsSommet[3].xY - RectDest->tdsSommet[0].xY;
    lScaledSpriteW = TDE_M_ValueToLong( xScaledSpriteW );
    lScaledSpriteH = TDE_M_ValueToLong( xScaledSpriteH );    
    xScaledSourceW = RectSource->tdsSommet[1].xX - RectSource->tdsSommet[0].xX;
    xScaledSourceH = RectSource->tdsSommet[3].xY - RectSource->tdsSommet[0].xY;
        
    lHorzIncrement = TDE_M_ValueTo1616( TDE_M_Div( xScaledSourceW , xScaledSpriteW) );   
    lVertIncrement = TDE_M_ValueTo1616( TDE_M_Div( xScaledSourceH , xScaledSpriteH) );    
    lHorzOrigin = lU =  TDE_M_ValueTo1616( RectSource->tdsSommet[0].xX);
    lVertOrigin = TDE_M_ValueTo1616( RectSource->tdsSommet[0].xY);          

    lPitchSrc = RectSource->lPitch;
    lPitchDest = (RectDest->lPitch)-lScaledSpriteW;
    
    lE = lPitchSrc*(lVertOrigin>>16);
    ldE = lPitchSrc*(lVertIncrement>>16);
    lF = (lVertOrigin>>1)&0x7FFF;
    ldF = (lVertIncrement>>1)&0x7FFF;

    cIndix1 = ((char)(xAlpha*64))&0x3F;
    cIndix2 = 63-cIndix1;
    p_cAcc15 = &(a_cTransparencyTable5[cIndix1][0]);
    p_cAcc25 = &(a_cTransparencyTable5[cIndix2][0]);
    p_cAcc16 = &(a_cTransparencyTable6[cIndix1][0]);
    p_cAcc26 = &(a_cTransparencyTable6[cIndix2][0]);
              
    for (sj=0; sj<lScaledSpriteH; sj++)
    {        
        for (si=0; si<lScaledSpriteW; si++)
        {
            usSpritePixel = *(p_usSource+lE+(lU>>16));            
            if (usSpritePixel>0)
            {
                usBackPixel = *p_usDest;                
                /*
                usSpritePixel = (usSpritePixel & sMasque_565)>>1;
                usBackPixel = (usBackPixel & sMasque_565)>>1;
                *p_usDest = usSpritePixel + usBackPixel;
                */                                                                
                sB = *(p_cAcc15 + (usBackPixel & sBlueMask)) + *(p_cAcc25+ (usSpritePixel & sBlueMask));
                sG = *(p_cAcc16 + ((usBackPixel & sGreenMask)>>5)) + *(p_cAcc26 + ((usSpritePixel & sGreenMask)>>5));
                sR = *(p_cAcc15 + (usBackPixel>>11)) + *(p_cAcc25 + (usSpritePixel>>11));                
                *p_usDest = sB+(sG<<5)+(sR<<11);                               
            }
            p_usDest++;
            lU += lHorzIncrement;
        }
        lU = lHorzOrigin;
        lE += ldE;
        lF += ldF;
        if (lF&0x8000) 
        { 
            lF &= 0x7FFF; 
            lE += lPitchSrc; 
        }
        
        p_usDest += lPitchDest;        
    }    
}


