Program pre otáčanie texturou pomocou kolineránich transformácií

Delphi & Pascal (česká wiki)
Přejít na: navigace, hledání
Category: KMP (Club of young programmers)
krychle.pngProgram: Krychle.pasU_crt.pasU_graf13.pasU_znacka.pas
File exe: Krychle.exe
need: Textura2.bmpTextura2.obj

Program pre otáčanie texturou pomocou kolineránich transformácií.
{ u_graf13.pas                                                       }
{ Unit pre program krychle.pas                                       }
{                                                                    }
{ Author:                                                            }
{ Datum:02.02.2008                              http://www.trsek.com }
 
{$D-,E-,G+,I-,L-,N-,P+,Q-,R-,S-,T-,V-,Y- exe}
{$G+}
{VGA a 386 nebo vyssi}
Unit U_Graf13;
Interface
 
Type
    PointType= record
      x,y:integer;
    end;
    Pole13=Array[0..201,0..319] of Byte;    {o 2 spodni radky vetsi}
    TypPaleta=Array[0..767] Of Byte; {RGB}
Const
    Scr13=$A000;    {pri SCR13:Word=$A000 pouzivat mov ax,[Scr13]}
    Color13:Byte=1;
    AktObraz13:Boolean=True;
    Vypln13:Boolean=False;
    Tet13:PointType=(x:0;y:0); {aktualni souradnice}
Var
    Red13,Green13,Blue13:Boolean;
    Pal13:TypPaleta; {RGB}
    FSeg13,FOfs13:Word;
    Schranka13:^Pole13;
    Obrazovka13:Pole13 Absolute SCR13:$0000;
 
 
Procedure PutPixel(X,Y:Integer;Barva:Byte);
Function  GetPixel(X,Y:Integer): Byte;
Procedure Line(X1,Y1,X2,Y2:Integer);
Procedure SetColor(Barva:Byte);
Function  GetColor:Byte;
Procedure SetRGBPalette(IndexBarvy,Red,Green,Blue:Byte);
Procedure Elipsa13(Sx,Sy:Integer;a,b:Real);
Procedure Circle(X,Y:Integer;Polomer:Word);
Procedure ClearDevice;
Procedure InitGraph;
Procedure CloseGraph;
Procedure OutText(Retezec:String);
Procedure OutInteger(Cislo:LongInt);
Procedure OutTextXY(X,Y:Integer;Retezec:String);
Procedure OutXYCode(X,Y:Integer;Cod:Byte);
Procedure DrawPoly(Pocet:word;var Seznam);
Procedure FillPoly(Pocet:word;var Seznam);
 
Procedure Rozmazni;    {Rozmaze Schranku13}
Procedure InitPalRGB;
Procedure InitPalSpektrum;
Procedure InitPalOhen;
Procedure Vybarvi(a:Byte); {vybarvi i skrytou cast (2 radky)}
Procedure ZobrazSchranku13;    {32 bit!!! Kopiruje Schranku13 do Obrazovky13}
Procedure UlozSchranku13;    {32 bit!!! naopak..}
Procedure LoadPal;
 
 
Implementation
 
Function Orez(var x1,y1,x2,y2:Integer):Boolean;
Const
MaxX = 319;
MaxY = 199;
MinX = 0;
MinY = 0;
Var
   P:array[0..9] of LongInt;
   W,O,N,M:Byte;
   D:LongInt;
Begin
   Orez := False;
   IF (x1 < MinX) and (x2 < MinX) Then Exit;
   IF (x1 > MaxX) and (x2 > MaxX) Then Exit;
   IF (y1 < MinY) and (y2 < MinY) Then Exit;
   IF (y1 > MaxY) and (y2 > MaxY) Then Exit;
   {zbavili jsme se tecek u neprotinajicich primek na okraji}
   Orez := True;
   P[0] := x1;
   P[1] := x2;
   P[2] := P[1] - P[0]; {dx}
   P[3] := MinX;
   P[4] := MaxX;
   P[5] := y1;
   P[6] := y2;
   P[7] := P[6] - P[5]; {dy}
   P[8] := MinY;
   P[9] := MaxY;
   For W := 0 to 1 do
    For O := 0 to 1 do
     For N := 0 to 1 do
      Begin
        M := (w shl 2) + w; {0,0,0,0,5,5,5,5}
        D := P[M + 3 + O] - P[M + N]; {3-0,3-1,4-0,4-1,8-5,8-6,9-5,9-6}
        IF (D * (1 - (O shl 1))) <= 0 THEN Continue;
        {bod je vne ohrady}
        IF P[M + 2] = 0 THEN
        Begin
         {rovnobezka mimo obdelnik}
         Orez := False;
         Exit;
        End;
        {(3-0)/2, (3-1)/2, (4-0)/2, (4-1)/2, (8-5)/7, (8-6)/7, (9-5)/7, (9-6)/7}
        P[5 - M + N] := P[5 - M + N] + (D * P[5 - M + 2]) div P[M + 2];
        P[M + N] := P[M + 3 + O];
        P[2] := P[1] - P[0];
        P[7] := P[6] - P[5];
      End;
   x1 := P[0];
   x2 := P[1];
   y1 := P[5];
   y2 := P[6];
   IF (x1 < MinX) Or (x1 > MaxX) Then Orez := False;
   IF (x2 < MinX) Or (x2 > MaxX) Then Orez := False;
   IF (y1 < MinY) Or (y1 > MaxY) Then Orez := False;
   IF (y2 < MinY) Or (y2 > MaxY) Then Orez := False;
End;
 
 
Procedure PutPixel(X,Y:Integer;Barva:Byte); Assembler;
ASM
    MOV    AX,X
    TEST   AX,$8000
    JNZ    @Exit
    CMP    AX,319
    JA     @Exit
    MOV    BX,Y
    TEST   BX,$8000
    JNZ    @Exit
    CMP    BX,199
    JA     @Exit
    XCHG   BH,BL      {Zameni BH a BL, jako * 256}
    TEST   AktObraz13,1
    JNZ    @Obraz
    LES    DI,Schranka13
    ADD    DI,BX
    JMP    @1
@Obraz:
    MOV    CX,SCR13
    MOV    ES,CX
    MOV    DI,BX
@1:
    SHR    BX,2
    ADD    BX,AX
    ADD    DI,BX
    MOV    AL,Barva
    MOV    ES:[DI],AL
@Exit:
End;
 
Function  GetPixel(X,Y: Integer): Byte;
Begin
   IF AktObraz13 Then GetPixel := Obrazovka13[y,x]
   Else GetPixel := Schranka13^[y,x];
End;
 
Procedure Line(X1,Y1,X2,Y2:Integer);
Var
DeltaS:Integer;    {Zmena za 1 ds}
Dskok,XRoz,XRoz2,YRoz,i:Integer;
Begin
   IF NOT Orez(x1,y1,x2,y2) Then Exit;
   XRoz := x2-x1;
   YRoz := y2-y1;
   IF XRoz < 0 Then    {1 reseni zacatku}
   Begin
      x1 := x2;
      y1 := y2;
      XRoz := - XRoz;
      YRoz := - YRoz;
   End;
   IF XRoz >= Abs(YRoz) Then
    Begin
        DeltaS:= 1;
        IF YRoz >= 0 Then DSkok := 320 Else Begin DSkok := -320; YRoz := -YRoz; End;
    End Else Begin
        IF YRoz >= 0 Then DeltaS:= 320 Else Begin DeltaS:= -320; YRoz := -YRoz; End;
        DSkok := 1;
      i := XRoz; XRoz := YRoz; YRoz := i;
    End;
    XRoz2 := -(XRoz Shl 1);
    ASM
        MOV    BX,y1
        XCHG   BH,BL      {Zameni BH a BL, jako * 256}
        TEST   AktObraz13,1
        JNZ    @Obraz
        LES    DI,Schranka13
        ADD    DI,BX
        JMP    @1
@Obraz:
        MOV    CX,SCR13
        MOV    ES,CX
        MOV    DI,BX
@1:
        SHR    BX,2
        ADD    BX,x1
        ADD    DI,BX            {cil ES:DI}
        MOV    AL,Color13    {AL := Color13}
        MOV    ES:[DI],AL
        MOV    CX,XRoz        {CX := XRoz na Smycku}
        OR     CX,CX
        JZ     @Exit
        MOV    DX,YRoz
        SHL    DX,1            {DX := 2*YRoz}
        MOV    SI,dx
        SUB    SI,CX            {SI := P}
        MOV    BX,DeltaS    {BX := DeltaS}
@Smycka:
        ADD    DI,BX
        TEST   SI,$8000
        JNZ    @2
        ADD    DI,DSkok
        ADD    SI,XRoz2
@2:
        MOV    ES:[DI],AL
        ADD    SI,DX
        LOOP   @Smycka
@Exit:
    End;
{  
   _Ofs := _Ofs + y1 Shl 8 + y1 Shl 6 + x1;
   YRoz := YRoz Shl 1;
   p := YRoz - XRoz;
   For i := 1 To XRoz do
   Begin
      IF p >= 0 Then    _Ofs := _Ofs + DeltaS + DSkok Else _Ofs := _Ofs + DeltaS;
      Mem[_Seg:_Ofs] := Color13;
      IF p >= 0 Then p := p + YRoz + XRoz2 Else p := p + YRoz;
   End;
}
End;
 
Procedure SetColor(Barva:Byte);
Begin
  Color13 := Barva;
End;
 
Function  GetColor:Byte;
Begin
  GetColor := Color13;
End;
 
Procedure SetRGBPalette(IndexBarvy,Red,Green,Blue:Byte);
Begin
  Pal13[IndexBarvy*3]  := Red Shr 2;
  Pal13[IndexBarvy*3+1]:= Green Shr 2;
  Pal13[IndexBarvy*3+2]:= Blue Shr 2;
End;
 
 
Procedure Elipsa13(Sx,Sy:Integer;a,b:Real);
Var
   x,y,MinX,MaxX:Integer;
   SegObr,OfsObr,OfsBodu:Word;
Begin
   IF (a>0) And (b>0) Then
   Begin
      IF Vypln13 Then
      Begin
         IF AktObraz13 Then Begin 
           SegObr := SCR13;
           OfsObr := 0;
         End
         Else Begin
           SegObr := Seg(Schranka13^);
           OfsObr := Ofs(Schranka13^);
         End;
      End;
      For y := Trunc(-b) to Trunc(b) do
      IF (Sy + y >= 0) And (Sy + y <= 199) Then
        Begin
         x := Trunc(SQRT(SQR(a)*(1-y*y/SQR(b))));
         IF Vypln13 Then
         Begin
            MinX := SX - x;
            MaxX := SX + x;
            IF MinX < 0   Then MinX := 0;
            IF MaxX > 319 Then MaxX := 319;
            IF MaxX >= MinX Then
            Begin
              OfsBodu := OfsObr + (Sy+y) Shl 8 + (Sy+y) Shl 6;
              FillChar(Ptr(SegObr,OfsBodu + MinX)^,MaxX-MinX + 1,Color13);
            End;
         End Else
         Begin
           PutPixel(Sx + x, Sy + y,Color13);
           PutPixel(Sx - x, Sy + y,Color13);
         End;
      End;
      IF Not Vypln13 Then
      For x := Trunc(-a) to Trunc(a) do
      IF (Sx + x >= 0) And (Sx + x <= 319) Then
      Begin
         y := Trunc(SQRT(SQR(b)*(1-x*x/SQR(a))));
         PutPixel(Sx + x,Sy + y,Color13);
         PutPixel(Sx + x,Sy - y,Color13);
      End;
   End;
End;
 
 
Procedure Circle(X,Y:Integer;Polomer:Word);
Begin
   Elipsa13(X,Y,Polomer*1.212,Polomer);
End;
 
 
Procedure ClearDevice; Assembler;
ASM
    TEST   AktObraz13,1
    JNZ    @Obraz
    LES    DI,Schranka13
    JMP    @1
@Obraz:
    MOV    CX,SCR13
    MOV    ES,CX
    XOR    DI,DI
@1:
    MOV    BX,320*200
    XOR    AX,AX
@2:
    MOV    ES:[DI+BX-2],AX
    SUB    BX,2
    JNZ    @2
    MOV    Tet13.X,0
    MOV    Tet13.Y,0
End;
 
 
Procedure Vybarvi(a:Byte); Assembler;
ASM
    TEST   AktObraz13,1
    JNZ    @Obraz
    LES    DI,Schranka13
    JMP    @1
@Obraz:
    MOV    CX,SCR13
    MOV    ES,CX
    XOR    DI,DI
@1:
    MOV    BX,320*202
    MOV    AL,a
    MOV    AH,AL
@2:
    MOV    ES:[DI+BX-2],AX
    SUB    BX,2
    JNZ    @2
    MOV    Tet13.X,0
    MOV    Tet13.Y,0
End;
 
 
Procedure InitGraph;
Var
b:Byte;
Begin
   Asm
    push ds
    push bp
    Mov ax,$1a00 {cteni kombinace monitoru}
    Int 10h
    Mov B,al
    pop bp
    pop ds
   End;
   IF b <> $1a Then Begin Writeln('Karta VGA nebyla nalezena.'); Halt; End;
   IF Schranka13 = nil Then
   Begin
       IF MaxAvail < SizeOf(Pole13) Then
       Begin
          Writeln('Nedostatek pameti, potrebuji jeste: ',SizeOf(Pole13)-MaxAvail,'b souvisleho bloku.');
          Halt;
       End;
       GetMem(Schranka13,SizeOf(Pole13));
      {Ofs(Schranka13^) = 0 nebo 8}
       Fillchar(Schranka13^,SizeOf(Schranka13^),0);
    End;
   Asm
    push ds
    push bp
{sluzba 0;ah=0,al=13h; nastaveni modu 13h}
    mov ax,13h
    int 10h
{sluzba 11; funkce 30; zjisteni informaci o fontu}
    mov ax,1130h
    mov bh,1
    int 10h
    mov FSeg13,es
    mov FOfs13,bp
    pop bp
    pop ds
   End;
End;
 
Procedure CloseGraph;
Begin
    IF Schranka13 <> nil Then
   Begin
        FreeMem(Schranka13, SizeOf(Pole13));
      Schranka13 := nil;
   End;
    Asm
      push ds
      push bp
      mov ax,3h
      int 10h
      pop bp
      pop ds
    End;
End;
 
Procedure OutInteger(Cislo:LongInt);
var Slovo:string[11];
Begin
   Str(Cislo,Slovo);
   OutTextXY(Tet13.x,Tet13.y,Slovo);
End;
 
Procedure OutText(Retezec:String);
Begin
   OutTextXY(Tet13.x,Tet13.y,Retezec);
End;
 
Procedure OutXYCode(X,Y:Integer;Cod:Byte);
Var
    a,dx,dy:byte;
   Cod8:Word;
Begin
   Tet13.x := x;
   Tet13.y := y;
   Cod8 := Cod Shl 3;
   For dy := 0 to 7 do
   Begin
      a:= Mem[FSeg13:FOfs13 + dy + Cod8];
      For dx := 0 to 7 do
      Begin
         Asm
            mov al,a
            rol al,1
{SHR al,1 dx:= 7 downto 0}
            mov a,al
         End;
         IF a And 1 = 1 then PutPixel(Tet13.x+dx,Tet13.y+dy,Color13);
      End;
   End;
   Tet13.x := Tet13.x + 8;
End;
 
Procedure OutTextXY(X,Y:Integer;Retezec:String);
Var
   a,delka,dx,dy:byte;
   p:Word;
Begin
   Tet13.x := x;
   Tet13.y := y;
   For Delka := 1 To Length(Retezec) do
   Begin
      p := Ord(Retezec[Delka]);
      IF (Tet13.x > 311) or (p = 13) Then
      Begin
         Tet13.x := 0;
         Tet13.y := Tet13.y + 8;
         If p = 13 then continue;
      End;
      p := p Shl 3;
      For dy := 0 to 7 do
      Begin
         a:= Mem[FSeg13:FOfs13+dy+p];
         For dx := 0 to 7 do
         Begin
            Asm
            mov al,a
            rol al,1
            mov a,al
            End;
            IF a And 1 = 1 then PutPixel(Tet13.x+dx,Tet13.y+dy,Color13);
         End;
      End;
      Tet13.x := Tet13.x + 8;
   End;
End;
 
Procedure DrawPoly(Pocet:word;var Seznam);
Var
   S:Array[1..1000] of PointType absolute Seznam;
   a:Word;
Begin
   For a := Pocet DownTo 2 do Line(S[a].x,S[a].y,S[a-1].x,S[a-1].y);
   Line(S[Pocet].x,S[Pocet].y,S[1].x,S[1].y);
End;
 
 
 
Procedure Rozmazni; Assembler;
ASM
    LES    DI,Schranka13
    ADD    DI,320            {ES:DI adresa meneneho bodu zvetsena o radek}
 
    XOR    BH,BH
    XOR    AH,AH
    MOV    CX,64000;      {320*200 = pocita se i z radku 200 a 201, posledni meneny je 199}
@1:
    MOV    AL,ES:[DI-1]   {   +----+}
    MOV    BL,ES:[DI]     {   |-320| =meneny bod}
    ADD    AX,BX          {+--+----+--+}
    MOV    BL,ES:[DI+1]   {|-1| DI |+1|}
    ADD    AX,BX          {+--+----+--+}
    MOV    BL,ES:[DI+320] {   |+320|}
    ADD    AX,BX          {   +----+}
    SHR    AX,2                {AX := (Bod(DI-1)+Bod(DI)+Bod(DI+1)+Bod(DI+320)) div 4}
    JZ     @2
    DEC    AX                    {IF AX > 0 Then AX := Ax -1}
@2:
    MOV    BYTE PTR ES:[DI-320],AL  {nastavena barva}
    INC    DI
    LOOP   @1
END;
 
 
 
Procedure LoadPal; Assembler;
Asm
{cekani na paprsek}
   mov dx,3dah
@1:in  al,dx
   and al,8
   jz @1
@2:in  al,dx
   and al,8
   jnz @2
{}
   push ds
   push bp
   mov si,offset pal13
   mov cx,768
   mov dx,03c8h
   xor al,al
   out dx,al
   inc dx
@3:outsb
   dec cx
   jnz @3
   pop bp
   pop ds
End;
 
 
Procedure InitPalRGB;
{Procedura je predelana z procedur Radovana Urbana}
Var
   w:Word;
   b:Byte;
Begin
   IF Red13 And Green13 And Blue13 Then
   Begin
      InitPalSpektrum;
      Exit;
   End;
   w := 0;
   {cerna..barevna/cerna}
   For b := 0 to 31 do
   Begin
      IF Red13   Then Pal13[w]   := b Shl 1 Else Pal13[w]   := 0;
      IF Green13 Then Pal13[w+1] := b Shl 1 Else Pal13[w+1] := 0;
      IF Blue13  Then Pal13[w+2] := b Shl 1 Else Pal13[w+2] := 0;
      Inc(w,3);
    End;
   {barevna/cerna..bila}
   For b := 32 to 63 do
   Begin
      IF Red13   Then Pal13[w]   := 63 Else Pal13[w]   := (b - 32) Shl 1;
      IF Green13 Then Pal13[w+1] := 63 Else Pal13[w+1] := (b - 32) Shl 1;
      IF Blue13  Then Pal13[w+2] := 63 Else Pal13[w+2] := (b - 32) Shl 1;
      Inc(w,3);
    End;
   {bila..barevna/cerna}
   For b := 64 to 159 do
   Begin
      IF Red13   Then Pal13[w]   := 63 Else Pal13[w]   := ((159 - b) Shl 1) Div 3;
      IF Green13 Then Pal13[w+1] := 63 Else Pal13[w+1] := ((159 - b) Shl 1) Div 3;
      IF Blue13  Then Pal13[w+2] := 63 Else Pal13[w+2] := ((159 - b) Shl 1) Div 3;
      Inc(w,3);
   End;
   {barevna/cerna..cerna}
    For b := 160 to 255 do
   Begin
      IF Red13   Then Pal13[w]   := ((255 - b) Shl 1) Div 3 Else Pal13[w]   := 0;
      IF Green13 Then Pal13[w+1] := ((255 - b) Shl 1) Div 3 Else Pal13[w+1] := 0;
      IF Blue13  Then Pal13[w+2] := ((255 - b) Shl 1) Div 3 Else Pal13[w+2] := 0;
      Inc(w,3);
   End;
   LoadPal;
End;
 
 
Procedure _InitPalSpektrum;
{Procedura je predelana z procedur Radovana Urbana}
Var
   w:Word;
   b:Byte;
Begin
   w := 0;
   {cerna}
   For b := 0 to 31 do {32}
   Begin
      {R} Pal13[w]  := b Shl 1;
      {G} Pal13[w+1]:= 0;
      {B} Pal13[w+2]:= 0;
      Inc(w,3);
   End;
   {cervena}
   For b := 32 to 95 do {64}
   Begin
      {64 = oranzova}
      {R}Pal13[w]   := 63;
      {G}Pal13[w+1] := b - 32;
      {B}Pal13[w+2] := 0;
      Inc(w,3);
   End;
   {zluta}
   For b := 96 to 127 do {32}
   Begin
      {R} Pal13[w]   := (127 - b) Shl 1;
      {G} Pal13[w+1] := 63;
      {B} Pal13[w+2] := 0;
      Inc(w,3);
   End;
   {zelena}
   For b := 128 to 191 do {64}
   Begin
      {160 = azurova}
      {R} Pal13[w]   := 0;
      {G} Pal13[w+1] := 191 - b;
      {B} Pal13[w+2] := b - 128;
      Inc(w,3);
   End;
   {modra}
   For b := 192 to 223 do {32}
   Begin
      {R} Pal13[w]   := (b - 192) Shl 1;
      {G} Pal13[w+1] := 0;
      {B} Pal13[w+2] := 63;
      Inc(w,3);
   End;
   {fialova}
   For b := 224 to 255 do {32}
   Begin
      {R} Pal13[w]   := (255 - b) Shl 1;
      {G} Pal13[w+1] := 0;
      {B} Pal13[w+2] := (255 - b) Shl 1;
      Inc(w,3);
   End;
   {cerna}
   LoadPal;
End;
 
 
Procedure InitPalSpektrum;
{Procedura je predelana z procedur Radovana Urbana}
Type
TypAkce=(min,max,up32,up64,down32,down64);
 
Function Akce(Kolik,b:Byte;A:TypAkce):Byte;
Begin
    Case A Of
      min : Akce := 0;
      max : Akce := 63;
      up32: Akce := b Shl 1;
      up64: Akce := b;
      down32: Akce := (Kolik - b - 1) Shl 1;
      down64: Akce := Kolik - b - 1;
   End;
End;
 
Procedure Pomocna(Kolik:Byte;Var Index:Word;ARed,AGreen,ABlue:TypAkce);
Var b:Byte;
Begin
   For b := 0 To Kolik - 1 Do
   Begin
      {R} Pal13[Index]  := Akce(Kolik,b,ARed);
      {G} Pal13[Index+1]:= Akce(Kolik,b,AGreen);
      {B} Pal13[Index+2]:= Akce(Kolik,b,ABlue);
      Inc(Index,3);
   End;
End;
 
Var
   w:Word;
   b:Byte;
Begin
   w := 0;
   {cerna}
   Pomocna(32,w,up32,min,min);
   {cervena}
   Pomocna(64,w,max,up64,min); {64 = oranzova}
   {zluta}
   Pomocna(32,w,down32,max,min);
   {zelena}
   Pomocna(64,w,min,down64,up64); {160 = azurova}
   {modra}
   Pomocna(32,w,up32,min,max);
   {fialova}
   Pomocna(32,w,down32,min,down32);
   {cerna}
   LoadPal;
End;
 
Procedure _InitPalOhen;
{Procedura je predelana z procedur Radovana Urbana}
Type
TypAkce=(min,max,up32,up64,down32,down64);
 
Function Akce(Kolik,b:Byte;A:TypAkce):Byte;
Begin
    Case A Of
      min : Akce := 0;
      max : Akce := 63;
      up32: Akce := b Shl 1;
      up64: Akce := b;
      down32: Akce := (Kolik - b - 1) Shl 1;
      down64: Akce := Kolik - b - 1;
   End;
End;
 
Procedure Pomocna(Kolik:Byte;Var Index:Word;ARed,AGreen,ABlue:TypAkce);
Var b:Byte;
Begin
   For b := 0 To Kolik - 1 Do
   Begin
      {R} Pal13[Index]  := Akce(Kolik,b,ARed);
      {G} Pal13[Index+1]:= Akce(Kolik,b,AGreen);
      {B} Pal13[Index+2]:= Akce(Kolik,b,ABlue);
      Inc(Index,3);
   End;
End;
 
Var
   w:Word;
   b:Byte;
Begin
   w := 0;
   {cerna}
   Pomocna(32,w,min,min,up32);
   {modra}
   Pomocna(32,w,up32,min,max);
   {fialova}
   Pomocna(64,w,max,min,down64);
   {cervena}
   Pomocna(64,w,max,up64,min);
   {zluta}
   Pomocna(64,w,max,max,up64);
   {bila}
{   Pomocna(32,w,max,down32,min);
   {cervena}
{   Pomocna(32,w,max,min,up32);
   {fialova}
{   Pomocna(32,w,down32,min,down32);
   {cerna}
   LoadPal;
End;
 
 
 
Procedure InitPalOhen;
{Procedura je predelana z procedur Radovana Urbana}
Var
   w:Word;
   b:Byte;
Begin
   w := 0;
   {cerna}
   For b := 0 to 15 do
   Begin
      {R} Pal13[w]  := 0;
      {G} Pal13[w+1]:= 0;
      {B} Pal13[w+2]:= b;
      Inc(w,3);
   End;
   {ctvrtmodra}
   For b := 16 to 31 do
   Begin
      {R}Pal13[w]   := b - 16;
      {G}Pal13[w+1] := 0;
      {B}Pal13[w+2] := b;
      Inc(w,3);
   End;
   {pulfialova}
   For b := 32 to 63 do
   Begin
      {R} Pal13[w]   := b - 16;
      {G} Pal13[w+1] := 0;
      {B} Pal13[w+2] := 63 - b;
      Inc(w,3);
   End;
   {cervena}
   For b := 64 to 79 do
   Begin
      {R} Pal13[w]   := b - 16;
      {G} Pal13[w+1] := 0;
      {B} Pal13[w+2] := 0;
      Inc(w,3);
   End;
   {cervena}
   For b := 80 to 95 do
   Begin
      {R} Pal13[w]   := 63;
      {G} Pal13[w+1] := 0;
      {B} Pal13[w+2] := 0;
      Inc(w,3);
   End;
   {cervena}
   For b := 96 to 159 do {64}
   Begin
      {v puli = oranzova}
      {R} Pal13[w]   := 63;
      {G} Pal13[w+1] := b - 96;
      {B} Pal13[w+2] := 0;
      Inc(w,3);
   End;
   {zluta}
   For b := 160 to 223 do {64}
   Begin
      {R} Pal13[w]   := 63;
      {G} Pal13[w+1] := 63;
      {B} Pal13[w+2] := b - 160;
      Inc(w,3);
   End;
   {bila}
   For b := 224 to 255 do
   Begin
      {R} Pal13[w]   := (255 - b) Shl 1;
      {G} Pal13[w+1] := (255 - b) Shl 1;
      {B} Pal13[w+2] := (255 - b) Shl 1;
      Inc(w,3);
   End;
   {cerna}
   LoadPal;
End;
 
 
Procedure ZobrazSchranku13; assembler;
Asm  {0..199}
{cekani na paprsek}
   mov dx,3dah
@1:in  al,dx
   and al,8
   jz  @1
@2:in  al,dx
   and al,8
   jnz @2
{}
    Push   ds
    mov    AX,SCR13
    mov    ES,ax
    Xor    DI,Di                {nastaven segment a offset cile ES:DI}
    LDS    SI,Schranka13    {nastaven segment a offset startu DS:SI}
    MOV    CX,16000            {kolikrat se bude opakovat rep}
    DB     66h                {32 bit instrukce?}
    REP    MOVSW                {rep = IF cx>0 then cx := cx - 1}
    Pop    ds
End;
 
 
Procedure UlozSchranku13; assembler;
Asm  {0..199}
    Push   ds
    mov    AX,SCR13
    LES    DI,Schranka13  {nastaven segment a offset cile ES:DI}
    MOV    DS,ax
    Xor    SI,SI                {nastaven segment a offset startu DS:SI}
    MOV    CX,16000            {kolikrat se bude opakovat rep}
    DB     66h                {32 bit instrukce?}
    REP    MOVSW                {rep = IF cx>0 then cx := cx - 1}
    Pop    ds
End;
 
 
Procedure FillPoly(Pocet:word;var Seznam);
Var
  S:Array[1..1000] of PointType absolute Seznam;
  DeltaX,DeltaY:Array[1..1000] of Integer;
  Pomocny:Array[1..1000] of Integer Absolute DeltaY;
  MinY,MaxY,Y,x1,x2:Integer;
  a,a2,Sum:Word;
  PrusecikX:Array[1..1000] of Integer;
  ZmenaStoupani:Boolean;
  L:LongInt;
  SegObr,OfsObr,OfsBodu:Word;
 
  Procedure Serad(Pocet:Word;Var IntegerBuffer);
  Var
     S:Array[1..1000] of Integer absolute IntegerBuffer;
     a,b:Word;
     i:Integer;
  Begin
     For a := 2 to Pocet do
     Begin
        For b := a downto 2 do
        Begin
          IF S[b] < S[b-1] Then
          Begin
             i      := S[b-1];
             S[b-1] := S[b];
             S[b]   := i;
          End
        Else Break;
        End;
    End;
  End;
 
Begin
  IF AktObraz13 then
  Begin
     SegObr := SCR13;
     OfsObr := 0;
  End
  Else begin
     SegObr := Seg(Schranka13^);
     OfsObr := Ofs(Schranka13^);
  End;
  For a := 1 To Pocet do Pomocny[a] := S[a].Y;
  Serad(Pocet,Pomocny);
  MinY := Pomocny[1];
  MaxY := Pomocny[Pocet];
  If MinY < 0 then MinY := 0;
  If MinY>199 then Exit;
  If MaxY>199 then MaxY := 199;
  If MaxY < 0 then Exit;
 
  DeltaX[1] := S[1].X - S[Pocet].X;
  DeltaY[1] := S[1].Y - S[Pocet].Y;
  For a := 2 to Pocet do DeltaX[a] := S[a].X - S[a-1].X;
  For a := 2 to Pocet do DeltaY[a] := S[a].Y - S[a-1].Y;
  DeltaX[Pocet+1] := DeltaX[1];
  DeltaY[Pocet+1] := DeltaY[1];
 
  For Y := MinY to MaxY do
  Begin
    Sum := 0;
    For a := 1 to Pocet do
    Begin
      IF a = 1 Then a2 := Pocet Else a2 := a - 1;
      ZmenaStoupani := Not (((DeltaY[a]>0) And (DeltaY[a+1]>0)) Or ((DeltaY[a]<0) And (DeltaY[a+1]<0)));
      {Test zda y protina usecku d(a,a2)}
      IF (S[a].y >= y) or (S[a2].y >= y) Then 
      IF (S[a].y <= y) or (S[a2].y <= y) Then 
      IF Not (S[a].y = S[a2].y) {vod primka, DeltaY = 0} Then 
      IF ZmenaStoupani OR (S[a].y <> y) Then Begin
        Sum := Sum + 1;
        L := y - S[a2].y; {jinak to obcas pretece}
{        PrusecikX[Sum] := L*DeltaX[a] div DeltaY[a] + S[a2].x;}
        L := L*DeltaX[a];
        IF ((L > 0) And (DeltaY[a] > 0)) Or ((L < 0) And (DeltaY[a] < 0)) Then
          PrusecikX[Sum] := (L + DeltaY[a] Div 2) div DeltaY[a] + S[a2].x
        Else
          PrusecikX[Sum] := (L - DeltaY[a] Div 2) div DeltaY[a] + S[a2].x;
      End;
    End;
    If Sum = 0 Then Continue;
    If Odd(Sum) Then OutText('Chyba pri vybarvovani n-uhelniku'#13); {nastane nekdy pokud jsou 2 totozne body(1= posledni)}
    Serad(Sum,PrusecikX);
    OfsBodu := OfsObr + y Shl 8 + y Shl 6;
    For a := 1 To Sum SHR 1 do
    Begin
      x1 := PrusecikX[(a SHL 1)-1];
      x2 := PrusecikX[(a SHL 1)];
      IF (x2 < 0) OR (x1 > 319) Then Continue;
      IF x1 < 0 then x1 := 0;
      IF x2 > 319 then x2 := 319;
      FillChar(Ptr(SegObr,OfsBodu + x1)^,x2-x1+1,Color13);
    End;
  End;
End;
 
 
End.