unit asem256;
interface
uses crt;
procedure init;
procedure pix(x,y,c:integer);
function getpix(x,y:integer):integer;
procedure setpal(i,r,g,b:byte);
Procedure Circle (Xx,Yy,rad:integer;Col:Byte);
Procedure line(a,b,c,d,col:integer);
Procedure GetPal(ColorNo : Byte; Var R,G,B : Byte);
procedure flipx;
procedure flipy;
procedure WaitRetrace;
Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte);
implementation
procedure init;
begin
asm
mov ax,13h
int 10h
end;
end;
procedure pix(x,y,c:integer);
begin
mem[$a000:y*320+x]:=c;
end;
function getpix(x,y:integer):integer;
begin
getpix:=mem[$a000:x+y*320];
end;
procedure setpal(i,r,g,b:byte);
begin
port[$3c8]:=i;
port[$3c9]:=r;
port[$3c9]:=g;
port[$3c9]:=b;
end;
Procedure Circle (Xx,Yy,rad:integer;Col:Byte);
  { This draws a circle with centre X,Y, with Rad as it's radius }
VAR deg:real;
    x,y:integer;
BEGIN
  deg:=0;
  repeat
    X:=round(rad*COS (deg));
    Y:=round(rad*sin (deg));
    pix(x+xx,y+yy,col);
    deg:=deg+0.005;
  until (deg>6.4);
END;
Procedure line(a,b,c,d,col:integer);
  { This draws a line from a,b to c,d of color col. }
   Function sgn(a:real):integer;
   BEGIN
        if a>0 then sgn:=+1;
        if a<0 then sgn:=-1;
        if a=0 then sgn:=0;
   END;
var u,s,v,d1x,d1y,d2x,d2y,m,n:real;
    i:integer;
BEGIN
     u:= c - a;
     v:= d - b;
     d1x:= SGN(u);
     d1y:= SGN(v);
     d2x:= SGN(u);
     d2y:= 0;
     m:= ABS(u);
     n := ABS(v);
     IF NOT (M>N) then
     BEGIN
          d2x := 0 ;
          d2y := SGN(v);
          m := ABS(v);
          n := ABS(u);
     END;
     s := INT(m / 2);
     FOR i := 0 TO round(m) DO
     BEGIN
          pix(a,b,col);
          s := s + n;
          IF not (s<m) THEN
          BEGIN
               s := s - m;
               a:= a +round(d1x);
               b := b + round(d1y);
          END
          ELSE
          BEGIN
               a := a + round(d2x);
               b := b + round(d2y);
          END;
     END;
END;
Procedure GetPal(ColorNo : Byte; Var R,G,B : Byte);
  { This reads the values of the Red, Green and Blue values of a certain
    color and returns them to you. }
Begin
   Port[$3c7] := ColorNo;
   R := Port[$3c9];
   G := Port[$3c9];
   B := Port[$3c9];
End;
procedure flipx;
var i,j,b,a:integer;

begin
for j:=0 to 100 do
  for i:=0 to 319 do begin
    a:=getpix(i,j);
    b:=getpix(i,199-j);
    pix(i,j,b);
    pix(i,199-j,a);
 end;
end;
procedure flipy;
var i,j,b,a:integer;

begin
for j:=0 to 160 do
  for i:=0 to 199 do begin
    a:=getpix(j,i);
    b:=getpix(319-j,i);
    pix(j,i,b);
    pix(319-j,i,a);
 end;
end;
procedure WaitRetrace; assembler;
  {  This waits for a vertical retrace to reduce snow on the screen }
label
  l1, l2;
asm
    mov dx,3DAh
l1:
    in al,dx
    and al,08h
    jnz l1
l2:
    in al,dx
    and al,08h
    jz  l2
end;
Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte);
  { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
    in color col }
var
  x:integer;
  mny,mxy:integer;
  mnx,mxx,yc:integer;
  mul1,div1,
  mul2,div2,
  mul3,div3,
  mul4,div4:integer;

begin
  mny:=y1; mxy:=y1;
  if y2<mny then mny:=y2;
  if y2>mxy then mxy:=y2;
  if y3<mny then mny:=y3;
  if y3>mxy then mxy:=y3;    { Choose the min y mny and max y mxy }
  if y4<mny then mny:=y4;
  if y4>mxy then mxy:=y4;

  if mny<0 then mny:=0;
  if mxy>199 then mxy:=199;
  if mny>199 then exit;
  if mxy<0 then exit;        { Verticle range checking }

  mul1:=x1-x4; div1:=y1-y4;
  mul2:=x2-x1; div2:=y2-y1;
  mul3:=x3-x2; div3:=y3-y2;
  mul4:=x4-x3; div4:=y4-y3;  { Constansts needed for intersection calc }

  for yc:=mny to mxy do
    begin
      mnx:=320;
      mxx:=-1;
      if (y4>=yc) or (y1>=yc) then
        if (y4<=yc) or (y1<=yc) then   { Check that yc is between y1 and y4 }
          if not(y4=y1) then
            begin
              x:=(yc-y4)*mul1 div div1+x4; { Point of intersection on x axis }
              if x<mnx then
                mnx:=x;
              if x>mxx then
                mxx:=x;       { Set point as start or end of horiz line }
            end;
      if (y1>=yc) or (y2>=yc) then
        if (y1<=yc) or (y2<=yc) then   { Check that yc is between y1 and y2 }
          if not(y1=y2) then
            begin
              x:=(yc-y1)*mul2 div div2+x1; { Point of intersection on x axis }
              if x<mnx then
                mnx:=x;
              if x>mxx then
                mxx:=x;       { Set point as start or end of horiz line }
            end;
      if (y2>=yc) or (y3>=yc) then
        if (y2<=yc) or (y3<=yc) then   { Check that yc is between y2 and y3 }
          if not(y2=y3) then
            begin
              x:=(yc-y2)*mul3 div div3+x2; { Point of intersection on x axis }
              if x<mnx then
                mnx:=x;
              if x>mxx then
                mxx:=x;       { Set point as start or end of horiz line }
            end;
      {q}
      if (y3>=yc) or (y4>=yc) then
        if (y3<=yc) or (y4<=yc) then   { Check that yc is between y3 and y4 }
          if not(y3=y4) then
            begin
              x:=(yc-y3)*mul4 div div4+x3; { Point of intersection on x axis }
              if x<mnx then
                mnx:=x;
              if x>mxx then
                mxx:=x;       { Set point as start or end of horiz line }
            end;
      if mnx<0 then
        mnx:=0;
      if mxx>319 then
        mxx:=319;          { Range checking on horizontal line }
      if mnx<=mxx then
        line (mnx,yc,mxx+1,yc,color);   { Draw the horizontal line }
    end;
  end;
end.