{$N+,A+,G+,F+,D-,E-,L-,R-,S-,Q-,Y-,I-}

{fast fill circle with precals table}
unit circles;

interface
{PROCEDURE PrecalsCircle(radius:Integer;mas:word);}
Procedure FillCircle5(x,y, r:integer;col:byte; mas, where:word);
Procedure FillCircle5_without_cut(x,y, r:integer;col:byte; mas, where:word);



implementation

{
PROCEDURE PrecalsCircle(radius:Integer;mas:word);
VAR
   CenterX,CenterY,X,Y,m, offs:Integer;
BEGIN
      offs:=(radius*2)*4*64;
      CenterX:=radius;
      CenterY:=radius;
      x := 0;
      y := radius;
      m := 5 - 4 * radius;

      while (x <= y) do
      begin
        memw[mas:word(offs+(centerY-x) shl 2)]  :=centerX - y;
        memw[mas:word(offs+(centerY-x) shl 2+2)]:=centerX + y;
        memw[mas:word(offs+(centerY+x) shl 2)]  :=centerX - y;
        memw[mas:word(offs+(centerY+x) shl 2+2)]:=centerX + y;

        if (m > 0) then
        begin
          memw[mas:word(offs+(centerY-y) shl 2)]  :=centerX - x;
          memw[mas:word(offs+(centerY-y) shl 2+2)]:=centerX + x;
          memw[mas:word(offs+(centerY+y) shl 2)]  :=centerX - x;
          memw[mas:word(offs+(centerY+y) shl 2+2)]:=centerX + x;
          dec(y);
          m := m - 8 * y;
        end;
        inc(x);
        m:= m + (8 * x + 4);
      end;
end;
}

Procedure FillCircle5(x,y, r:integer;col:byte; mas, where:word);
var d, offs, di_offs, height:word;
begin

if (r<1) or (y-r>199) or (y+r<0) or (x-r>319) or (x+r<0) then exit;

d:=r shl 1;
offs:=word(r shl 9{*2*4*64});
if (y-r)<0 then begin
    di_offs:=0;
    offs:=offs+abs(y-r)*4;
    height:=r shl 1 + (y-r)+1;
end else begin
    if (y+r)<200 then height:=d+1 else height:=d - (y+r-200);
    di_offs:=y-r;
    end;
asm
  mov es, where
  mov si, offs

  mov dx, x

  {imul di, di_offs, 320}
    mov ax, di_offs
    xchg ah, al
    mov  di, ax
    shr  di, 2
    add  di, ax


  mov  bl, col  {set eax to color}
  mov  bh, bl
  mov  ax, bx
  db $66; shl ax, 16
  mov  ax, bx

  mov bx, r
  mov cx, height

  push ds
  push bp
  mov ds, mas
  mov bp, dx
  sub bp, bx

  @line: {  for n:=0 to r*2 do begin}
     db $66; mov bx, ds:[si]   {x1:=memw[mas:offs+(n shl 2)]-r;}
     db $66,$0f,$a4,$da,$10    {shld edx, ebx, 16} {mov dx, ds:[si+2] {x2:=memw[mas:offs+(n shl 2)+2]-r;}

     add bx, bp
     cmp bx, 319; jg @next
     add dx, bp
     js @next

     cmp bx, 0; jge @sk_x1_to_zero; xor bx, bx; @sk_x1_to_zero:
     cmp dx, 320;jl @sk_x2_to_w; mov dx, 319; @sk_x2_to_w:

        push di
        {DrawLineH(x1+x, x2+x, y+n-r, col, where);}
        add  di, bx     {start offset}
        inc  dx
        sub  dx, bx     {length}

                 test dx, 65520
                 jz @length_less_sixteen
                 mov  bx, dx
                 shr  bx, 4
                 @l16:
                    db $66; mov es:[di], ax
                    db $66; mov es:[di+4], ax
                    db $66; mov es:[di+8], ax
                    db $66; mov es:[di+12], ax
                    add di, 16
                    dec bx
                 jnz @l16

             @length_less_sixteen:
                 mov bx, dx
                 and bx, 15
                 shr bx, 2
                 jz @length_less_four
                 @l4:
                    db $66; mov es:[di], ax
                    add di, 4
                    dec bx
                 jnz @l4

             @length_less_four:
                 test dx, 2
                 jz @length_less_two
                    mov es:[di], ax
                    add di, 2
             @length_less_two:
                 test dx, 1
                 jz @exit
                    mov es:[di], al

             @exit:
        pop di
  @next:
  add di, 320
  add si, 4
  dec cx
  jnz @line
  pop bp
  pop ds
end;
end;

Procedure FillCircle5_without_cut(x,y, r:integer;col:byte; mas, where:word);
var d, offs, di_offs, height:word;
begin
if (r<1) or (y-r>199) or (y+r<0) or (x-r>319) or (x+r<0) then exit;
d:=r shl 1;
offs:=word(r shl 9{*2*4*64});
if (y-r)<0 then begin
    di_offs:=0;
    offs:=offs+abs(y-r)*4;
    height:=r shl 1 + (y-r)+1;
end else begin
    if (y+r)<200 then height:=d+1 else height:=d - (y+r-200);
    di_offs:=y-r;
    end;
asm
  mov es, where
  mov si, offs

  mov dx, x

  {imul di, di_offs, 320}
    mov ax, di_offs
    xchg ah, al
    mov  di, ax
    shr  di, 2
    add  di, ax

  sub dx, r
  add di, dx

  mov  bl, col  {set eax to color}
  mov  bh, bl
  mov  ax, bx
  db $66; shl ax, 16
  mov  ax, bx

  mov cx, height

  push ds
  push bp
  mov ds, mas

  @line: {  for n:=0 to r*2 do begin}
     db $66; mov bx, ds:[si]   {x1:=memw[mas:offs+(n shl 2)]-r;}
     db $66,$0f,$a4,$da,$10    {shld edx, ebx, 16} {mov dx, ds:[si+2] {x2:=memw[mas:offs+(n shl 2)+2]-r;}

        mov bp, di {push di}
        {DrawLineH(x1+x, x2+x, y+n-r, col, where);}
        add  di, bx     {start offset}
        inc  dx
        sub  dx, bx     {length}

                 test dx, 65520
                 jz @length_less_sixteen
                 mov  bx, dx
                 shr  bx, 4
                 @l16:
                    db $66; mov es:[di], ax
                    db $66; mov es:[di+4], ax
                    db $66; mov es:[di+8], ax
                    db $66; mov es:[di+12], ax
                    add di, 16
                    dec bx
                 jnz @l16

             @length_less_sixteen:
                 mov bx, dx
                 and bx, 15
                 shr bx, 2
                 jz @length_less_four
                 @l4:
                    db $66; mov es:[di], ax
                    add di, 4
                    dec bx
                 jnz @l4

             @length_less_four:
                 test dx, 2
                 jz @length_less_two
                    mov es:[di], ax
                    add di, 2
             @length_less_two:
                 test dx, 1
                 jz @exit
                    mov es:[di], al
             @exit:
        mov di, bp {pop di}
  @next:
  add di, 320
  add si, 4
  dec cx
  jnz @line
  pop bp
  pop ds
end;
end;


end.