.286
w equ word ptr
b equ byte ptr

include texture.inc             ;Textur-Makros implementieren

setnewlinel macro               ;Hier nur ax und bx verwenden !
local dylpos,dxlpos,dxlgross,macro_fertig
  mov bx,4043h                  ;Code fr inc ax (in bh) und inc bx (in bl)
  mov bp,links
  mov ax,poly2d[bp+8]           ;Zielkoordinaten sichern
  mov xl1,ax
  mov ax,poly2d[bp+10d]
  mov yl1,ax

  mov ax,poly2d[bp]             ;links x/y Start in glob. var
  mov xl0,ax
  sub ax,xl1                    ;delta x bilden
  inc xl1                       ;fr die Abbruchbedingung
  neg ax                        ;xl1-xl0
  jns dxlpos                    ;dxl negativ ?
  neg ax                        ;dann Betrag bilden
  mov bh,48h                    ;Code fr dec ax (dec xl0)
  sub xl1,2                     ;Erweiterung der Zielkoordinate nach negativ
dxlpos:
  mov dxl,ax                    ;und glob. sichern
  mov incflagl,ax               ;im Inkrement-Flag sichern
  mov ax,poly2d[bp+2]
  mov yl0,ax
  sub ax,yl1                    ;|delta y| bilden
  inc yl1                       ;fr die Abbruchbedingung
  neg ax
  jns dylpos                    ;negativ ?
  neg ax                        ;dann Betrag bilden
  mov bl,4bh                    ;Code fr dec bx (dec yl1)
  sub yl1,2                     ;Erweiterung der Zielkoordinate nach negativ
dylpos:
  mov dyl,ax                    ;und glob. sichern
  cmp dxl,ax                    ;dx < dy
  jae dxlgross
  neg incflagl                  ;dann Vorzeichenwechsel fr Inkrement-Flag
dxlgross:
  mov cs:byte ptr incxl,bh      ;Selbstmodifikation durchfhren
  mov cs:byte ptr incyl,bl

  cmp texture,1                 ;Texturen ben”tigt ?
  jne macro_fertig              ;nein, dann berspringen

  txt_makevarl                  ;sonst Textur-Variablen berechnen

macro_fertig:
  mov ax,xl0                    ;Register als Laufvariablen verwenden
  mov bx,yl0
  mov si,incflagl
endm

setnewliner macro               ;Hier nur cx und dx verwenden !
local dyrpos,dxrpos,dxrgross,macro_fertig
  mov cx,4142h                  ;Code fr inc cx (in ch) und inc dx (in cl)
  mov bp,rechts
  mov dx,poly2d[bp]             ;Zielkoordinaten holen
  mov xr1,dx
  mov dx,poly2d[bp+2]
  mov yr1,dx
  mov dx,poly2d[bp+8]           ;rechts x/y in glob. var
  mov xr0,dx
  sub dx,xr1                    ;|delta x| bilden
  inc xr1                       ;fr die Abbruchbedingung
  neg dx
  jns dxrpos                    ;negativ ?
  neg dx                        ;dann Betrag bilden
  mov ch,49h                    ;Code fr dec cx
  sub xr1,2                     ;Erweiterung der Zielkoordinate nach negativ
dxrpos:
  mov dxr,dx                    ;in glob. Var sichern
  mov incflagr,dx
  mov dx,poly2d[bp+10d]         ;|delta y| bilden
  mov yr0,dx
  sub dx,yr1
  inc yr1                       ;fr die Abbruchbedingung
  neg dx
  jns dyrpos                    ;negativ ?
  neg dx                        ;dann Betrag bilden
  mov cl,4ah                    ;Code fr dec dx
  sub yr1,2                     ;Erweiterung der Zielkoordinate nach negativ
dyrpos:
  mov dyr,dx                    ;und in glob. var sichern
  cmp dxr,dx                    ;dx < dy ?
  jae dxrgross
  neg incflagr                  ;dann Vorzeichenwechsel fr Inkrement-Flag
dxrgross:
  mov cs:byte ptr incxr,ch      ;Selbstmodifikation
  mov cs:byte ptr incyr,cl

  cmp texture,1                 ;Texturen ben”tigt ?
  jne macro_fertig              ;nein, dann berspringen

  txt_makevarr                  ;sonst Textur-Variablen berechnen

macro_fertig:
  mov cx,xr0                    ;Register laden
  mov dx,yr0
  mov di,incflagr
endm

data segment public
  extrn vpage:word              ;aktuelle Bildschirmseite
  extrn fl_ruecken              ;Flag fr Fl„chenrckenunterdrckung
  extrn glas:Byte;              ;Flag fr Glas-Fl„chen

;Textur-Variablen:
  extrn Texture:Byte            ;Textur ben”tigt ?
  extrn Txt_Daten:DataPtr       ;Array mit Zeigern auf Grafikdaten
  extrn Txt_Offs:DataPtr        ;Array mit Offsets innerhalb des Textur-Bilds
  extrn Txt_Groesse:DataPtr     ;Array mit Gr”áenangaben

d_x  dd 0                       ;relative x-Koordinate
d_y dd 0                        ;relative y-Koordinate
D    dd 0                       ;Hauptdeterminante
Spalte1 dd 0                    ;Komponenten der Hauptdeterminante
        dd 0
Spalte2 dd 0
        dd 0
obere_Reihe dw 0                ;welche Koordinaten wurden benutzt ?
untere_Reihe dw 0

xl_3d dd 0                      ;Laufwerte fr 3d-Koordinaten beim Fllen
yl_3d dd 0
zl_3d dd 0
xr_3d dd 0
yr_3d dd 0
zr_3d dd 0

inc_xl dd 0                     ;Werte fr Addition auf Laufwerte
inc_yl dd 0
inc_zl dd 0
inc_xr dd 0
inc_yr dd 0
inc_zr dd 0

;Variablen fr Fllalghorithmus
hoch_punkt   dw 0               ;w„hrend Suche in dx gehalten
hoch_y      dw 0                ;w„hrend Suche in bx gehalten

links        dw 0               ;Punkt der linken Seite
rechts      dw 0                ;Punkt der rechten Seite

xl0  dw 0                       ;Laufwerte fr linke Start- und Endpunkte
yl0 dw 0
xl1 dw 0
yl1 dw 0
xr0 dw 0                        ;Laufwerte fr rechts
yr0 dw 0
xr1 dw 0
yr1 dw 0
dxl dw 0                        ;Delta X / Y fr beide Seiten
dyl dw 0
dxr dw 0
dyr dw 0
incflagl dw 0                   ;Flags, wann y inkrementiert werden muá
incflagr dw 0                   ;also eine Art "Steigung"

data ends

code segment public
assume cs:code,ds:data
extrn polycol:word              ;Fl„chenfarbe
extrn polyn:word                ;Anzahl Ecken
extrn poly2d:word               ;Array mit 2D-Koordinaten
extrn poly3d:word               ;Array mit 3D-Koordinaten
extrn delta1,delta2:word        ;Ebenenvektoren
extrn bline:near                ;zeichnet Linie

lambda1 dd 0                    ;affine Koordinaten
lambda2 dd 0

inc_lambda1 dd 0                ;Schrittweiten
inc_lambda2 dd 0

plane dw 0002h                  ;aktuell zu setzende Plane
x0 dw 0                         ;Koordinaten fr Linie
y0 dw 0
x1 dw 0
zz dw 0                         ;noch zu zeichnende Punkte

extrn Txt_Nr:Word               ;Nummer der zu zeichnenden Textur

public drawpol
;zeichnet Drahtmodell der Fl„che in Poly2d
drawpol proc near
  push es
  pusha
  xor si,si                     ;Index auf ersten Eintrag
  mov bp,polyn                  ;Anzahl Ecken holen
@nline:
  mov ax,poly2d[si]             ;Koordinaten aus Tabelle holen
  mov bx,poly2d[si+2]
  mov cx,poly2d[si+8]
  mov dx,poly2d[si+10d]
  push bp
  push si
  call bline                    ;Linie zeichnen
  pop si
  pop bp
  add si,8                      ;n„chste Linie
  dec bp                        ;Anzahl dekrementieren
  jne @nline
  popa
  pop es
  ret
drawpol endp

hline proc near                 ;zeichnet horiz. Linie ax/bx -> cx/bx
  pusha
  push es
  mov x0,ax                     ;Koordinaten fr sp„ter sichern
  mov y0,bx
  mov x1,cx
  sub cx,ax                     ;Anzahl zu zeichnender Punkte berechnen
  jne zzok
  inc cx

zzok:
  mov zz,cx

  cmp glas,1                    ;Glas-Fl„chen ?
  jne Solid1
  push ax                       ;ja, dann GDC-Modus: OR
  mov dx,3ceh
  mov ax,1003h                  ;Register 3: Function Select
  out dx,ax
  pop ax

Solid1:
  mov dx,3c4h                   ;Timing Sequenzer-Port
  mov di,0a000h
  mov es,di                     ;VGA-Segment w„hlen
  mov di,ax                     ;Offset berechnen
  shr di,2                      ;(x div 4) + y*80
  add di,vpage                  ;aktuelle Seite drauf
  mov bx,y0
  imul bx,80d
  add di,bx                     ;jetzt in di
  cmp zz,4
  jl keine_mitte                ;<4 Punkte zeichnen -> keine 4er-Bl”cke
  and ax,11b                    ;untere beiden Bit sind wichtig
  je mitte                      ;wenn 0 sofort 4er-Bl”cke setzen
keine_mitte:
  mov bx,0f02h                  ;wenn kein_shift, dann diese Maske benutzen
  mov cx,zz                     ;Anzahl Punkte in Maske setzen
  cmp cx,20h                    ;ab 20h shiftet der 386 wieder rein !
  jae kein_shift
  mov bx,0102h                  ;Maske vorbereiten
  shl bh,cl                     ;Anzahl Punkte=Anzahl zu setzender Bits
  dec bh
  and bh,0fh
kein_shift:
  mov cx,ax                     ;je nach Startplane richtig schieben
  and cl,3
  shl bh,cl
  mov ax,bx                     ;und Maske fertig
  sub zz,4                      ;zu zeichnende Punkte runterzaehlen
  add zz,cx
start:
  out dx,ax                     ;berechnete Schreibmaske setzen
  mov al,b polycol              ;Farbe holen

  mov ah,es:[di]                ;Latches laden, nur fr Glas-K”rper

  stosb                         ;setzen
mitte:
  cmp zz,4
  jl schluss                    ;wenn kein 4er Block mehr -> Abschluss

  mov ax,0f02h                  ;alle Planes selektieren
  out dx,ax                     ;(zz div 4) 4er Bl”cker setzen
  mov cx,zz
  shr cx,2
  mov al,b polycol

  cmp glas,1                    ;Glas-K”rper ?
  jne Solid

@lp:
  mov ah,es:[di]                ;Latches laden, nur fr Glas-K”rper
  stosb                         ;und zurckschreiben
  dec cx
  jne @lp
  jmp schluss

Solid:
  rep stosb                     ;Mittelteil zeichnen

schluss:
  mov cx,x1                     ;šbrige Pixel setzen
  and cx,3h
  dec zz
  js hline_fertig               ;wenn nichts mehr da -> Ende
  mov ax,0102h
  shl ah,cl                     ;Maske erstellen
  dec ah
  out dx,ax
  mov al,b polycol              ;Farbe holen

  mov ah,es:[di]                ;Latches laden, nur fr Glas-K”rper

  stosb                         ;und Punkte zeichnen
hline_fertig:
  mov dx,3ceh                   ;GDC-Mode wieder auf MOVE
  mov ax,0003h
  out dx,ax
  pop es
  popa
  ret
hline endp

txt_hline                       ;Macro enth„lt die Prozedur "hline_texture"

public fillpol
fillpol proc near               ;fllt Polygon in Mode X
  push bp
  pusha

  cmp texture,1                 ;werden Texturen benutzt ?
  jne Fllen                    ;nein, dann einfach fllen

  txt_Hauptdet                  ;sonst Hauptdeterminante berechnen

Fllen:
  xor si,si                     ;Suche nach h”chstem Punkt,ersten Eintrag sel.
  mov cx,polyn                  ;Anzahl Ecken
  sub cx,2
  mov bx,0ffffh                 ;extrem hoher Wert, auf jeden Fall unterboten
npoint:
  mov ax,poly2d[si+2]           ;y holen
  cmp ax,bx                     ;wenn bisheriges Minimum unterboten
  ja  no_min
  mov bx,ax                     ;neues Minimum festhalten
  mov dx,si
no_min:
  add si,8
  dec cx                        ;n„chste Ecke, wenn nicht 0ffffh
  jns npoint
  mov hoch_punkt,dx             ;in glob var festhalten
  mov hoch_y,bx                 ;Hochpunkt-Suche abgeschlossen

  or dx,dx                      ;links = 0 ?
  jne dec_valid
  mov bx,polyn                  ;ja: rechts ans andere Ende
  sub bx,2
  shl bx,3
  jmp lr_fertig                 ;positionieren
dec_valid:
  mov bx,dx                     ;ansonsten einen davor
  sub bx,8
lr_fertig:
  mov links,dx                  ;in glob var festhalten
  mov rechts,bx

; ax/bx : Startkoordinaten links    (xl0/yl0)
; cx/dx : Startkoordinaten rechts   (xr0/yr0)
; si    : šberlaufflag links
; di    : šberlaufflag rechts
; bp    : Zeiger auf aktuellen Punkt

  setnewlinel                   ;Linienvariablen laden
  setnewliner

schleifel:
  cmp ax,xl1
  je neue_liniel                ;wenn Ende erreicht -> neue Linie setzen
  cmp bx,yl1
  je neue_liniel                ;sonst weiterzeichnen

  or si,si                      ;Inkrement-Flag <= 0
  jg flaglgross
incyl:                          ;Diese Stelle wird gepatcht !
  inc bx                        ;y weiter
  add si,dxl                    ;IncFlag weitersetzen

  txt_incl                      ;auch 3D-Koordinaten weiter

  cmp bx,yl1                    ;Ziel erreicht ?
  je neue_liniel                ;dann neue Linie
  jmp links_erh”ht              ;Links wurde y erh”ht -> jetzt rechts
flaglgross:
  sub si,dyl                    ;Inkflag runterz„hlen
incxl:                          ;Diese Stelle wird gepatcht !
  inc ax                        ;x weiter
  jmp schleifel

fertig__:
  jmp fertig

neue_liniel:
  mov bx,links                  ;Erh”hung vorbereiten
  cmp bx,rechts
  je fertig__                   ;gleich, dann fertig
  add bx,8                      ;links weiter
  mov ax,polyn                  ;Ist Links am Ende der Liste ?
  shl ax,3
  sub ax,8                      ;Ende bestimmt
  cmp bx,ax                     ;Vergleich
  jb links_setzen
  xor bx,bx                     ;wenn ja, dann auf 0 setzen
links_setzen:
  mov links,bx
  setnewlinel                   ;Variablen neu laden
  jmp schleifel
fertig_:
  jmp fertig
links_erh”ht:

schleifer:
  cmp cx,xr1
  je neue_linier                ;wenn Ende erreicht -> neue Linie setzen
  cmp dx,yr1
  je neue_linier                ;sonst weiterzeichnen

  or di,di                      ;Inkrement-Flag <= 0
  jg flagrgross
incyr:                          ;Diese Stelle wird gepatcht !
  inc dx                        ;y weiter
  add di,dxr                    ;IncFlag weitersetzen

  txt_incr

  cmp dx,yr1                    ;Ziel erreicht ?
  je neue_linier                ;dann neue Linie
  jmp rechts_erh”ht             ;Rechts wurde y erh”ht -> jetzt Linie ziehen
flagrgross:
  sub di,dyr                    ;Inkflag runterz„hlen
incxr:
  inc cx                        ;Diese Stelle wird gepatcht !
  jmp schleifer

neue_linier:
  mov dx,rechts                 ;Verminderung vorbereiten
  cmp dx,links
  je fertig_                    ;wenn gleich, dann fertig
  sub dx,8                      ;Wenn vorher auf 0->ans andere Ende setzen
  jns rechts_setzen
  mov dx,polyn
  sub dx,2
  shl dx,3                      ;auf Ende positioniert
rechts_setzen:
  mov rechts,dx

  setnewliner                   ;Variablen neu laden
  jmp schleifer

rechts_erh”ht:
  push ax
  push cx
  cmp cx,ax                     ;richtige Reihenfolge ?
  jae direct_ok                 ;dann ok, sonst:
  cmp w fl_ruecken,0            ;Fl„chenrcken unterdrcken ?
  je zeichnen                   ;nein, dann dennoch zeichnen
  pop cx
  pop ax
  jmp fertig                    ;Polygon wird nicht gezeichnet
zeichnen:
  xchg ax,cx                    ;Koordinaten in richtige Reihenfolge
direct_ok:

  cmp texture,1                 ;Texturen verwenden ?
  jne norm_fuellen              ;nein, dann normal fllen
  call hline_texture            ;horizontale Textur-Linie zeichnen
  pop cx
  pop ax
  jmp schleifel                 ;und weiter
norm_fuellen:
  call hline                    ;horizontale Linie zeichnen
  pop cx
  pop ax
  jmp schleifel                 ;und weitermachen
fertig:
  popa
  pop bp
  ret
fillpol endp
code ends
end