;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                                                                         ;
; Real 2 SuperReal Demo June/July 1995                                    ;
; SuperReal (our first SVGA demo)                                         ;
;                                                                         ;
; trapezoid filler WITH Z Clipping (Gourand shaded)                       ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ideal
p386
model flat
stack 2048
codeseg

extrn debug           : near
Zero_Addr             dd ?
Environment_Address   dd ?
PSP_Address           dd ?
_0B8000h              dd ?
_0A0000h              dd ?
DOS_Ptr               dd ?

poly_l_clip           dd 0
poly_r_clip           dd 320
poly_t_clip           dd 0
poly_b_clip           dd 200

old_l_incr_t          dd ?
old_r_incr_t          dd ?
old_cl_incr_t         dd ?
old_cr_incr_t         dd ?

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                                                                         ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc key_pressed2
  push   esi
  mov    esi,[Zero_Addr]
  add    esi,41ah
  mov    ax,[esi]
  cmp    ax,[word esi+2]
  jne    @@l
  pop    esi
  clc
  ret
@@l:
  movzx  eax,ax
  add    eax,400h
  add    eax,[Zero_Addr]
  mov    ax,[word eax]
  pop    esi
  stc
  ret
endp

last_get_key          db ?

proc get_key
@@l:
  call   key_pressed2
  jnc    @@l
  mov    eax,0
  int    16h
  mov    [last_get_key],al
  ret
endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                                                                         ;
;void GZ_trapezoid(long x1,long x2,long l_incr,long r_incr,               ;
;                  long y1,long y3,                                       ;
;                  long c1,long c2,long cl_incr,long cr_incr,             ;
;                  long hold)                                             ;
;                                                                         ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
HOLD_OFF              = 0
HOLD_LEFT             = 1
HOLD_RIGHT            = 2

struc GZ_trape_sk
  caller              dd ?
  TARGET_WIDTH        dd ?
  hold                dd ?
  cr_incr             dd ?
  cl_incr             dd ?
  c2                  dd ?
  c1                  dd ?
  y3                  dd ?
  y1                  dd ?
  r_incr              dd ?
  l_incr              dd ?
  x2                  dd ?
  x1                  dd ?
ends

proc GZ_trapezoid
  mov    ebp,esp

;height = y3 - y1;
  mov    eax,[ebp+GZ_trape_sk.y3]
  sub    eax,[ebp+GZ_trape_sk.y1]
  mov    [@@height],eax

;  if(hold == HOLD_OFF)
;  {
;    l_incr_t = x1 << 16;
;    r_incr_t = x2 << 16;
;
;    cl_incr_t = c1 << 16;
;    cr_incr_t = c2 << 16;
;
;  }
  cmp    [ebp+GZ_trape_sk.hold],HOLD_OFF
  jne    @@holding

  mov    eax,[ebp+GZ_trape_sk.x1]
  sal    eax,16
  mov    [@@l_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.x2]
  sal    eax,16
  mov    [@@r_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.c1]
  sal    eax,16
  mov    [@@cl_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.c2]
  sal    eax,16
  mov    [@@cr_incr_t],eax
  jmp    @@end_holdsetup
@@holding:
;  else
;  {
;    if(hold == HOLD_LEFT)
;    {
;      l_incr_t = old_l_incr_t;
;      r_incr_t = x2 << 16;
;
;      cl_incr_t = old_cl_incr_t;
;      cr_incr_t = c2 << 16;
;    }
  cmp    [ebp+GZ_trape_sk.hold],HOLD_LEFT
  jne    @@hold_right

  mov    eax,[old_l_incr_t]
  mov    [@@l_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.x2]
  sal    eax,16
  mov    [@@r_incr_t],eax

  mov    eax,[old_cl_incr_t]
  mov    [@@cl_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.c2]
  sal    eax,16
  mov    [@@cr_incr_t],eax

  jmp    @@end_holdsetup
@@hold_right:
;    else
;    {
;      r_incr_t = old_r_incr_t;
;      l_incr_t = x1 << 16;
;
;      cr_incr_t = old_cr_incr_t;
;      cl_incr_t = c1 << 16;
;    }
;  }
  mov    eax,[old_r_incr_t]
  mov    [@@r_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.x1]
  sal    eax,16
  mov    [@@l_incr_t],eax

  mov    eax,[old_cr_incr_t]
  mov    [@@cr_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.c1]
  sal    eax,16
  mov    [@@cl_incr_t],eax
@@end_holdsetup:

;  if(y3 < poly_t_clip)
;  {
;    old_l_incr_t = l_incr_t += l_incr * height;
;    old_r_incr_t = r_incr_t += r_incr * height;
;
;    old_cl_incr_t = cl_incr_t += cl_incr * height;
;    old_cr_incr_t = cr_incr_t += cr_incr * height;
;    return;
;  }
  mov    eax,[ebp+GZ_trape_sk.y3]
  cmp    eax,[poly_t_clip]
  jge    @@dont_t_clip

  mov    eax,[ebp+GZ_trape_sk.l_incr]
  imul   eax,[@@height]
  add    eax,[@@l_incr_t]
  mov    [old_l_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.r_incr]
  imul   eax,[@@height]
  add    eax,[@@r_incr_t]
  mov    [old_r_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.cl_incr]
  imul   eax,[@@height]
  add    eax,[@@cl_incr_t]
  mov    [old_cl_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.cr_incr]
  imul   eax,[@@height]
  add    eax,[@@cr_incr_t]
  mov    [old_cr_incr_t],eax

  ret
@@dont_t_clip:

;  if(y1 < poly_t_clip)
;  {
;    long t_clip_d = poly_t_clip - y1;
;    height -= t_clip_d;
;    vline = poly_t_clip;
;    l_incr_t += l_incr * t_clip_d;
;    r_incr_t += r_incr * t_clip_d;
;
;    cl_incr_t += cl_incr * t_clip_d;
;    cr_incr_t += cr_incr * t_clip_d;
;  }
  mov    ebx,[ebp+GZ_trape_sk.y1]
  cmp    ebx,[poly_t_clip]
  jge    @@dont_t_clip2

  mov    ecx,[poly_t_clip]
  sub    ecx,ebx                  ;[ebp+GZ_trape_sk.y1]
  sub    [@@height],ecx
  mov    eax,[poly_t_clip]
  mov    [@@vline],eax

  mov    eax,[ebp+GZ_trape_sk.l_incr]
  imul   ecx
  add    [@@l_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.r_incr]
  imul   ecx
  add    [@@r_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.cl_incr]
  imul   ecx
  add    [@@cl_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.cr_incr]
  imul   ecx
  add    [@@cr_incr_t],eax

  jmp    @@dont_t_clip2_end
@@dont_t_clip2:
;  else
;  {
;    vline = y1;
;  }
  mov    eax,[ebp+GZ_trape_sk.y1]
  mov    [@@vline],eax
@@dont_t_clip2_end:

;  vline = vline * SCREEN_X;
  mov    eax,[ebp+GZ_trape_sk.TARGET_WIDTH]
  mul    [@@vline]
  add    eax,[_0A0000h]
  mov    [@@vline],eax

;  if(y3 > poly_b_clip)
;  {
;    height -= y3 - poly_b_clip;
;  }
  mov    eax,[ebp+GZ_trape_sk.y3]
  cmp    eax,[poly_b_clip]
  jle    @@dont_b_clip
  sub    eax,[poly_b_clip]
  sub    [@@height],eax
@@dont_b_clip:

;  for(line = 0;line < height; line++)
;  {
@@paint_line:

;    xl = l_incr_t >> 16;
;    xr = r_incr_t >> 16;
;    cl = cl_incr_t >> 16;
;    cr = cr_incr_t >> 16;

  mov    eax,[@@l_incr_t]
  sar    eax,16
  mov    [@@xl],eax

  mov    eax,[@@r_incr_t]
  sar    eax,16
  mov    [@@xr],eax

  mov    eax,[@@cl_incr_t]
  sar    eax,16
  mov    [@@cl],eax

  mov    eax,[@@cr_incr_t]
  sar    eax,16
  mov    [@@cr],eax

;    if(xr > poly_l_clip)
;    {
  mov    ebx,[@@xr]
  cmp    ebx,[poly_l_clip]
  jle    @@ignore_line

;      if(xl < poly_r_clip)
;      {
  mov    ecx,[@@xl]
  cmp    ecx,[poly_r_clip]
  jge    @@ignore_line

;        if(xl < poly_l_clip)
;        {
;          xl = poly_l_clip;
;        }
  cmp    ecx,[poly_l_clip]
  jge    @@dont_l_clip_xl
  mov    ecx,[poly_l_clip]
@@dont_l_clip_xl:

;        if(xr > poly_r_clip)
;        {
;          xr = poly_r_clip;
;        }
  cmp    ebx,[poly_r_clip]
  jle    @@dont_r_clip_xr
  mov    ebx,[poly_r_clip]
@@dont_r_clip_xr:

;        long Crun = cl_incr_t;
  mov    eax,[@@cl_incr_t]
  mov    [@@Crun],eax

;        long x_diff = xr - xl + 2;
  sub    ebx,ecx
  add    ebx,2
  mov    [@@x_diff],ebx

;        long Crun_grad = 0;
;        if(x_diff)
;        {
;          Crun_grad = compute_Zgrad(cl,cr,x_diff);
;        }
  mov    [@@Crun_grad],0
  or     ebx,ebx
  jz     @@dont_set_cgrad

;long compute_Zgrad(long z1, long z2, long run)
;{
;  long slope = ((z2 - z1) << 16) / run;
;  return slope;
;}
  mov    eax,[@@cr]
  sub    eax,[@@cl]
  cdq
  shld   eax,edx,16
  idiv   ebx
  mov    [@@Crun_grad],eax
@@dont_set_cgrad:
;        for(xl;xl < xr;xl++)
;        {
;          long c = Crun >> 16;
;          write_video(vline+xl,c);
;          Crun += Crun_grad;
;        }
  mov    ecx,[@@xr]
  sub    ecx,[@@xl]
  mov    edi,[@@vline]
  mov    edx,[@@Crun]
@@paint_x_run:
  mov    eax,edx
  sar    eax,16
  mov    [edi],al
  inc    edi
  add    edx,[@@Crun_grad]
  dec    ecx
  jnz    @@paint_x_run

;      }
;    }
@@ignore_line:

;    vline += SCREEN_X;
;    l_incr_t += l_incr;
;    r_incr_t += r_incr;
;
;    cl_incr_t += cl_incr;
;    cr_incr_t += cr_incr;
  mov    eax,[ebp+GZ_trape_sk.TARGET_WIDTH]
  add    [@@vline],eax

  mov    eax,[ebp+GZ_trape_sk.l_incr]
  add    [@@l_incr_t],eax
  mov    eax,[ebp+GZ_trape_sk.r_incr]
  add    [@@r_incr_t],eax

  mov    eax,[ebp+GZ_trape_sk.cl_incr]
  add    [@@cl_incr_t],eax
  mov    eax,[ebp+GZ_trape_sk.cr_incr]
  add    [@@cr_incr_t],eax

;  }
  dec    [dword @@height]
  jnz    @@paint_line

;  old_l_incr_t = l_incr_t;
;  old_r_incr_t = r_incr_t;
;  old_cl_incr_t = cl_incr_t;
;  old_cr_incr_t = cr_incr_t;

  mov    eax,[@@l_incr_t]
  mov    [old_l_incr_t],eax
  mov    eax,[@@r_incr_t]
  mov    [old_r_incr_t],eax

  mov    eax,[@@cl_incr_t]
  mov    [old_cl_incr_t],eax
  mov    eax,[@@cr_incr_t]
  mov    [old_cr_incr_t],eax

  ret
;vars;;;;;;;;;;;;;;;;;;;;;;;;
@@vline               dd ?
@@height              dd ?
@@l_incr_t            dd ?
@@r_incr_t            dd ?
@@xl                  dd ?
@@xr                  dd ?
@@cl_incr_t           dd ?
@@cr_incr_t           dd ?
@@cl                  dd ?
@@cr                  dd ?
@@x_diff              dd ?
@@Crun                dd ?
@@Crun_grad           dd ?
endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                                                                         ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Start_gztrap:
  call   debug
  cld
  mov    eax,0EE02h      ; get DOS32 address information
  int    31h
  neg    ebx
  mov    [Zero_Addr],ebx
  add    ebx,0A0000h
  mov    [_0A0000h],ebx
  add    ebx,0B8000h-0A0000h
  mov    [_0B8000h],ebx
  mov    [Environment_Address],edi
  mov    [PSP_Address],esi

  mov    eax,13h
  int    10h

;struc GZ_trape_sk
;  save_ebp            dd ?
;  caller              dd ?
;  TARGET_WIDTH        dd ?
;  hold                dd ?
;  cr_incr             dd ?
;  cl_incr             dd ?
;  c2                  dd ?
;  c1                  dd ?
;  y3                  dd ?
;  y1                  dd ?
;  r_incr              dd ?
;  l_incr              dd ?
;  x2                  dd ?
;  x1                  dd ?
;ends

  push   0               ;x1
  push   100             ;x2
  push   00010000h       ;l_incr
  push   00020000h       ;r_incr
  push   0               ;y1
  push   100             ;y3
  push   16              ;c1
  push   20              ;c2
  push   00001000h       ;cl_incr
  push   00004000h       ;cr_incr
  push   HOLD_OFF
  push   320
  call   GZ_trapezoid
  add    esp,(size GZ_trape_sk)-4

  call   get_key

  mov    eax,3h
  int    10h
  mov    eax,4c00h
  int    21h
ends

end Start_gztrap
