
// lg3drasw.cpp
//
// Copyright (c) 1996 by Toshiaki Tsuji, all rights reserved.

#include "stdgfx.h"
#include "lg3dras.h"

LONG  _LeftX;
LONG  _LeftY;
LONG  _LeftU;
LONG  _LeftV;
LONG  _LeftI;
LONG  _LeftZ;
  
LONG  _RightX;
LONG  _RightY;
LONG  _RightU;
LONG  _RightV;
LONG  _RightI;
LONG  _RightZ;
  
LONG  _LeftDx;
LONG  _LeftDy;
LONG  _LeftDu;
LONG  _LeftDv;
LONG  _LeftDI;
LONG  _LeftDz;
  
LONG  _RightDx;
LONG  _RightDy;
LONG  _RightDu;
LONG  _RightDv;
LONG  _RightDI;
LONG  _RightDz;
    
BYTE*  _DestBuffer;
BYTE*  _TextureBuffer;
LONG   _AddDest;
BYTE*  _ShadeBuffer;
float* _DivTable;

LONG  Color;
LONG  LoopCount;
LONG  VMinX;
LONG  VMaxX;
LONG  VMinY;
LONG  VMaxY;
LONG  TempLen;
LONG  TempVal;
  
// Inner Loop Delta
LONG  InDeltaDI;
LONG  InDeltaDu;
LONG  InDeltaDv;

LONG  FracDv;
LONG  FracDI;
SHORT  FracDu;
BYTE  IntDu;
BYTE  IntDv;
BYTE  IntDI;

float DummyFloat;

// VOID _SetViewPortData ( LONG MinX, LONG MinY, LONG MaxX, LONG MaxY )
//
// EAX = MinX, EDX = MinY, EBX = MaxX, ECX = MaxY

VOID _SetViewPortData ( LONG MinX, LONG MinY, 
                        LONG MaxX, LONG MaxY );
#pragma aux _SetViewPortData = \
  "mov  VMinX, EAX" \
  "mov  VMinY, EDX" \
  "mov  VMaxX, EBX" \
  "mov  VMaxY, ECX" \
  parm [EAX] [EDX] [EBX] [ECX]
// End of _SetViewPortData


// VOID _DrawSolidNoHorz ( LONG Color, LONG LoopCount, LONG SkipRow, LONG SideClipped )
//
// EAX = Color, EDX = LoopCount, EBX = SkipRow, ECX = SideClipped

VOID _DrawSolidNoHorz ( LONG nColor, LONG nLoopCount, 
                        LONG SkipRow, LONG SideClipped );
#pragma aux _DrawSolidNoHorz = \
  "mov  Color, EAX" \
\  
  "sub  EDX, EBX" \
  "mov  LoopCount, EDX" \
\  
  "cmp  EBX, 0" \
  "je   CheckClippedSolidNoHorz " \
\  
      "mov  EAX, _LeftDx" \
    "imul  EBX" \
    "add  _LeftX, EAX" \
    "mov  EAX, _RightDx" \
    "imul  EBX" \
    "add  _RightX, EAX" \
\
    "mov  EAX, _AddDest" \
    "imul  EBX" \
    "add  _DestBuffer, EAX" \
\
  "CheckClippedSolidNoHorz :" \
    "cmp  ECX, 0" \
    "jne  DrawSolidNoHorzClip" \
\
  "DrawSolidNoHorzNoClip :" \
    "cld" \
    "mov  ESI, LoopCount" \
    "cmp  ESI, 0" \
    "jle  EndLoopOutSolidNoHorz" \
    "adc  EAX, 0"  \
    "nop" \
\
    "LoopOutSolidNoHorz :" \
      "mov  EBX, _LeftX" \
      "mov  EAX, EBX" \
      "add  EBX, _LeftDx" \
      "sar  EAX, 16" \
      "mov  _LeftX, EBX" \
\
      "mov  EDX, _RightX" \
      "mov  ECX, EDX" \
      "add  EDX, _RightDx" \
      "sar  ECX, 16" \
      "mov  _RightX, EDX" \
\
      "mov  EBX, _DestBuffer" \
      "mov  EDI, EBX" \
      "add  EBX, _AddDest" \
      "mov  _DestBuffer, EBX" \
\
      "sub  ECX, EAX           ; V" \
      "add  EDI, EAX           ; U" \
      "inc  ECX                ; V" \
      "cmp  ECX, 0" \
      "jle  NextRowSolidNoHorzNoClip " \
\
      "mov  EAX, Color         ; U" \
      "mov  EDX, ECX           ; V" \
\    
      "shr  ECX, 2             ; U" \
      "and  EDX, 3             ; V" \
      "rep  stosd" \
      "mov  ECX, EDX" \
      "rep  stosb" \
\
      "NextRowSolidNoHorzNoClip :" \
        "dec  ESI" \
        "jnz  LoopOutSolidNoHorz" \
      "jmp  EndLoopOutSolidNoHorz" \
\
  "DrawSolidNoHorzClip :" \
    "cld" \
    "mov  ESI, LoopCount" \
    "cmp  ESI, 0" \
    "jle  EndLoopOutSolidNoHorz" \
    "adc  EAX, 0        ; Make sure the loop starts with U pipe" \
    "nop" \
\
    "LoopOutClippedSolidNoHorz :" \
      "mov  EBX, _LeftX    ; U" \
      "mov  EAX, EBX        ; U" \
      "add  EBX, _LeftDx   ; V" \
      "sar  EAX, 16         ; U EAX is the Left X" \
      "mov  _LeftX, EBX    ; V" \
\
      "mov  EDX, _RightX   ; U" \
      "mov  ECX, EDX       ; U" \
      "add  EDX, _RightDx  ; V" \
      "sar  ECX, 16        ; U ECX is the Right X" \
      "mov  _RightX, EDX   ; V" \
\
      "mov  EBX, _DestBuffer  ; U" \
      "mov  EDI, EBX          ; U" \
      "add  EBX, _AddDest     ; V" \
      "mov  _DestBuffer, EBX  ; U" \
\
        "; Check for Easy reject" \
        "cmp  EAX, VMaxX      ; Left is greater than MaxX" \
        "jg   NextRowSolidNoHorz" \
        "cmp  ECX, VMinX      ; Right is smaller than MinX" \
        "jl   NextRowSolidNoHorz" \
\
        "; Check for Left" \
        "cmp  EAX, VMinX" \
        "jge  CheckRightSolidNoHorz" \
          "mov  EAX, VMinX    ; Set Left to MinX" \
\
        "; Check for Right" \
      "CheckRightSolidNoHorz :" \
        "cmp  ECX, VMaxX" \
        "jle  StartSolidNoHorz" \
        "mov  ECX, VMaxX    ; Set Right to MaxX" \
\
    "StartSolidNoHorz :" \
      "sub  ECX, EAX" \
      "inc  ECX"
      "cmp  ECX, 0" \
      "jle  NextRowSolidNoHorz" \
\
      "add  EDI, EAX" \
\
      "mov  EAX, Color" \         
      "mov  EDX, ECX" \
\    
      "shr  ECX, 2" \
      "and  EDX, 3" \
      "rep  stosd" \
      "mov  ECX, EDX" \
      "rep  stosb" \
\    
      "NextRowSolidNoHorz :" \ 
        "dec  ESI" \
      "jnz  LoopOutClippedSolidNoHorz" \
\
  "EndLoopOutSolidNoHorz :" \
  parm [EAX] [EDX] [EBX] [ECX]
// End of _DrawSolidNoHorz


// VOID _DrawSolidGrdHorz ( LONG Color, LONG LoopCount, LONG SkipRow, LONG SideClipped )
//
// EAX = Color, EDX = LoopCount, EBX = SkipRow, ECX = SideClipped

VOID _DrawSolidGrdHorz ( LONG nColor, LONG nLoopCount, LONG SkipRow, 
                                                 LONG SideClipped )
{
_asm {
  pushad

  "mov EAX, nColor
  "mov EDX, nLoopCount
  "mov EBX, SkipRow
  "mov ECX, SideClipped
    
  "mov  Color, EAX

  sub  EDX, EBX
  "mov  LoopCount, EDX

  "cmp  EBX, 0
  je   CheckClippedSolidGrdHorz 

    "mov  EAX, _LeftDx
    imul  EBX
    "add  _LeftX, EAX

    "mov  EAX, _RightDx
    imul  EBX
    "add  _RightX, EAX

    "mov  EAX, _LeftDI
    imul  EBX
    "add  _LeftI, EAX

    "mov  EAX, _RightDI
    imul  EBX
    "add  _RightI, EAX

    "mov  EAX, _"addDest
    imul  EBX
    "add  _DestBuffer, EAX

  CheckClippedSolidGrdHorz :
    "cmp  ECX, 0
    jne  DrawSolidGrdHorzClip

  DrawSolidGrdHorzNoClip :
    "cld
    "mov  ESI, LoopCount
    "cmp  ESI, 0
    "jle  EndLoopOutSolidGrdHorz
    "adc  EAX, 0        ; Make sure the loop starts with U pipe
    nop          

    LoopOutSolidGrdHorz :
      "mov  EBX, _LeftX    ; U
      "mov  EAX, EBX        ; U
      "add  EBX, _LeftDx   ; V
      "sar  EAX, 16         ; U EAX is the Left X
      "mov  _LeftX, EBX    ; V

      "mov  EDX, _RightX   ; U
      "mov  ECX, EDX        ; U
      "add  EDX, _RightDx  ; V
      "sar  ECX, 16         ; U ECX is the Right X
      "mov  _RightX, EDX   ; V

      "mov  EBX, _DestBuffer  ; U
      "mov  EDI, EBX           ; U
      "add  EBX, _"addDest     ; V
      sub  ECX, EAX           ; U

      "mov  _DestBuffer, EBX  ; V

      "add  EDI, EAX           ; U
      inc  ECX                ; V
      
      "mov  EBX, _LeftI    ; U
      "mov  EAX, EBX        ; U     EAX is the Left I
      "add  EBX, _LeftDI   ; V
      "mov  _LeftI, EBX    ; V
      
      "mov  EBX, _RightI   ; U
      "mov  EDX, EBX        ; U     EDX is the Right I
      "add  EBX, _RightDI  ; V
      "mov  _RightI, EBX   ; V
      
      "cmp  ECX, 0
      "jle  NextRowSolidGrdHorzNoClip

      "mov  EBX, EAX        ; EBX is the Left I
      sub  EDX, EAX
      "mov  EAX, EDX
      "sar  EDX, 01Fh
      idiv ECX
      "mov  InDeltaDI, EAX

      "mov  EBP, EBX
      "mov  EAX, Color        
      "mov  EDX, InDeltaDI 
      push ESI
      "mov  ESI, _ShadeBuffer
      
        InLoopSolidGrdHorz :
          "mov  EBX, EBP
          shr  EBX, 8
          "mov  BL, AL
          "add  EBP, EDX
          "mov  AH, [EBX+ESI]
          "mov  [EDI], AH
          inc  EDI
          loop InLoopSolidGrdHorz

      pop  ESI

      NextRowSolidGrdHorzNoClip :
        dec  ESI
        jnz  LoopOutSolidGrdHorz
      jmp  EndLoopOutSolidGrdHorz

  DrawSolidGrdHorzClip :
    "cld
    "mov  ESI, LoopCount
    "cmp  ESI, 0
    "jle  EndLoopOutSolidGrdHorz
    "adc  EAX, 0        ; Make sure the loop starts with U pipe
    nop          

    LoopOutClippedSolidGrdHorz :
      "mov  EBX, _LeftX    ; U
      "mov  EAX, EBX        ; U
      "add  EBX, _LeftDx   ; V
      "sar  EAX, 16         ; U EAX is the Left X
      "mov  _LeftX, EBX    ; V

      "mov  EDX, _RightX   ; U
      "mov  ECX, EDX        ; U
      "add  EDX, _RightDx  ; V
      "sar  ECX, 16         ; U ECX is the Right X
      "mov  _RightX, EDX   ; V

      "mov  EBX, _DestBuffer  ; U
      "mov  EDI, EBX           ; U
      "add  EBX, _"addDest     ; V
      "mov  _DestBuffer, EBX  ; U

      "mov  TempLen, ECX
      sub  TempLen, EAX
      inc  TempLen
      "mov  EBX, 0

        ; Check for Easy reject
        "cmp  EAX, VMaxX      ; Left is greater than MaxX
        jg   NextRowSolidGrdHorz
        "cmp  ECX, VMinX      ; Right is smaller than MinX
        jl   NextRowSolidGrdHorz

        ; Check for Left
        "cmp  EAX, VMinX
        jge  CheckRightSolidGrdHorz
          "mov  EBX, VMinX
          sub  EBX, EAX
          "mov  EAX, VMinX    ; Set Left to MinX

        ; Check for Right
        CheckRightSolidGrdHorz :
          "cmp  ECX, VMaxX
          "jle  StartSolidGrdHorz
          "mov  ECX, VMaxX    ; Set Right to MaxX

    StartSolidGrdHorz :  ; Clipped
      sub  ECX, EAX
      inc  ECX

      "add  EDI, EAX

      "mov  EBP, TempLen    ; EBP is the loop count before clipped
      "mov  TempLen, EBX    ; TempLen is now the skip pixel in x-direction

      "mov  EBX, _LeftI    ; U
      "mov  EAX, EBX        ; U   EAX is the Left I
      "add  EBX, _LeftDI   ; V
      "mov  _LeftI, EBX    ; V
      
      "mov  EBX, _RightI   ; U
      "mov  EDX, EBX        ; U   EDX is the Right I
      "add  EBX, _RightDI  ; V
      "mov  _RightI, EBX   ; V
            
      "cmp  ECX, 0
      "jle  NextRowSolidGrdHorz

      "mov  EBX, EAX        ; EAX is Left I
      sub  EDX, EAX
      "mov  EAX, EDX
      "sar  EDX, 01Fh
      idiv EBP
      "mov  InDeltaDI, EAX

      ; "add Delta for Skipped pixel
      "mov  EBP, EBX
      "mov  EAX, InDeltaDI
      imul TempLen 
      "add  EBP, EAX

      "mov  EAX, Color        
      "mov  EDX, InDeltaDI 
      push ESI
      "mov  ESI, _ShadeBuffer
      
        InLoopClippedSolidGrdHorz :
          "mov  EBX, EBP
          shr  EBX, 8
          "mov  BL, AL
          "mov  AH, [EBX+ESI]
          "add  EBP, EDX
          "mov  [EDI], AH
          inc  EDI
          loop InLoopClippedSolidGrdHorz
    
      pop  ESI
      NextRowSolidGrdHorz : 
        dec  ESI
      jnz  LoopOutClippedSolidGrdHorz

  EndLoopOutSolidGrdHorz :

  popad
} // End asm
} // End of _DrawSolidGrdHorz


// VOID _DrawTextureNoHorz ( LONG Color, LONG LoopCount, LONG SkipRow, LONG SideClipped )
//
// EAX = Color, EDX = LoopCount, EBX = SkipRow, ECX = SideClipped

VOID _DrawTextureNoHorz ( LONG nColor, LONG nLoopCount, 
                                                  LONG SkipRow, LONG SideClipped )
{
_asm {
  pushad

  "mov EAX, nColor
  "mov EDX, nLoopCount
  "mov EBX, SkipRow
  "mov ECX, SideClipped

  sub  EDX, EBX
  "mov  LoopCount, EDX

  "cmp  EBX, 0
  je   CheckClippedTextureNoHorz 

    "mov  EAX, _LeftDx
    imul  EBX
    "add  _LeftX, EAX

    "mov  EAX, _RightDx
    imul  EBX
    "add  _RightX, EAX

    "mov  EAX, _LeftDu
    imul  EBX
    "add  _LeftU, EAX

    "mov  EAX, _RightDu
    imul  EBX
    "add  _RightU, EAX

    "mov  EAX, _LeftDv
    imul  EBX
    "add  _LeftV, EAX

    "mov  EAX, _RightDv
    imul  EBX
    "add  _RightV, EAX

    "mov  EAX, _"addDest
    imul  EBX
    "add  _DestBuffer, EAX

  CheckClippedTextureNoHorz :
    "cmp  ECX, 0
    jne  DrawTextureNoHorzClip

  DrawTextureNoHorzNoClip :
    "cld
    "mov  ESI, LoopCount
    "cmp  ESI, 0
    "jle  EndLoopOutTextureNoHorz
    "adc  EAX, 0        ; Make sure the loop starts with U pipe
    nop          

    LoopOutTextureNoHorz :
      "mov  EBX, _LeftX    ; U
      "mov  EAX, EBX        ; U
      "add  EBX, _LeftDx   ; V
      "sar  EAX, 16         ; U EAX is the Left X
      "mov  _LeftX, EBX    ; V

      "mov  EDX, _RightX   ; U
      "mov  ECX, EDX        ; U
      "add  EDX, _RightDx  ; V
      "sar  ECX, 16         ; U ECX is the Right X
      "mov  _RightX, EDX   ; V

      "mov  EBX, _DestBuffer  ; U
      "mov  EDI, EBX           ; U
      "add  EBX, _"addDest     ; V
      "mov  _DestBuffer, EBX  ; U

      sub  ECX, EAX           ; V
      "add  EDI, EAX           ; U
      inc  ECX                ; V
            
      "cmp  ECX, 0
      "jle  NextRowTextureNoHorzNoClip

      "mov  EBP, ECX
      "shl  EBP, 2
      "add  EBP, _DivTable
      fld  dword ptr [EBP] 
      
      "mov  EBP, ECX      ; EBP is the loop

      "mov  EAX, _LeftU    
      "mov  EDX, _RightU         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDu, EDX
      fild InDeltaDu      
      fmul st, st(1)
      fistp InDeltaDu
      
      "mov  EAX, _LeftV    
      "mov  EDX, _RightV         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDv, EDX
      fild InDeltaDv      
      fmul st, st(1)
      fistp InDeltaDv

      fstp DummyFloat

      push ESI

      "mov  ECX, _LeftU
      "sar  ECX, 8
      "mov  EDX, _LeftV
      "sar  EDX, 8
      "mov  ESI, _TextureBuffer
      "mov  EBX, 0

        InLoopTextureNoHorz :
          "mov  BH, DH
          "mov  BL, CH
          "add  ECX, InDeltaDu
          "mov  AL, [EBX+ESI]
          "add  EDX, InDeltaDv
          "mov  [EDI], AL
          inc  EDI
          dec  EBP
          jnz  InLoopTextureNoHorz

      pop  ESI

      NextRowTextureNoHorzNoClip :

      "mov  EAX, _LeftU
      "mov  EBX, _LeftV
      "add  EAX, _LeftDu
      "add  EBX, _LeftDv
      "mov  _LeftU, EAX
      "mov  _LeftV, EBX

      "mov  EAX, _RightU
      "mov  EBX, _RightV
      "add  EAX, _RightDu
      "add  EBX, _RightDv
      "mov  _RightU, EAX
      "mov  _RightV, EBX

      dec  ESI
      jnz  LoopOutTextureNoHorz
      jmp  EndLoopOutTextureNoHorz

  DrawTextureNoHorzClip :
    "cld
    "mov  ESI, LoopCount
    "cmp  ESI, 0
    "jle  EndLoopOutTextureNoHorz
    "adc  EAX, 0        ; Make sure the loop starts with U pipe
    nop          

    LoopOutClippedTextureNoHorz :
      "mov  EBX, _LeftX    ; U
      "mov  EAX, EBX        ; U
      "add  EBX, _LeftDx   ; V
      "sar  EAX, 16         ; U EAX is the Left X
      "mov  _LeftX, EBX    ; V

      "mov  EDX, _RightX   ; U
      "mov  ECX, EDX        ; U
      "add  EDX, _RightDx  ; V
      "sar  ECX, 16         ; U ECX is the Right X
      "mov  _RightX, EDX   ; V

      "mov  EBX, _DestBuffer  ; U
      "mov  EDI, EBX           ; U
      "add  EBX, _"addDest     ; V
      "mov  _DestBuffer, EBX  ; U

      "mov  TempLen, ECX
      sub  TempLen, EAX
      inc  TempLen
      "mov  EBX, 0

        ; Check for Easy reject
        "cmp  EAX, VMaxX      ; Left is greater than MaxX
        jg   NextRowTextureNoHorz
        "cmp  ECX, VMinX      ; Right is smaller than MinX
        jl   NextRowTextureNoHorz

        ; Check for Left
        "cmp  EAX, VMinX
        jge  CheckRightTextureNoHorz
          "mov  EBX, VMinX
          sub  EBX, EAX
          "mov  EAX, VMinX    ; Set Left to MinX

        ; Check for Right
      CheckRightTextureNoHorz :
        "cmp  ECX, VMaxX
        "jle  StartTextureNoHorz
        "mov  ECX, VMaxX    ; Set Right to MaxX

    StartTextureNoHorz :
      sub  ECX, EAX
      inc  ECX

      "cmp  ECX, 0
      "jle  NextRowTextureNoHorz

      "add  EDI, EAX

      "mov  EBP, TempLen
      "shl  EBP, 2
      "add  EBP, _DivTable
      fld  dword ptr [EBP]
      
      "mov  EBP, ECX      ; EBP is the loop
      "mov  TempLen, EBX

      "mov  EAX, _LeftU
      "mov  EDX, _RightU         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDu, EDX
      fild InDeltaDu      
      fmul st, st(1)
      fistp InDeltaDu
      
      "mov  EAX, _LeftV    
      "mov  EDX, _RightV         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDv, EDX
      fild InDeltaDv      
      fmul st, st(1)
      fistp InDeltaDv

      fstp  DummyFloat

      push ESI

      "mov  EAX, InDeltaDu
      imul TempLen
      "mov  ECX, _LeftU
      "sar  ECX, 8
      "add  ECX, EAX

      "mov  EAX, InDeltaDv
      imul TempLen
      "mov  EDX, _LeftV
      "sar  EDX, 8
      "add  EDX, EAX

      "mov  ESI, _TextureBuffer
      "mov  EBX, 0

        InLoopClippedTextureNoHorz :
          "mov  BH, DH
          "mov  BL, CH
          "add  ECX, InDeltaDu
          "mov  AL, [EBX+ESI]
          "add  EDX, InDeltaDv
          "mov  [EDI], AL
          inc  EDI
          dec  EBP
          jnz  InLoopClippedTextureNoHorz

      pop  ESI

      NextRowTextureNoHorz : 
        "mov  EAX, _LeftU
        "mov  EBX, _LeftV
        "add  EAX, _LeftDu
        "add  EBX, _LeftDv
        "mov  _LeftU, EAX
        "mov  _LeftV, EBX

        "mov  EAX, _RightU
        "mov  EBX, _RightV
        "add  EAX, _RightDu
        "add  EBX, _RightDv
        "mov  _RightU, EAX
        "mov  _RightV, EBX

        dec  ESI
      jnz  LoopOutClippedTextureNoHorz

  EndLoopOutTextureNoHorz :

  popad
} // End asm
} // End of _DrawTextureNoHorz


// VOID _DrawTextureFlatHorz ( LONG Color, LONG LoopCount, LONG SkipRow, LONG SideClipped )
//
// EAX = Color, EDX = LoopCount, EBX = SkipRow, ECX = SideClipped

VOID _DrawTextureFlatHorz ( LONG nColor, LONG nLoopCount, 
                                                    LONG SkipRow, LONG SideClipped )
{
_asm {
  pushad

  "mov EAX, nColor
  "mov EDX, nLoopCount
  "mov EBX, SkipRow
  "mov ECX, SideClipped

  sub  EDX, EBX
  "mov  LoopCount, EDX

  "cmp  EBX, 0
  je   CheckClippedTextureFlatHorz 

    "mov  EAX, _LeftDx
    imul  EBX
    "add  _LeftX, EAX

    "mov  EAX, _RightDx
    imul  EBX
    "add  _RightX, EAX

    "mov  EAX, _LeftDu
    imul  EBX
    "add  _LeftU, EAX

    "mov  EAX, _RightDu
    imul  EBX
    "add  _RightU, EAX

    "mov  EAX, _LeftDv
    imul  EBX
    "add  _LeftV, EAX

    "mov  EAX, _RightDv
    imul  EBX
    "add  _RightV, EAX

    "mov  EAX, _"addDest
    imul  EBX
    "add  _DestBuffer, EAX

  CheckClippedTextureFlatHorz :
    "cmp  ECX, 0
    jne  DrawTextureFlatHorzClip

  DrawTextureFlatHorzNoClip :
    "cld
    "mov  ESI, LoopCount
    "cmp  ESI, 0
    "jle  EndLoopOutTextureFlatHorz
    "adc  EAX, 0        ; Make sure the loop starts with U pipe
    nop          

    LoopOutTextureFlatHorz :
      "mov  EBX, _LeftX    ; U
      "mov  EAX, EBX        ; U
      "add  EBX, _LeftDx   ; V
      "sar  EAX, 16         ; U EAX is the Left X
      "mov  _LeftX, EBX    ; V

      "mov  EDX, _RightX   ; U
      "mov  ECX, EDX        ; U
      "add  EDX, _RightDx  ; V
      "sar  ECX, 16         ; U ECX is the Right X
      "mov  _RightX, EDX   ; V

      "mov  EBX, _DestBuffer  ; U
      "mov  EDI, EBX           ; U
      "add  EBX, _"addDest     ; V
      sub  ECX, EAX           ; U

      "mov  _DestBuffer, EBX  ; V

      "add  EDI, EAX           ; U
      inc  ECX                ; V

      "cmp  ECX, 0
      "jle  NextRowTextureFlatHorzNoClip

      "mov  EBP, ECX
      "shl  EBP, 2
      "add  EBP, _DivTable
      fld  dword ptr [EBP]
      
      "mov  EBP, ECX      ; EBP is the loop

      "mov  EAX, _LeftU    
      "mov  EDX, _RightU         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDu, EDX
      fild InDeltaDu      
      fmul st, st(1)
      fistp InDeltaDu
      
      "mov  EAX, _LeftV    
      "mov  EDX, _RightV         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDv, EDX
      fild InDeltaDv      
      fmul st, st(1)
      fistp InDeltaDv

      fstp DummyFloat

      push ESI

      "mov  ECX, _LeftU
      "mov  EDX, _LeftV
      "sar  ECX, 8
      "sar  EDX, 8

      "mov  EAX, _LeftI
      "sar  EAX, 8
      "mov  ESI, _ShadeBuffer
      
        InLoopTextureFlatHorz :
          "mov  EBX, 0
          "mov  BH, DH
          "mov  BL, CH
          "add  ECX, InDeltaDu
          "add  EBX, _TextureBuffer
          "mov  AL, [EBX]
          "add  EDX, InDeltaDv
          "mov  BL, [ESI+EAX]
          "mov  [EDI], BL
          inc  EDI
          dec  EBP
          jnz  InLoopTextureFlatHorz
    
      pop  ESI

      NextRowTextureFlatHorzNoClip : 
        "mov  EAX, _LeftU
        "mov  EBX, _LeftV
        "add  EAX, _LeftDu
        "add  EBX, _LeftDv
        "mov  _LeftU, EAX
        "mov  _LeftV, EBX

        "mov  EAX, _RightU
        "mov  EBX, _RightV
        "add  EAX, _RightDu
        "add  EBX, _RightDv
        "mov  _RightU, EAX
        "mov  _RightV, EBX

        dec  ESI
      jnz  LoopOutTextureFlatHorz
      jmp  EndLoopOutTextureFlatHorz

  DrawTextureFlatHorzClip :
    "cld
    "mov  ESI, LoopCount
    "cmp  ESI, 0
    "jle  EndLoopOutTextureFlatHorz
    "adc  EAX, 0        ; Make sure the loop starts with U pipe
    nop          

    LoopOutClippedTextureFlatHorz :
      "mov  EBX, _LeftX    ; U
      "mov  EAX, EBX        ; U
      "add  EBX, _LeftDx   ; V
      "sar  EAX, 16         ; U EAX is the Left X
      "mov  _LeftX, EBX    ; V

      "mov  EDX, _RightX   ; U
      "mov  ECX, EDX        ; U
      "add  EDX, _RightDx  ; V
      "sar  ECX, 16         ; U ECX is the Right X
      "mov  _RightX, EDX   ; V

      "mov  EBX, _DestBuffer  ; U
      "mov  EDI, EBX           ; U
      "add  EBX, _"addDest     ; V
      "mov  _DestBuffer, EBX  ; U

      "mov  TempLen, ECX
      sub  TempLen, EAX
      inc  TempLen
      "mov  EBX, 0

        ; Check for Easy reject
        "cmp  EAX, VMaxX      ; Left is greater than MaxX
        jg   NextRowTextureFlatHorz
        "cmp  ECX, VMinX      ; Right is smaller than MinX
        jl   NextRowTextureFlatHorz

        ; Check for Left
        "cmp  EAX, VMinX
        jge  CheckRightTextureFlatHorz
          "mov  EBX, VMinX
          sub  EBX, EAX
          "mov  EAX, VMinX    ; Set Left to MinX

        ; Check for Right
        CheckRightTextureFlatHorz :
          "cmp  ECX, VMaxX
          "jle  StartTextureFlatHorz
          "mov  ECX, VMaxX    ; Set Right to MaxX

    StartTextureFlatHorz :
      sub  ECX, EAX
      inc  ECX
      "add  EDI, EAX

      "cmp  ECX, 0
      "jle  NextRowTextureFlatHorz

      "mov  EBP, TempLen
      "shl  EBP, 2
      "add  EBP, _DivTable
      fld  dword ptr [EBP]

      "mov  EBP, ECX      ; EBP is the loop

      "mov  ECX, TempLen
      "mov  TempLen, EBX    ; TempLen is now the skip pixel in x-direction

      "mov  EAX, _LeftU    
      "mov  EDX, _RightU         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDu, EDX
      fild InDeltaDu      
      fmul st, st(1)
      fistp InDeltaDu
      
      "mov  EAX, _LeftV    
      "mov  EDX, _RightV         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDv, EDX
      fild InDeltaDv      
      fmul st, st(1)
      fistp InDeltaDv

      fstp DummyFloat

      push ESI

      "mov  EAX, InDeltaDu
      imul TempLen
      "mov  ECX, _LeftU
      "sar  ECX, 8
      "add  ECX, EAX

      "mov  EAX, InDeltaDv
      imul TempLen
      "mov  EDX, _LeftV
      "sar  EDX, 8
      "add  EDX, EAX

      "mov  EAX, _LeftI
      "sar  EAX, 8
      "mov  ESI, _ShadeBuffer
      
        InLoopClippedTextureFlatHorz :
          "mov  EBX, 0
          "mov  BH, DH
          "mov  BL, CH
          "add  ECX, InDeltaDu
          "add  EBX, _TextureBuffer
          "mov  AL, [EBX]
          "add  EDX, InDeltaDv
          "mov  BL, [ESI+EAX]
          "mov  [EDI], BL
          inc  EDI
          dec  EBP
          jnz  InLoopClippedTextureFlatHorz
    
      pop  ESI

      NextRowTextureFlatHorz : 
        "mov  EAX, _LeftU
        "mov  EBX, _LeftV
        "add  EAX, _LeftDu
        "add  EBX, _LeftDv
        "mov  _LeftU, EAX
        "mov  _LeftV, EBX

        "mov  EAX, _RightU
        "mov  EBX, _RightV
        "add  EAX, _RightDu
        "add  EBX, _RightDv
        "mov  _RightU, EAX
        "mov  _RightV, EBX

        dec  ESI
      jnz  LoopOutClippedTextureFlatHorz

  EndLoopOutTextureFlatHorz :

  popad
} // End asm
} // End of _DrawTextureFlatHorz


// VOID _DrawTextureGrdHorz ( LONG Color, LONG LoopCount, LONG SkipRow, LONG SideClipped )
//
// EAX = Color, EDX = LoopCount, EBX = SkipRow, ECX = SideClipped

VOID _DrawTextureGrdHorz ( LONG nColor, LONG nLoopCount, 
                                                   LONG SkipRow, LONG SideClipped )
{
_asm {
  pushad

  "mov EAX, nColor
  "mov EDX, nLoopCount
  "mov EBX, SkipRow
  "mov ECX, SideClipped

  "mov  Color, EAX

  sub  EDX, EBX
  "mov  LoopCount, EDX

  "cmp  EBX, 0
  je   CheckClippedTextureGrdHorz 

    "mov  EAX, _LeftDx
    imul  EBX
    "add  _LeftX, EAX

    "mov  EAX, _RightDx
    imul  EBX
    "add  _RightX, EAX

    "mov  EAX, _LeftDu
    imul  EBX
    "add  _LeftU, EAX

    "mov  EAX, _RightDu
    imul  EBX
    "add  _RightU, EAX

    "mov  EAX, _LeftDv
    imul  EBX
    "add  _LeftV, EAX

    "mov  EAX, _RightDv
    imul  EBX
    "add  _RightV, EAX

    "mov  EAX, _LeftDI
    imul  EBX
    "add  _LeftI, EAX

    "mov  EAX, _RightDI
    imul  EBX
    "add  _RightI, EAX

    "mov  EAX, _"addDest
    imul  EBX
    "add  _DestBuffer, EAX

  CheckClippedTextureGrdHorz :
    "cmp  ECX, 0
    jne  DrawTextureGrdHorzClip

  DrawTextureGrdHorzNoClip :
    "cld
    "mov  ESI, LoopCount
    "cmp  ESI, 0
    "jle  EndLoopOutTextureGrdHorz
    "adc  EAX, 0        ; Make sure the loop starts with U pipe
    nop          

    LoopOutTextureGrdHorz :
      "mov  EBX, _LeftX    ; U
      "mov  EAX, EBX        ; U
      "add  EBX, _LeftDx   ; V
      "sar  EAX, 16         ; U EAX is the Left X
      "mov  _LeftX, EBX    ; V

      "mov  EDX, _RightX   ; U
      "mov  ECX, EDX        ; U
      "add  EDX, _RightDx  ; V
      "sar  ECX, 16         ; U ECX is the Right X
      "mov  _RightX, EDX   ; V

      "mov  EBX, _DestBuffer  ; U
      "mov  EDI, EBX           ; U
      "add  EBX, _"addDest     ; V
      sub  ECX, EAX           ; U

      "mov  _DestBuffer, EBX  ; V

      "add  EDI, EAX           ; U
      inc  ECX                ; V

      "cmp  ECX, 0
      "jle  NextRowTextureGrdHorzNoClip

      "mov  EBP, ECX
      "shl  EBP, 2
      "add  EBP, _DivTable
      fld  dword ptr [EBP]
      
      "mov  EBP, ECX      ; EBP is the loop

      "mov  EAX, _LeftI    ; U
      "mov  EDX, _RightI   ; U      
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  EAX, EDX
      "sar  EDX, 01Fh
      idiv ECX
      "mov  InDeltaDI, EAX

      "mov  EAX, _LeftU
      "mov  EDX, _RightU         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDu, EDX
      fild InDeltaDu      
      fmul st, st(1)
      fistp InDeltaDu
      
      "mov  EAX, _LeftV    
      "mov  EDX, _RightV         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDv, EDX
      fild InDeltaDv      
      fmul st, st(1)
      fistp InDeltaDv

      fstp DummyFloat

      push ESI
      
      "mov  ECX, _LeftU
      "mov  EDX, _LeftV
      "mov  ESI, _LeftI
      "sar  ECX, 8
      "sar  EDX, 8
      "sar  ESI, 8
      
        InLoopTextureGrdHorz :
          "mov  EBX, 0
          "mov  BH, DH
          "mov  BL, CH
          "add  ECX, InDeltaDu
          "add  EBX, _TextureBuffer
          "mov  EAX, ESI
          "mov  AL, [EBX]
          "add  EDX, InDeltaDv
          "add  EAX, _ShadeBuffer
          "mov  BL, [EAX]
          "add  ESI, InDeltaDI
          "mov  [EDI], BL
          inc  EDI
          dec  EBP
          jnz  InLoopTextureGrdHorz
   
      pop  ESI

      NextRowTextureGrdHorzNoClip :
        "mov  EAX, _LeftU
        "mov  EBX, _LeftV
        "add  EAX, _LeftDu
        "add  EBX, _LeftDv
        "mov  _LeftU, EAX
        "mov  _LeftV, EBX

        "mov  EAX, _RightU
        "mov  EBX, _RightV
        "add  EAX, _RightDu
        "add  EBX, _RightDv
        "mov  _RightU, EAX
        "mov  _RightV, EBX

        "mov  EAX, _LeftI
        "mov  EBX, _RightI
        "add  EAX, _LeftDI
        "add  EBX, _RightDI
        "mov  _LeftI, EAX
        "mov  _RightI, EBX

        dec  ESI
      jnz  LoopOutTextureGrdHorz
      jmp  EndLoopOutTextureGrdHorz

  DrawTextureGrdHorzClip :
    "cld
    "mov  ESI, LoopCount
    "cmp  ESI, 0
    "jle  EndLoopOutTextureGrdHorz
    "adc  EAX, 0        ; Make sure the loop starts with U pipe
    nop          

    LoopOutClippedTextureGrdHorz :
      "mov  EBX, _LeftX    ; U
      "mov  EAX, EBX        ; U
      "add  EBX, _LeftDx   ; V
      "sar  EAX, 16         ; U EAX is the Left X
      "mov  _LeftX, EBX    ; V

      "mov  EDX, _RightX   ; U
      "mov  ECX, EDX        ; U
      "add  EDX, _RightDx  ; V
      "sar  ECX, 16         ; U ECX is the Right X
      "mov  _RightX, EDX   ; V

      "mov  EBX, _DestBuffer  ; U
      "mov  EDI, EBX           ; U
      "add  EBX, _"addDest     ; V
      "mov  _DestBuffer, EBX  ; U

      "mov  TempLen, ECX
      sub  TempLen, EAX
      inc  TempLen
      "mov  EBX, 0

        ; Check for Easy reject
        "cmp  EAX, VMaxX      ; Left is greater than MaxX
        jg   NextRowTextureGrdHorz
        "cmp  ECX, VMinX      ; Right is smaller than MinX
        jl   NextRowTextureGrdHorz

        ; Check for Left
        "cmp  EAX, VMinX
        jge  CheckRightTextureGrdHorz
          "mov  EBX, VMinX
          sub  EBX, EAX
          "mov  EAX, VMinX    ; Set Left to MinX

        ; Check for Right
        CheckRightTextureGrdHorz :
          "cmp  ECX, VMaxX
          "jle  StartTextureGrdHorz
          "mov  ECX, VMaxX    ; Set Right to MaxX

    StartTextureGrdHorz :
      sub  ECX, EAX
      inc  ECX
      "add  EDI, EAX

      "cmp  ECX, 0
      "jle  NextRowTextureGrdHorz

      "mov  EBP, TempLen
      "shl  EBP, 2
      "add  EBP, _DivTable
      fld  dword ptr [EBP]

      "mov  EBP, ECX      ; EBP is the loop

      "mov  ECX, TempLen
      "mov  TempLen, EBX    ; TempLen is now the skip pixel in x-direction

      "mov  EAX, _LeftI    ; U
      "mov  EDX, _RightI   ; U      
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  EAX, EDX
      "sar  EDX, 01Fh
      idiv ECX
      "mov  InDeltaDI, EAX

      "mov  EAX, _LeftU    
      "mov  EDX, _RightU         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDu, EDX
      fild InDeltaDu      
      fmul st, st(1)
      fistp InDeltaDu
      
      "mov  EAX, _LeftV    
      "mov  EDX, _RightV         
      sub  EDX, EAX
      "sar  EDX, 8
      "mov  InDeltaDv, EDX
      fild InDeltaDv      
      fmul st, st(1)
      fistp InDeltaDv

      fstp DummyFloat

      push ESI

      "mov  EAX, InDeltaDu
      imul TempLen
      "mov  ECX, _LeftU
      "sar  ECX, 8
      "add  ECX, EAX

      "mov  EAX, InDeltaDI
      imul TempLen
      "mov  ESI, _LeftI
      "sar  ESI, 8
      "add  ESI, EAX
      
      "mov  EAX, InDeltaDv
      imul TempLen
      "mov  EDX, _LeftV
      "sar  EDX, 8
      "add  EDX, EAX

        InLoopClippedTextureGrdHorz :
          "mov  EBX, 0
          "mov  BH, DH
          "mov  BL, CH
          "add  ECX, InDeltaDu
          "add  EBX, _TextureBuffer
          "mov  EAX, ESI
          "mov  AL, [EBX]
          "add  EDX, InDeltaDv
          "add  EAX, _ShadeBuffer
          "mov  BL, [EAX]
          "add  ESI, InDeltaDI
          "mov  [EDI], BL
          inc  EDI
          dec  EBP
          jnz  InLoopClippedTextureGrdHorz
    
      pop  ESI

      NextRowTextureGrdHorz : 
        "mov  EAX, _LeftU
        "mov  EBX, _LeftV
        "add  EAX, _LeftDu
        "add  EBX, _LeftDv
        "mov  _LeftU, EAX
        "mov  _LeftV, EBX
   
        "mov  EAX, _RightU
        "mov  EBX, _RightV
        "add  EAX, _RightDu
        "add  EBX, _RightDv
        "mov  _RightU, EAX
        "mov  _RightV, EBX

        "mov  EAX, _LeftI
        "mov  EBX, _RightI
        "add  EAX, _LeftDI
        "add  EBX, _RightDI
        "mov  _LeftI, EAX
        "mov  _RightI, EBX

        dec  ESI
      jnz  LoopOutClippedTextureGrdHorz

  EndLoopOutTextureGrdHorz :

  popad
} // End asm
} // End of _DrawTextureGrdHorz


