
; lg3d256w.asm
;
; Copyright (c) 1996 by Toshiaki Tsuji, all rights reserved.

; Functions
PUBLIC _SetEdgeData_
PUBLIC _SetDestData_
PUBLIC _SetGradientData_
PUBLIC _SetShadeTable_ 
PUBLIC _SetTextureBuffer_ 

PUBLIC _ScanEdgeSolid_, _DrawSolidPoly_
PUBLIC _ScanEdgeSolidGouraud_, _DrawSolidGouraudPoly_
PUBLIC _ScanEdgeTexture_, _DrawTexturePoly_

.DATA
  LeftEdge  DD 0
  RightEdge DD 0
  EdgeSize  DD 0

  DestBuffer DD 0
  AddDest DD 0

  LeftX DD 0
  RightX DD 0
  RowStepX DD 0

  ExtraHt DD 0

  OneOverZdX DD 0
  OneOverZdY DD 0

  UOverZdX DD 0
  UOverZdY DD 0
  UOverZRowStep DD 0
  UOverZInStep DD 0

  VOverZdX DD 0
  VOverZdY DD 0
  VOverZRowStep DD 0
  VOverZInStep DD 0

  IOverZdX DD 0
  IOverZdY DD 0
  IOverZRowStep DD 0
  IOverZInStep DD 0
        
  HOverZdX DD 0
  HOverZdY DD 0
  HOverZRowStep DD 0
  HOverZInStep DD 0

  ShadeBuffer DD 0
  TextureBuffer DD 0

XOffset EQU  0
YOffset EQU  4
UOffset EQU  8
VOffset EQU 12
IOffset EQU 16
HOffset EQU 20
SizeOfEdge EQU 32


.CODE
.486

; _SetEdgeData ( FXPEDGE *LeftEdgePtr, FXPEDGE *RightEdgePtr, LONG EdgeSize )
;
; EAX = LeftEdgePtr, EDX = RightEdgePtr, EBX = EdgeSize

_SetEdgeData_ PROC
  mov  LeftEdge, EAX
  mov  RightEdge, EDX
  mov  EdgeSize, EBX
  ret
_SetEdgeData_ ENDP


; _SetDestData_ ( BYTE *DestBuffer, LONG AddDest )
;
; EAX = DestBuffer, EDX = AddDest

_SetDestData_ PROC
  mov DestBuffer, EAX
  mov AddDest, EDX 
  ret
_SetDestData_ ENDP


; _SetGradientData_ ( FXPGRADIENT *Gradient )
;
; EAX = Gradient

_SetGradientData_ PROC
  push ESI

  mov  ESI, EAX

  mov  EAX, [ESI+0]
  mov  OneOverZdX, EAX
  mov  EAX, [ESI+4]
  mov  OneOverZdY, EAX

  mov  EAX, [ESI+8]
  mov  UOverZdX, EAX
  mov  EAX, [ESI+12]
  mov  UOverZdY, EAX

  mov  EAX, [ESI+16]
  mov  VOverZdX, EAX
  mov  EAX, [ESI+20]
  mov  VOverZdY, EAX

  mov  EAX, [ESI+24]
  mov  IOverZdX, EAX
  mov  EAX, [ESI+28]
  mov  IOverZdY, EAX

  mov  EAX, [ESI+32]
  mov  HOverZdX, EAX
  mov  EAX, [ESI+36]
  mov  HOverZdY, EAX

  pop  ESI
  ret
_SetGradientData_ ENDP


; _SetShadeTable ( BYTE *Table )
;
; EAX = Table

_SetShadeTable_ PROC
  mov  ShadeBuffer, EAX
  ret
_SetShadeTable_ ENDP


; _SetTextureBuffer ( BYTE *Buffer )
;
; EAX = Buffer

_SetTextureBuffer_ PROC
  mov  TextureBuffer, EAX
  ret
_SetTextureBuffer_ ENDP


;***********************************************
;
; Solid, No Shading
;
;***********************************************

; FXPEDGE* _ScanEdgeSolid ( FXPPOINT2D *Point1, FXPPOINT2 *Point2,
;                           FXPEDGE *EdgePtr, LONG ExtraHt )
;
; EAX = Point1, EDX = Point2, EBX = EdgePtr, LONG ExtraHt

_ScanEdgeSolid_ PROC
  push EBP
  push EDI
  push ESI

  mov  ESI, EAX
  mov  EDI, EDX
  mov  EBP, EBX
  mov  ExtraHt, ECX

  ;  All X coords are in 16:16, Y is in Integer
  mov  ECX, dword ptr [EDI+YOffset]
  sub  ECX, dword ptr [ESI+YOffset] ; ECX is the Height

  mov  EAX, dword ptr [EDI]
  mov  EBX, dword ptr [ESI]  ; EBX is the TopX
  sub  EAX, EBX
  cdq 
  idiv ECX                   ; EAX is the StepX
   
  add  ECX, ExtraHt

  ScanEdgeSolidHtLoop :
    mov  [EBP], EBX
    add  EBX, EAX
    add  EBP, SizeOfEdge     ; FXPEDGE is 32 bytes
    dec  ECX
    jz   EndScanEdgeSolidHtLoop

    mov  [EBP], EBX
    add  EBX, EAX
    add  EBP, SizeOfEdge     ; FXPEDGE is 32 bytes
    dec  ECX
    jz   EndScanEdgeSolidHtLoop

    mov  [EBP], EBX
    add  EBX, EAX
    add  EBP, SizeOfEdge     ; FXPEDGE is 32 bytes
    dec  ECX
    jz   EndScanEdgeSolidHtLoop

    mov  [EBP], EBX
    add  EBX, EAX
    add  EBP, SizeOfEdge     ; FXPEDGE is 32 bytes
    dec  ECX
    jnz  ScanEdgeSolidHtLoop

  EndScanEdgeSolidHtLoop :

  mov  EAX, EBP
  pop  ESI
  pop  EDI
  pop  EBP
  ret
_ScanEdgeSolid_ ENDP


; _DrawSolidPoly ( LONG Color, LONG Intensity, LONG Skip, LONG LoopCount )
;
; EAX = Color, EDX = Intensity, EBX = Skip, ECX =LoopCount

_DrawSolidPoly_ PROC
  push EBP
  push EDI
  push ESI

  mov  AH, AL
  mov  EBX, EAX
  shl  EAX, 16
  mov  AX, BX

  DrawSolidPolyHtLoop :
    cld
    mov  ESI, LeftEdge
    mov  EBP, RightEdge

    mov  EBX, dword ptr [ESI]
    mov  EDX, dword ptr [EBP]
    add  ESI, SizeOfEdge           ; FXPEDGE is 32 bytes
    add  EBP, SizeOfEdge           ; FXPEDGE is 32 bytes
    sar  EBX, 16
    sar  EDX, 16

    mov  LeftEdge, ESI
    mov  RightEdge, EBP

    push ECX

    mov  ECX, DestBuffer
    mov  EDI, ECX
    add  ECX, AddDest
    add  EDI, EBX
    mov  DestBuffer, ECX

    mov  ECX, EDX
    sub  ECX, EBX
    inc  ECX
    mov  EDX, ECX

    and  EDX, 03h
    shr  ECX, 2

    rep  stosd
    mov  ECX, EDX
    rep  stosb

    pop  ECX
    loop DrawSolidPolyHtLoop

  pop  ESI
  pop  EDI
  pop  EBP
  ret
_DrawSolidPoly_ ENDP

;***********************************************
;
; Solid, Gouraud Shading
;
;***********************************************

; FXPEDGE* _ScanEdgeSolidGouraud ( FXPPOINT2D *Point1, FXPPOINT2 *Point2,
;                                  FXPEDGE *EdgePtr, LONG ExtraHt )
;
; EAX = Point1, EDX = Point2, EBX = EdgePtr, LONG ExtraHt

_ScanEdgeSolidGouraud_ PROC
  push EBP
  push EDI
  push ESI

  mov  ESI, EAX
  mov  EDI, EDX
  mov  EBP, EBX
  mov  ExtraHt, ECX

  ;  All X coords are in 16:16, Y is in Integer
  mov  ECX, dword ptr [EDI+YOffset]
  sub  ECX, dword ptr [ESI+YOffset] ; ECX is the Height

  mov  EAX, dword ptr [EDI]
  mov  EBX, dword ptr [ESI]  ; EBX is the TopX
  sub  EAX, EBX
  cdq 
  idiv ECX                   ; EAX is the StepX

  mov  RowStepX, EAX

  mov  EDX, IOverZdX
  imul EDX
  shrd EAX, EDX, 16
  add  EAX, IOverZdY         ; EAX is the StepI
  mov  IOverZRowStep, EAX    

  add  ECX, ExtraHt

  mov  ESI, dword ptr [ESI+IOffset]  ; ESI is the TopI
  mov  EAX, RowStepX
  mov  EDX, IOverZRowStep

  ScanEdgeSolidGouraudHtLoop :
    mov  [EBP], EBX
    add  EBX, EAX
    mov  [EBP+IOffset], ESI
    add  ESI, EDX
    add  EBP, SizeOfEdge       ; FXPEDGE is 32 bytes
    dec  ECX
    jnz  ScanEdgeSolidGouraudHtLoop

  mov  EAX, EBP
  pop  ESI
  pop  EDI
  pop  EBP
  ret
_ScanEdgeSolidGouraud_ ENDP


; _DrawSolidGouraudPoly ( LONG Color, LONG Intensity, LONG Skip, LONG LoopCount )
;
; EAX = Color, EDX = Intensity, EBX = Skip, ECX =LoopCount

_DrawSolidGouraudPoly_ PROC
  push EBP
  push EDI
  push ESI

  mov  AH, AL
  mov  EBX, EAX
  shl  EAX, 16
  mov  AX, BX

  DrawSolidGouraudPolyHtLoop :
    cld
    push ECX

    mov  ESI, LeftEdge
    mov  EBP, RightEdge

    mov  EBX, dword ptr [ESI]
    mov  EDX, dword ptr [EBP]
    sar  EBX, 16
    sar  EDX, 16

    mov  ECX, DestBuffer
    mov  EDI, ECX
    add  ECX, AddDest
    add  EDI, EBX
    mov  DestBuffer, ECX

    mov  ECX, EDX
    sub  ECX, EBX
    inc  ECX          ; ECX is Width of scanline

    mov  EBX, dword ptr [ESI+IOffset] ; EBX is I in 16:16

    add  ESI, SizeOfEdge          ; FXPEDGE is 32 bytes
    add  EBP, SizeOfEdge          ; FXPEDGE is 32 bytes
    mov  LeftEdge, ESI
    mov  RightEdge, EBP

    mov  ESI, ShadeBuffer
    mov  EBP, IOverZdX

    DrawSolidGouraudPolyInLoop :
      mov  EDX, EBX
      shr  EDX, 8
      mov  DL, AH
      mov  AL, [ESI+EDX]
      add  EBX, EBP
      stosb 
      loop DrawSolidGouraudPolyInLoop 

    pop  ECX
    loop DrawSolidGouraudPolyHtLoop

  pop  ESI
  pop  EDI
  pop  EBP
  ret
_DrawSolidGouraudPoly_ ENDP


;***********************************************
;
; Texture, No Shading
;
;***********************************************

; FXPEDGE* _ScanEdgeTexture ( FXPPOINT2D *Point1, FXPPOINT2 *Point2,
;                                  FXPEDGE *EdgePtr, LONG ExtraHt )
;
; EAX = Point1, EDX = Point2, EBX = EdgePtr, LONG ExtraHt

_ScanEdgeTexture_ PROC
  push EBP
  push EDI
  push ESI

  mov  ESI, EAX
  mov  EDI, EDX
  mov  EBP, EBX
  mov  ExtraHt, ECX

  ;  All X coords are in 16:16, Y is in Integer
  mov  ECX, dword ptr [EDI+YOffset]
  sub  ECX, dword ptr [ESI+YOffset] ; ECX is the Height

  mov  EAX, dword ptr [EDI]
  mov  EBX, dword ptr [ESI]  ; EBX is the TopX
  sub  EAX, EBX
  cdq 
  idiv ECX                   ; EAX is the StepX

  mov  RowStepX, EAX

  mov  EDX, UOverZdX
  imul EDX
  shrd EAX, EDX, 16
  add  EAX, UOverZdY         ; EAX is the StepU
  mov  UOverZRowStep, EAX    

  mov  EAX, RowStepX
  mov  EDX, VOverZdX
  imul EDX
  shrd EAX, EDX, 16
  add  EAX, VOverZdY         ; EAX is the StepV
  mov  VOverZRowStep, EAX    

  add  ECX, ExtraHt

  mov  ESI, dword ptr [ESI+UOffset]  ; ESI is the TopU
  mov  EDI, dword ptr [ESI+VOffset]  ; EDI is the TopV
  mov  EAX, RowStepX
  mov  EDX, UOverZRowStep

  ScanEdgeTextureHtLoop :
    mov  [EBP], EBX
    add  EBX, EAX
    mov  [EBP+UOffset], ESI
    add  ESI, EDX
    mov  [EBP+VOffset], EDI
    add  EDI, VOverZRowStep
    add  EBP, SizeOfEdge       ; FXPEDGE is 32 bytes
    dec  ECX
    jnz  ScanEdgeTextureHtLoop

  mov  EAX, EBP
  pop  ESI
  pop  EDI
  pop  EBP
  ret
_ScanEdgeTexture_ ENDP


; _DrawTexturePoly ( LONG Color, LONG Intensity, LONG Skip, LONG LoopCount )
;
; EAX = Color, EDX = Intensity, EBX = Skip, ECX =LoopCount

_DrawTexturePoly_ PROC
  push EBP
  push EDI
  push ESI

  mov  AH, AL
  mov  EBX, EAX
  shl  EAX, 16
  mov  AX, BX

  DrawTexturePolyHtLoop :
    cld
    push ECX

    mov  ESI, LeftEdge
    mov  EBP, RightEdge

    mov  EBX, dword ptr [ESI]
    mov  EDX, dword ptr [EBP]
    sar  EBX, 16
    sar  EDX, 16

    mov  ECX, DestBuffer
    mov  EDI, ECX
    add  ECX, AddDest
    add  EDI, EBX
    mov  DestBuffer, ECX

    mov  ECX, EDX
    sub  ECX, EBX
    inc  ECX          ; ECX is Width of scanline

    mov  EBX, dword ptr [ESI+UOffset] ; EBX is U in 16:16
    mov  EDX, dword ptr [ESI+VOffset] ; EDX is V in 16:16

    add  ESI, SizeOfEdge          ; FXPEDGE is 32 bytes
    add  EBP, SizeOfEdge          ; FXPEDGE is 32 bytes
    mov  LeftEdge, ESI
    mov  RightEdge, EBP

    mov  ESI, TextureBuffer
    mov  EBP, UOverZdX
    shl  EBX, 8      ; EBX is U in 8:24
    shl  EBP, 8      ; EBP is StepU in 8:24

    DrawTexturePolyInLoop :
      mov  EAX, EDX
      shr  EAX, 16
      shld EAX, EBX, 8
      add  EDX, VOverZdX
      add  EBX, EBP
      mov  AL, [ESI+EAX]
      stosb
      dec ECX
      jz  EndDrawTexturePolyInLoop

      mov  EAX, EDX
      shr  EAX, 16
      shld EAX, EBX, 8
      add  EDX, VOverZdX
      add  EBX, EBP
      mov  AL, [ESI+EAX]
      stosb
      dec ECX
      jz  EndDrawTexturePolyInLoop

      mov  EAX, EDX
      shr  EAX, 16
      shld EAX, EBX, 8
      add  EDX, VOverZdX
      add  EBX, EBP
      mov  AL, [ESI+EAX]
      stosb
      dec ECX
      jz  EndDrawTexturePolyInLoop

      mov  EAX, EDX
      shr  EAX, 16
      shld EAX, EBX, 8
      add  EDX, VOverZdX
      add  EBX, EBP
      mov  AL, [ESI+EAX]
      stosb
      dec ECX
      jnz DrawTexturePolyInLoop

    EndDrawTexturePolyInLoop :

    pop  ECX
    dec  ECX
    jnz  DrawTexturePolyHtLoop

  pop  ESI
  pop  EDI
  pop  EBP
  ret
_DrawTexturePoly_ ENDP

END
