;this include file contains all the necessary macros for displaying
;textures.

txt_makevarl macro              ;reloads the 3d variables of the left side
.386
  movsx ebx,dyl                 ;number steps
  inc ebx
  push ecx
  push edx

  movsx eax,poly3d[bp]          ;get 3d-x
  shl eax,8                     ;lower 8 bits are "fractional" part
  mov xl_3d,eax                 ;and write
  movsx ecx,poly3d[bp+8]        ;obtain difference
  shl ecx,8
  sub eax,ecx
  neg eax
  cdq
  idiv ebx                      ;define step
  mov inc_xl,eax

  movsx eax,poly3d[bp+2]        ;get 3d-y
  shl eax,8
  mov yl_3d,eax
  movsx ecx,poly3d[bp+10d]      ;obtain difference
  shl ecx,8
  sub eax,ecx
  neg eax
  cdq
  idiv ebx                      ;define step
  mov inc_yl,eax

  movsx eax,poly3d[bp+4]        ;get 3d-z
  shl eax,8
  mov zl_3d,eax
  movsx ecx,poly3d[bp+12d]      ;obtain difference
  shl ecx,8
  sub eax,ecx
  neg eax
  cdq
  idiv ebx                      ;define step
  mov inc_zl,eax
  pop edx
  pop ecx
endm

txt_makevarr macro              ;reloads the 3d variables of the right side
.386
  push eax
  push ebx
  movsx ebx,dyr                 ;number steps
  inc ebx

  movsx eax,poly3d[bp+8]        ;get 3d-x
  shl eax,8                     ;lower 8 bits are "fractional" part
  mov xr_3d,eax                 ;and write
  movsx ecx,poly3d[bp]          ;obtain difference
  shl ecx,8
  sub eax,ecx
  neg eax
  cdq
  idiv ebx                      ;define step
  mov inc_xr,eax

  movsx eax,poly3d[bp+10d]      ;get 3d-y
  shl eax,8
  mov yr_3d,eax
  movsx ecx,poly3d[bp+2]        ;obtain difference
  shl ecx,8
  sub eax,ecx
  neg eax
  cdq
  idiv ebx                      ;define step
  mov inc_yr,eax

  movsx eax,poly3d[bp+12d]      ;get 3d-z
  shl eax,8
  mov zr_3d,eax
  movsx ecx,poly3d[bp+4]        ;obtain difference
  shl ecx,8
  sub eax,ecx
  neg eax
  cdq
  idiv ebx                      ;define step
  mov inc_zr,eax
  pop ebx
  pop eax
endm

txt_hline macro
hline_texture proc near         ;replaces "hline" procedure with textures
.386
  push es
  pusha
  mov x0,ax                     ;save coordinates for later
  mov y0,bx
  mov x1,cx
  sub cx,ax                     ;calculate number of pixels to be drawn
  jne zzok2
  inc cx
zzok2:
  mov zz,cx

  mov bp,upper_row
  mov bx,lower_row
  mov eax,xr_3d[bx]             ;determine relative x-coordinate
  movsx ecx,poly3d[2]
  shl ecx,8                     ;put in "fixed point" format
  sub eax,ecx
  mov d_y,eax
  movsx ecx,w column2[0]
  imul ecx                      ;multiply by Delta2 x
  mov esi,eax                   ;place result in temporary storage

  mov eax,xr_3d[bp]             ;determine relative y-coordinate
  movsx ecx,poly3d[0]
  shl ecx,8                     ;put in "fixed point" format
  sub eax,ecx
  mov d_x,eax
  movsx ecx,w column2[4]
  imul ecx                      ;multiply by Delta2 y
  sub eax,esi                   ;obtain difference (D1)
  cdq                           ;prepare division
  idiv dword ptr D              ;divide by main determinant
  shl eax,8
  neg eax
  mov inc_lambda1,eax           ;store for subtraction

  mov eax,d_x                   ;get relative x-coordinate
  movsx ecx,w column1[4]
  imul ecx                      ;multiply by Delta1 y
  mov esi,eax                   ;place result in temporary storage

  mov eax,d_y                   ;get relative y-coordinate
  movsx ecx,w Column1[0]
  imul ecx                      ;multiply by Delta1 x
  sub eax,esi                   ;obtain difference (D2)
  cdq                           ;prepare division
  idiv dword ptr D              ;divide by main determinant
  shl eax,8
  neg eax
  mov inc_lambda2,eax           ;store for subtraction

  mov eax,xl_3d[bx]             ;determine relative x-coordinate
  movsx ecx,poly3d[2]
  shl ecx,8                     ;put in "fixed point" format
  sub eax,ecx
  mov d_y,eax
  movsx ecx,w column2[0]
  imul ecx                      ;multiply by Delta2 x
  mov esi,eax                   ;place result in temporary storage

  mov eax,xl_3d[bp]             ;determine relative y-coordinate
  movsx ecx,poly3d[0]
  shl ecx,8                     ;put in "fixed point" format
  sub eax,ecx
  mov d_x,eax
  movsx ecx,w column2[4]
  imul ecx                      ;multiply by Delta2 y
  sub eax,esi                   ;obtain difference (D1)
  cdq                           ;prepare division
  idiv dword ptr D              ;divide by main determinant
  shl eax,8
  neg eax
  mov lambda1,eax               ;Lambda1 determined
  sub inc_lambda1,eax

  mov eax,d_x                   ;get relative x-coordinate
  movsx ecx,w column1[4]
  imul ecx                      ;multiply by Delta1 y
  mov esi,eax                   ;place result in temporary storage

  mov eax,d_y                   ;get relative y-coordinate
  movsx ecx,w column1[0]
  imul ecx                      ;multiply by Delta1 x
  sub eax,esi                   ;obtain difference (D2)
  cdq                           ;prepare division
  idiv dword ptr D              ;divide by main determinant
  neg eax
  shl eax,8
  mov lambda2,eax               ;Lambda2 determined
  sub inc_lambda2,eax

  mov ax,80d                    ;determine offset
  mov bx,y0
  mul bx
  mov bx,x0                     ;(x div 4) + y*80
  shr bx,2
  add ax,bx
  add ax,vpage
  mov di,ax
  mov ax,0a000h                 ;load VGA segment
  mov es,ax

  mov cx,x0                     ;mask start plane
  and cx,3
  mov ax,1
  shl ax,cl                     ;set corresponding bit
  mov b plane+1,al
  shl al,4                      ;and extend to high nibble
  or b plane+1,al

  movsx ecx,zz                  ;calculate Lambda-Schrittweiten
  mov eax,inc_lambda1           ;get total length
  cdq
  idiv ecx                      ;and divide by number steps
  mov inc_lambda1,eax
  mov eax,inc_lambda2           ;get total length
  cdq
  idiv ecx                      ;and divide by number steps
  mov inc_lambda2,eax

  mov bp,txt_no                 ;get number of current texture
  shl bp,1                      ;two bytes per entry
  mov bx,txt_size[bp]           ;get current size specification
  mov b cs:size_patch+3,bl      ;and patch in code
  mov b cs:size_patch+7,bh

  mov ax,word ptr txt_offs[bp]  ;get offset of this texture

  push ds
  shl bp,1                      ;4 byte entries
  lds si,dword ptr txt_data[bp];get pointer to actual data
  add si,ax
  mov w cs:ofs_patch+2,si       ;and patch in code

  mov dx,3c4h                   ;timing sequencer
  mov ebp,lambda1               ;register instead of variables
  mov esi,lambda2

lp:                             ;runs for each pixel
  add ebp,inc_lambda1           ;continue Lambda1 and 2
  add esi,inc_lambda2

  mov ax,plane                  ;get plane
  out dx,ax                     ;and select

  mov eax,ebp                   ;determine offset within the texture graphic
  mov ebx,esi
size_patch:
  sar eax,11d                   ;set size, being modified
  sar ebx,11d
   imul eax,320d
  add ebx,eax

ofs_patch:
  mov al,ds:[bx+1111h]          ;get color from texture, being modified
  mov es:[di],al                ;enter color
  dec cx                        ;decrement number pixels
  je hlt_finished               ;all pixels finished ?
  rol b plane+1,1               ;next plane
  cmp b plane+1,11h             ;plane overflow from 3 to 0 ?
  jne lp                        ;no, then continue
  inc di                        ;otherwise increment offset
  jmp lp                        ;and continue
hlt_finished:
  pop ds
  popa
  pop es
  ret
hline_texture endp

endm

txt_maindet macro               ;calculate main determinant
  xor si,si                     ;first attempt: rows 0 and 1
  mov di,2

next:
  mov ax,w delta1[si]           ;calculate main determinant
  imul w delta2[di]
  mov bx,ax                     ;store intermediate result
  mov cx,dx
  mov ax,w delta2[si]
  imul w delta1[di]
  sub bx,ax                     ;store difference
  sbb cx,dx
  mov w D,bx
  mov w D+2,cx
  or bx,cx                      ;main determinant = 0 ?
  jne D_finished
  add si,2                      ;then new components
  add di,2
  cmp di,4                      ;still within existing rows ?
  jbe next
  xor di,di                     ;no, then start again from above
  jmp next
D_finished:
  movsx eax,delta1[si]          ;store used columnn values
  mov column1[0],eax
  movsx eax,delta1[di]
  mov column1[4],eax
  movsx eax,delta2[si]
  mov column2[0],eax
  movsx eax,delta2[di]
  mov column2[4],eax
  shl si,1                      ;note used columns
  shl di,1
  mov upper_row,si
  mov lower_row,di
endm

txt_incl macro                  ;increment left
  push eax
  mov eax,inc_xl                ;add 3d x-coordinate
  add xl_3d,eax
  mov eax,inc_yl                ;add 3d y-coordinate
  add yl_3d,eax
  mov eax,inc_zl                ;add 3d z-coordinate
  add zl_3d,eax
  pop eax
endm
txt_incr macro                  ;increment right
  push eax
  mov eax,inc_xr                ;add 3d x-coordinate
  add xr_3d,eax
  mov eax,inc_yr                ;add 3d y-coordinate
  add yr_3d,eax
  mov eax,inc_zr                ;add 3d z-coordinate
  add zr_3d,eax
  pop eax
endm
