;------------------------------------------------------------------------------------------
; Адаптация процедуры: "Алгоритм Брезенхема для генерации эллипса"  
; Апрель 2017 - 12:49 | Консманов Алексей    http://grafika.me/node/658


; честно в алгоритме нифига не понял, адаптировал, перевёл в асм.
; При равных полуосях наблюдается лёгкая несимметрия - крайние боковые
; вертикальные линии короче верхних/нижних горизонтальных на пару пикселей.
; После экспериментов часть кода просто выкинул, как несущественно влияющую на результат ))   /DA

EL_     

;procedure DrawEllipse (x, y, a, b : Integer; color: TColor);  //a, b - полуоси
;begin
; a_sqr:=a*a;   //a^2
; b_sqr:=b*b;   //b^2
; row:=b;
; col:=0;

          ld a,0
.a    EQU $-1
          call mulsAA  ; hl=a*a         
          ld (.a_sqr),hl
          
          ld a,0
.b    EQU $-1
          ld (.row),a
          push af    
          call mulsAA  ; hl=a*a
          ld (.b_sqr),hl
          xor a
          ld (.col),a
          pop af     ; (.row)
                      
; d:=2*a_sqr*((row-1)*(row))+a_sqr+2*b_sqr-2*b_sqr*a_sqr;  

          ld h,a
          dec a
          call MULS    ; HL = A*H  :>  (row-1)*(row)
          ex de,hl
          ld hl,(.a_sqr)
          push hl     
          call mulDEHL  ; dehl=de*hl  :> a_sqr*((row-1)*(row))
          call X2dehl   ; dehl=2*dehl :> 2*a_sqr*((row-1)*(row))
          pop bc
          push bc
          call dehlADDbc  ; dehl=dehl+bc :> 2*a_sqr*((row-1)*(row))+a_sqr
          ld bc,(.b_sqr)
          call dehlADDbc
          call dehlADDbc  ; dehl=dehl+bc :> 2*a_sqr*((row-1)*(row))+a_sqr+2*b_sqr         
          ex (sp),hl    ; hl=.a_sqr
          push de
          ex de,hl
          call mulDEBC  ; dehl=de*bc  :> b_sqr*a_sqr
          call X2dehl   ; dehl=2*dehl :> 2*b_sqr*a_sqr
     ;     ld (.asMbs),hl
     ;     ld (.asMbs_),de

          ld c,l
          ld b,h        ; debc=2*b_sqr*a_sqr
          ld a,e
          ex af,af'
          ld a,d        ; aa'bc=2*b_sqr*a_sqr
          pop de
          pop hl        ; dehl=2*a_sqr*((row-1)*(row))+a_sqr+2*b_sqr
          call dehlSUBaAbc   ; dehl=dehl-aa'bc 
          ld (.d),hl
          ld (.d2),de

;  while (a_sqr*row > b_sqr*col) do
.while         
          ld de,#0000
.b_sqr  EQU $-2
          ld bc,#0000
.col    EQU $-2                    
          call mulDEBC  ; dehl=de*bc  :> b_sqr*col
          push hl
          push de
          ld de,#0000
.a_sqr  EQU $-2
          ld bc,#0000
.row    EQU $-2                    
          call mulDEBC  ; dehl=de*bc  :> a_sqr*row
          ex de,hl
          pop bc
          or a
          sbc hl,bc
          pop bc
         jr c,.ew_         ; while exit
         jr nz,1F         ; yes
          ex de,hl
          sbc hl,bc
         jr c,.ew_        ; while exit
         jr z,.ew_
1             
;      begin

             call .pixels  ; вывод пикселей 
             
;           if d >= 0 then
            ld a,(.d2+1)
            and 128      ; sign for bit 7
           jr nz,.ei1_        ; else

;           begin
;                row:=row-1;
;                d:=d-4*a_sqr*row;
;           end;
            ld hl,(.row)
            dec l        
            ld (.row),hl
            ld de,(.a_sqr)
            call mulDEHL  ; dehl=de*hl
            call X2dehl
            call X2dehl   ; 4*a_sqr*row
            ld c,l
            ld b,h
            ld a,e
            ex af,af'
            ld a,d        ; aa'bc=dehl
            ld hl,#0000
.d        EQU $-2
            ld de,#0000
.d2       EQU $-2  
            call dehlSUBaAbc    ; dehl=dehl-aa'bc :> d-4*a_sqr*row;
            ld (.d),hl
            ld (.d2),de
.ei1_

;           d:=d+6*b_sqr+4*b_sqr*col ; 
    ; как показала практика, '6*b_sqr' можно выкинуть - искажения незаметны 
    ; остаётся d:=d+4*b_sqr*col                                              /DA
;           col:=col+1;
            ld hl,(.col)
            inc l
            ld (.col),hl   ; col:=col+1;
        ;    dec l
            ld de,(.b_sqr)            
            call mulDEHL  ; dehl=de*hl
            call X2dehl   ; 2*b_sqr*col
            call X2dehl   ; 4*b_sqr*col
            ld bc,(.d)
            ld a,(.d2)
            ex af,af'
            ld a,(.d2+1)
            call dehlADDaAbc ; dehl=dehl+aa'bc
            ld (.d),hl
            ld (.d2),de
;      end;                        
          jp .while
          
.ew_ 
           
 ; d:=2*b_sqr*(col+1)*col+2*a_sqr*(row*(row-2)+1)+b_sqr-2*a_sqr*b_sqr
 
 ; как показала практика этими вычислениями в нашем случае можно пренебречь  /DA

;           ld a,(.col)
;           ld h,a
;           ld l,0
;           inc a
;          jr z,1F    ; если col+1=256
;           call MULS    ; HL = A*H
;1           ; hl=(col+1)*col
;           ld de,(.b_sqr)
;           call mulDEHL  ; dehl=de*hl  :> b_sqr*(col+1)*col
;           call X2dehl   ; dehl=2*dehl :> 2*b_sqr*(col+1)*col
;          push hl
;          push de
;           ld a,(.row)
;           ld h,a
;           ld l,0
;           dec a
;           dec a
;           call MULS    ; HL = A*H  :> row*(row-2)
;           inc hl
;           ld de,(.a_sqr)
;           call mulDEHL  ; dehl=de*hl  :> a_sqr*(row*(row-2)+1)
;           call X2dehl   ; dehl=2*dehl :> 2*a_sqr*(row*(row-2)+1)
;          pop bc
;           ld a,c
;           ex af,af'
;           ld a,b
;          pop bc            ; aa'bc = 2*b_sqr*(col+1)*col
;           call dehlADDaAbc  ; dehl=dehl+aa'bc :> 2*b_sqr*(col+1)*col+2*a_sqr*(row*(row-2)+1)
;           ld bc,(.b_sqr)
;           call dehlADDbc    ; dehl=dehl+bc :> 2*b_sqr*(col+1)*col+2*a_sqr*(row*(row-2)+1)+b_sqr
;           ld bc,#0000
;.asMbs_  EQU $-2
;           ld a,c
;           ex af,af'
;           ld a,b
;           ld bc,#0000         ; aa'bc=2*a_sqr*b_sqr
;.asMbs   EQU $-2
;          call dehlSUBaAbc ; dehl=dehl-aa'bc 
;          ld (.d),hl
;          ld (.d2),de 




;  while ((row)+1)<>0 do
.while_      ld a,(.row)
             inc a
            ret z
;     begin
            call .pixels  ; вывод пикселей 
            
;          if d<=0 then
           ld a,(.d2+1)
           and 128      ; sign for bit 7
          jr z,.ei2_        ; else
      ;     ld hl,(.d)
      ;     ld de,(.d2)
      ;     ld a,h
      ;     or l
      ;     or d
      ;     or e
      ;    jr z,1F
      ;     bit 7,d
      ;    jr z,.ei2_
1          
;          begin
;                col:=col+1;
;                d:=d+4*b_sqr*col;
;          end;
            ld hl,(.col)
            inc l
            ld (.col),hl   ; col:=col+1;
            ld de,(.b_sqr)            
            call mulDEHL  ; dehl=de*hl
            call X2dehl   ; dehl=2*dehl
            call X2dehl   ; dehl=2*dehl :> 4*b_sqr*col
            ld bc,(.d2)
            ld a,c
            ex af,af'
            ld a,b
            ld bc,(.d)         
            call dehlADDaAbc             ; dehl=dehl+aa'bc
            ld (.d),hl
            ld (.d2),de
.ei2_      
  
       ;    row:=row-1;
       ;   d:=d+6*a_sqr-4*a_sqr*row;
    ; как показала практика, '6*a_sqr' можно выкинуть - искажения незаметны 
    ; остаётся d:=d-4*a_sqr*row                                              /DA
        
       ;     ld hl,(.a_sqr)
       ;     xor a
       ;     ld c,a
       ;     ld d,h
       ;     ld e,l
       ;     add hl,hl   ; *2
       ;     adc a,c
       ;     add hl,de   ; *3
       ;     adc a,c
       ;     add hl,hl   ; *6
       ;     adc a,c
       ;     ld e,a
       ;     ld d,c      ; dehl=6*a_sqr
       ;     ld bc,(.d2)
       ;     ld a,c
       ;     ex af,af'
       ;     ld a,b
       ;     ld bc,(.d)
       ;     call dehlADDaAbc   ; dehl=dehl+aa'bc :> d+6*a_sqr
       ;    push hl
       ;    push de 
            ld hl,(.row)
            dec l
            ld (.row),hl
            add hl,hl
            add hl,hl   ; *4
            ld de,(.a_sqr)
            call mulDEHL  ; dehl=de*hl :> (row*4*a_sqr)
            ld b,h
            ld c,l
            ld a,e
            ex af,af'
            ld a,d    ; aa'bc=(row*4*a_sqr)
       ;     pop de
       ;     pop hl
             ld hl,(.d)
             ld de,(.d2)
            call dehlSUBaAbc ; dehl=dehl-aa'bc :> d-(row*4*a_sqr)
            ld (.d),hl
            ld (.d2),de           
;      end;
           jp .while_

;end;
        
                    
.resIncX   ex af,af'         ; EL_.resIncX
           xor a 
           ld (.incX),a
           ex af,af'
          ret
.resIncY   ex af,af'         ; EL_.resIncY
           xor a
          jr 1F          
.setIncXY  ex af,af'
           ld a,1            ; EL_.setIncXY
.setAIncXY ld (.incX),a      ; EL_.setAIncXY
1          ld (.incY),a
           ex af,af'
          ret        

            
.pixels 
;          Form1.PaintBox1.Canvas.Pixels[x+col, y+row]:=color; 
;          Form1.PaintBox1.Canvas.Pixels[x+col, y-row]:=color;
;          Form1.PaintBox1.Canvas.Pixels[x-col, y+row]:=color;
;          Form1.PaintBox1.Canvas.Pixels[x-col, y-row]:=color;
           ld a,(.col)
           ld b,a
           ld a,(.row)
           ld c,a
           ld de,#0000
.x0    EQU $-1
.y0    EQU $-2

           ld a,d
           add a,1     ; 1 / 0 
.incX   EQU $-1       ; .incX / .incY* нужны когда используются четные диаметры
           rl l   ; fc
           add a,b
           ld h,a   ; x
           rla      ; fc
           or l
           and 1
           ld l,a    ; hl - h -X+col , bit 0,l - sign
           ld (.xPcol),hl   ; 

           ld a,d
           sub b
           ld h,a
           rla
           and 1
           ld l,a
           ld (.xMcol),hl 
    
           ld a,e
           add a,1      ; 1 / 0       
.incY  EQU $-1      ; .incX / .incY* нужны когда используются четные диаметры
           add a,c
          jr c, 1F
           cp 197
          jr c,2F
1          ld a,220    ; позиция Y не выводится
2          ld (.yProw),a
           
           ld a,e
           sub c
          jr nc,1F
           cp 250
          jr nc,1F
           ld a,220    ; позиция Y не выводится  
1          ld (.yMrow),a  

           ld de,#0000   ; x+col
.xPcol    EQU $-2
           ld a,e
           rra
          jr nc,1F
           ld a,d   ; x>255
           cp 5
          jr nc,2F      ; пропуск если больше
1          call .yProwSet  ; de= x+col                              
           call .yMrowSet          
2          ld de,#0000  ; x-col    EL_.xMcol
.xMcol    EQU $-2
           ld a,e
           rra
          jr nc,1F
           ld a,d
           cp 250
          ret c          ; пропуск если меньше
1          call .yProwSet  ; de= x-col

.yMrowSet   ld a,#00
.yMrow    EQU $-1
            ld b,a
            cp 220
           ret z         ; пропуск если не выводится
.setplot    push de
            push bc
            ld a,e
            ld e,b           
            call PlotOb.HiX
.AddrPlot  EQU $-2
            pop bc
            pop de
           ret
         
.yProwSet   
            ld a,#00
.yProw    EQU $-1           
            ld b,a
            cp 220
           ret z      ; пропуск если не выводится
           jr .setplot           
            
;-------------------------------------------