]> 4ch.mooo.com Git - 16.git/blobdiff - 16/xlib/xcircle.asm
refresh wwww
[16.git] / 16 / xlib / xcircle.asm
diff --git a/16/xlib/xcircle.asm b/16/xlib/xcircle.asm
new file mode 100755 (executable)
index 0000000..4e75031
--- /dev/null
@@ -0,0 +1,710 @@
+;-----------------------------------------------------------------------\r
+;\r
+; MODULE XCIRCLE\r
+;\r
+;   This module was written by Matthew MacKenzie\r
+;   matm@eng.umd.edu\r
+;\r
+; Circles, full and empty.\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+; ****** XLIB - Mode X graphics library                ****************\r
+; ******                                               ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+include xlib.inc\r
+include xcircle.inc\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_circle\r
+;\r
+; Draw a circle.\r
+;\r
+; C near-callable as:\r
+; int x_circle (WORD Left, WORD Top, WORD Diameter,\r
+;                WORD Color, WORD ScreenOffs);\r
+;\r
+; No clipping is performed.\r
+;\r
+; ax, bx, cx, and dx bite the dust, as Homer would say.\r
+\r
+; we plot into eight arcs at once:\r
+;      4 0\r
+;    6 \|/ 2\r
+;     --*--\r
+;    7 /|\ 3\r
+;      5 1\r
+;\r
+; 0, 1, 4, and 5 are considered x-major; the rest, y-major.\r
+;\r
+; The x-major plots grow out from the top and bottom of the circle,\r
+; while the y-major plots start at the left and right edges.\r
+\r
+       .data\r
+\r
+       align 2\r
+\r
+ColumnMask      db      011h,022h,044h,088h\r
+\r
+       .code\r
+\r
+       public _x_circle\r
+       align   2\r
+_x_circle proc\r
+ARG Left:word, Top:word, Diameter:word, Color:word, ScreenOffs:word\r
+LOCAL offset0,offset1,offset2,offset3,offset4,offset5,offset6,offset7,mask0n1,mask2n3,mask4n5,mask6n7,shrunk_radius,diameter_even,error:word=LocalStk\r
+; Tasm 1.0 does not allow the \ line continuation\r
+;LOCAL offset0:word, offset1:word, offset2:word, offset3:word, \\r
+;        offset4:word, offset5:word, offset6:word, offset7:word, \\r
+;        mask0n1:word, mask2n3:word, mask4n5:word, mask6n7:word, \\r
+;        shrunk_radius:word, diameter_even:word, error:word=LocalStk\r
+\r
+       push bp\r
+       mov  bp, sp\r
+       sub  sp, LocalStk\r
+       push si\r
+       push di\r
+       push ds\r
+\r
+; find starting locations of plots 2, 3, 6, and 7\r
+       mov di, _ScrnLogicalByteWidth\r
+       xor dx, dx\r
+\r
+       mov ax, Diameter    ; find vertical midpoint\r
+       dec ax\r
+       shr ax, 1\r
+       adc dx, 0           ; remember if it's rounded\r
+       mov shrunk_radius, ax ; radius, rounded down for adding\r
+       mov diameter_even, dx ; (diameter - 1) & 1, effectively\r
+       add ax, Top\r
+       mul di              ; vertical midpoint in bytes\r
+       add ax, ScreenOffs\r
+\r
+       mov bx, Left\r
+       mov cx, bx          ; save for later\r
+       mov si, bx\r
+       shr si, 2\r
+       add si, ax\r
+       mov offset6, si\r
+       and bx, 3           ; column of left side\r
+       mov bl, ColumnMask[bx]\r
+       mov mask6n7, bx\r
+\r
+       add cx, Diameter\r
+       dec cx\r
+       mov bx, cx\r
+       shr cx, 2\r
+       add cx, ax\r
+       mov offset2, cx\r
+       and bx, 3           ; column of right side\r
+       mov bl, ColumnMask[bx]\r
+       mov mask2n3, bx\r
+\r
+       cmp diameter_even, 1\r
+       jne @@MiddlePlotsOverlap\r
+       add si, di\r
+       add cx, di\r
+@@MiddlePlotsOverlap:\r
+       mov offset7, si\r
+       mov offset3, cx\r
+\r
+; starting locations of 0, 1, 4, and 5\r
+       mov bx, Left\r
+       add bx, shrunk_radius ; find horizontal midpoint\r
+\r
+       mov ax, Top         ; top in bytes\r
+       mul di\r
+       add ax, ScreenOffs\r
+       mov si, ax\r
+\r
+       mov ax, Diameter    ; bottom in bytes\r
+       dec ax\r
+       mul di\r
+       add ax, si\r
+\r
+       mov di, bx          ; horizontal midpoint in bytes\r
+       shr di, 2\r
+       add si, di              ; top midpoint in bytes\r
+       mov offset4, si\r
+       add di, ax              ; bottom midpoint in bytes\r
+       mov offset5, di\r
+       and bx, 3           ; column of horizontal midpoint\r
+       mov bl, ColumnMask[bx]\r
+       mov mask4n5, bx\r
+\r
+       cmp diameter_even, 1\r
+       jne @@TopAndBottomPlotsOverlap\r
+       rol bl, 1\r
+       jnc @@TopAndBottomPlotsOverlap\r
+       inc si\r
+       inc di\r
+@@TopAndBottomPlotsOverlap:\r
+       mov offset0, si\r
+       mov offset1, di\r
+       mov mask0n1, bx\r
+\r
+; we've got our eight plots in their starting positions, so\r
+; it's time to sort out the registers\r
+       mov bx, _ScrnLogicalByteWidth\r
+\r
+       mov dx, SCREEN_SEG\r
+       mov ds, dx\r
+\r
+       mov dx, SC_INDEX    ; set VGA to accept column masks\r
+       mov al, MAP_MASK\r
+       out dx, al\r
+       inc dx              ; gun the engine...\r
+\r
+       mov si, Diameter    ; initial y is radius -- 2 #s per pixel\r
+       inc si\r
+\r
+       mov cx, si\r
+       neg cx\r
+       add cx, 2\r
+       mov error, cx       ; error = -y + one pixel since we're a step ahead\r
+\r
+       xor cx, cx          ; initial x = 0\r
+       mov ah, byte ptr Color\r
+       jmp @@CircleCalc        ; let's actually put something on the screen!\r
+\r
+; move the x-major plots horizontally and the y-major plots vertically\r
+@@NoAdvance:\r
+       mov al, byte ptr mask0n1\r
+       out dx, al\r
+       mov di, offset0     ; plot 0\r
+       mov [di], ah\r
+       rol al, 1           ; advance 0 right\r
+       mov byte ptr mask0n1, al\r
+       adc di, 0\r
+       mov offset0, di\r
+       mov di, offset1\r
+       mov [di], ah        ; plot 1\r
+       ror al, 1           ; what was that bit again?\r
+       adc di, 0           ; advance 1 right\r
+       mov offset1, di\r
+\r
+       mov al, byte ptr mask2n3\r
+       out dx, al\r
+       mov di, offset2\r
+       mov [di], ah        ; plot 2\r
+       sub di, bx          ; advance 2 up\r
+       mov offset2, di\r
+       mov di, offset3\r
+       mov [di], ah        ; plot 3\r
+       add di, bx          ; advance 3 down\r
+       mov offset3, di\r
+\r
+       mov al, byte ptr mask4n5\r
+       out dx, al\r
+       mov di, offset4\r
+       mov [di], ah\r
+       ror al, 1\r
+       mov byte ptr mask4n5, al\r
+       sbb di, 0\r
+       mov offset4, di\r
+       mov di, offset5\r
+       mov [di], ah\r
+       rol al, 1\r
+       sbb di, 0\r
+       mov offset5, di\r
+\r
+       mov al, byte ptr mask6n7\r
+       out dx, al\r
+       mov di, offset6\r
+       mov [di], ah\r
+       sub di, bx\r
+       mov offset6, di\r
+       mov di, offset7\r
+       mov [di], ah\r
+       add di, bx\r
+       mov offset7, di\r
+\r
+       jmp @@CircleCalc\r
+\r
+; move all plots diagonally\r
+@@Advance:\r
+       mov al, byte ptr mask0n1\r
+       out dx, al\r
+       mov di, offset0\r
+       mov [di], ah        ; plot 0\r
+       rol al, 1           ; advance 0 right and down\r
+       mov byte ptr mask0n1, al\r
+       adc di, bx\r
+       mov offset0, di\r
+       mov di, offset1\r
+       mov [di], ah        ; plot 1\r
+       ror al, 1           ; what was that bit again?\r
+       adc di, 0           ; advance 1 right and up\r
+       sub di, bx\r
+       mov offset1, di\r
+\r
+       mov al, byte ptr mask2n3\r
+       out dx, al\r
+       mov di, offset2\r
+       mov [di], ah        ; plot 2\r
+       ror al, 1           ; advance 2 up and left\r
+       mov byte ptr mask2n3, al\r
+       sbb di, bx\r
+       mov offset2, di\r
+       mov di, offset3\r
+       mov [di], ah        ; plot 3\r
+       rol al, 1\r
+       sbb di, 0           ; advance 3 down and left\r
+       add di, bx\r
+       mov offset3, di\r
+\r
+       mov al, byte ptr mask4n5\r
+       out dx, al\r
+       mov di, offset4\r
+       mov [di], ah\r
+       ror al, 1\r
+       mov byte ptr mask4n5, al\r
+       sbb di, 0\r
+       add di, bx\r
+       mov offset4, di\r
+       mov di, offset5\r
+       mov [di], ah\r
+       rol al, 1\r
+       sbb di, bx\r
+       mov offset5, di\r
+\r
+       mov al, byte ptr mask6n7\r
+       out dx, al\r
+       mov di, offset6\r
+       mov [di], ah\r
+       rol al, 1\r
+       mov byte ptr mask6n7, al\r
+       adc di, 0\r
+       sub di, bx\r
+       mov offset6, di\r
+       mov di, offset7\r
+       mov [di], ah\r
+       ror al, 1\r
+       adc di, bx\r
+       mov offset7, di\r
+\r
+; do you realize the entire function has been set up for this little jot?\r
+; keep in mind that radii values are 2 per pixel\r
+@@CircleCalc:\r
+       add cx, 2           ; x += 1\r
+       mov di, error\r
+       add di, cx          ; error += (2 * x) + 1\r
+       inc di\r
+       jl @@CircleNoError\r
+       cmp cx, si          ; x > y?\r
+       ja @@FleeFlyFlowFum\r
+       sub si, 2           ; y -= 1\r
+       sub di, si          ; error -= (2 * y)\r
+       mov error, di\r
+       jmp @@Advance\r
+@@CircleNoError:\r
+       mov error, di\r
+       jmp @@NoAdvance\r
+\r
+@@FleeFlyFlowFum:\r
+       pop ds\r
+       pop di\r
+       pop si\r
+       mov sp,bp\r
+       pop bp\r
+\r
+       ret\r
+\r
+_x_circle endp\r
+\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_filled_circle\r
+;\r
+; Draw a disc.\r
+;\r
+; C near-callable as:\r
+; int x_filled_circle (WORD Left, WORD Top, WORD Diameter,\r
+;                      WORD Color, WORD ScreenOffs);\r
+;\r
+; No clipping is performed.\r
+;\r
+; ax, bx, cx, dx, and es bite the dust, as Homer would say.\r
+; DF is set to 0 (strings go forward).\r
+\r
+       .data\r
+\r
+       align 2\r
+\r
+; the only entries of these tables which are used are positions\r
+; 1, 2, 4, and 8\r
+LeftMaskTable   db      0, 0ffh, 0eeh, 0, 0cch, 0, 0, 0, 088h\r
+RightMaskTable  db             0, 011h, 033h, 0, 077h, 0, 0, 0, 0ffh\r
+\r
+       .code\r
+\r
+       public _x_filled_circle\r
+       align   2\r
+_x_filled_circle proc\r
+ARG Left:word, Top:word, Diameter:word, Color:word, ScreenOffs:word\r
+; Tasm 1.0 does not allow the \ line continuation\r
+;LOCAL offset0:word, offset1:word, offset2:word, offset3:word, \\r
+;        offset4:word, offset5:word, offset6:word, offset7:word, \\r
+;        mask0n1:word, mask2n3:word, mask4n5:word, mask6n7:word, \\r
+;        shrunk_radius:word, diameter_even:word, error:word, \\r
+;        jump_vector:word=LocalStk\r
+LOCAL offset0,offset1,offset2,offset3,offset4,offset5,offset6,offset7,mask0n1,mask2n3,mask4n5,mask6n7,shrunk_radius,diameter_even,error,jump_vector:word=LocalStk\r
+\r
+       push bp\r
+       mov  bp, sp\r
+       sub  sp, LocalStk\r
+       push si\r
+       push di\r
+\r
+       cld                                     ; strings march forward\r
+\r
+; this first part is identical to the other function --\r
+; the only differences, in fact, are in the drawing and moving around\r
+\r
+; find starting locations of plots 2, 3, 6, and 7\r
+       mov di, _ScrnLogicalByteWidth\r
+       xor dx, dx\r
+\r
+       mov ax, Diameter    ; find vertical midpoint\r
+       dec ax\r
+       shr ax, 1\r
+       adc dx, 0           ; remember if it's rounded\r
+       mov shrunk_radius, ax ; radius, rounded down for adding\r
+       mov diameter_even, dx ; (diameter - 1) & 1, effectively\r
+       add ax, Top\r
+       mul di              ; vertical midpoint in bytes\r
+       add ax, ScreenOffs\r
+\r
+       mov bx, Left\r
+       mov cx, bx          ; save for later\r
+       mov si, bx\r
+       shr si, 2\r
+       add si, ax\r
+       mov offset6, si\r
+       and bx, 3           ; column of left side\r
+       mov bl, ColumnMask[bx]\r
+       mov mask6n7, bx\r
+\r
+       add cx, Diameter\r
+       dec cx\r
+       mov bx, cx\r
+       shr cx, 2\r
+       add cx, ax\r
+       mov offset2, cx\r
+       and bx, 3           ; column of right side\r
+       mov bl, ColumnMask[bx]\r
+       mov mask2n3, bx\r
+\r
+       cmp diameter_even, 1\r
+       jne @@MiddlePlotsOverlap\r
+       add si, di\r
+       add cx, di\r
+@@MiddlePlotsOverlap:\r
+       mov offset7, si\r
+       mov offset3, cx\r
+\r
+; starting locations of 0, 1, 4, and 5\r
+       mov bx, Left\r
+       add bx, shrunk_radius ; find horizontal midpoint\r
+\r
+       mov ax, Top         ; top in bytes\r
+       mul di\r
+       add ax, ScreenOffs\r
+       mov si, ax\r
+\r
+       mov ax, Diameter    ; bottom in bytes\r
+       dec ax\r
+       mul di\r
+       add ax, si\r
+\r
+       mov di, bx          ; horizontal midpoint in bytes\r
+       shr di, 2\r
+       add si, di              ; top midpoint in bytes\r
+       mov offset4, si\r
+       add di, ax              ; bottom midpoint in bytes\r
+       mov offset5, di\r
+       and bx, 3           ; column of horizontal midpoint\r
+       mov bl, ColumnMask[bx]\r
+       mov mask4n5, bx\r
+\r
+       cmp diameter_even, 1\r
+       jne @@TopAndBottomPlotsOverlap\r
+       rol bl, 1\r
+       jnc @@TopAndBottomPlotsOverlap\r
+       inc si\r
+       inc di\r
+@@TopAndBottomPlotsOverlap:\r
+       mov offset0, si\r
+       mov offset1, di\r
+       mov mask0n1, bx\r
+\r
+; we've got our eight plots in their starting positions, so\r
+; it's time to sort out the registers\r
+       mov bx, _ScrnLogicalByteWidth\r
+\r
+       mov dx, SCREEN_SEG\r
+       mov es, dx\r
+\r
+       mov dx, SC_INDEX    ; set VGA to accept column masks\r
+       mov al, MAP_MASK\r
+       out dx, al\r
+       inc dx              ; gun the engine...\r
+\r
+       mov si, Diameter    ; initial y is radius -- 2 #s per pixel\r
+       inc si\r
+\r
+       mov cx, si\r
+       neg cx\r
+       add cx, 2\r
+       mov error, cx       ; error = -y + one pixel since we're a step ahead\r
+\r
+       xor cx, cx          ; initial x = 0\r
+       mov ah, byte ptr Color\r
+       jmp @@FilledCircleCalc ; let's actually put something on the screen!\r
+\r
+\r
+; plotting is completely different from in the other function (naturally)\r
+@@PlotLines:\r
+       push cx                         ; we'll need cx for string stores\r
+\r
+; draw x-major horz. lines, from plot 4 to plot 0 and from plot 5 to plot 1\r
+       mov di, mask0n1\r
+       and di, 0000fh          ; we only want the lower nybble for the mask table\r
+       mov al, RightMaskTable[di]\r
+       mov di, offset0         ; left and right offsets the same?\r
+       cmp di, offset4\r
+       jne @@PlotXMajorNontrivial ; try and say this one 10 times fast!\r
+       mov di, mask4n5\r
+       and di, 0000fh\r
+       and al, LeftMaskTable[di] ; intersection of left & right masks\r
+       out dx, al                      ; set mask\r
+       mov di, offset4\r
+       mov es:[di], ah\r
+       mov di, offset5\r
+       mov es:[di], ah\r
+       jmp @@PlotYMajor\r
+@@PlotXMajorNontrivial:\r
+       out dx, al          ; draw right edge\r
+       mov es:[di], ah\r
+       mov di, offset1\r
+       mov es:[di], ah\r
+\r
+       mov di, mask4n5         ; draw left edge\r
+       and di, 0000fh\r
+       mov al, LeftMaskTable[di]\r
+       out dx, al\r
+       mov di, offset4\r
+       mov es:[di], ah\r
+       mov di, offset5\r
+       mov es:[di], ah\r
+\r
+       mov al, 0ffh            ; set mask for middle chunks\r
+       out dx, al\r
+       mov al, ah                      ; ready to store two pixels at a time\r
+       inc di                          ; move string start past left edge\r
+       mov cx, offset1         ; store line from plot 5 to plot 1, exclusive\r
+       sub cx, di                      ; width of section in bytes\r
+       push cx\r
+       shr cx, 1                       ; draw midsection eight pixels at a time\r
+       rep stosw\r
+       adc cx, 0                       ; draw last four pixels, if such there are\r
+       rep stosb\r
+\r
+       mov di, offset4         ; draw line from plot 4 to plot 0\r
+       inc di                          ; move past left edge\r
+       pop cx\r
+       shr cx, 1\r
+       rep stosw\r
+       adc cx, 0\r
+       rep stosb\r
+\r
+@@PlotYMajor:\r
+; draw y-major horz. lines, from plot 6 to plot 2 and from plot 7 to plot 3\r
+       mov di, mask2n3\r
+       and di, 0000fh          ; we only want the lower nybble for the mask table\r
+       mov al, RightMaskTable[di]\r
+       mov di, offset2         ; left and right offsets the same?\r
+       cmp di, offset6\r
+       jne @@PlotYMajorNontrivial ; try and say this one 10 times fast!\r
+       mov di, mask6n7\r
+       and di, 0000fh\r
+       and al, LeftMaskTable[di] ; intersection of left & right masks\r
+       out dx, al                      ; set mask\r
+       mov di, offset6\r
+       mov es:[di], ah\r
+       mov di, offset7\r
+       mov es:[di], ah\r
+       jmp @@ClimaxOfPlot\r
+@@PlotYMajorNontrivial:\r
+       out dx, al          ; draw right edge\r
+       mov es:[di], ah\r
+       mov di, offset3\r
+       mov es:[di], ah\r
+\r
+       mov di, mask6n7         ; draw left edge\r
+       and di, 0000fh\r
+       mov al, LeftMaskTable[di]\r
+       out dx, al\r
+       mov di, offset6\r
+       mov es:[di], ah\r
+       mov di, offset7\r
+       mov es:[di], ah\r
+\r
+       mov al, 0ffh            ; set mask for middle chunks\r
+       out dx, al\r
+       mov al, ah                      ; ready to store two pixels at a time\r
+\r
+       inc di                          ; move string start past left edge\r
+       mov cx, offset3         ; draw line from plot 7 to plot 3, exclusive\r
+       sub cx, di                      ; width of section in bytes\r
+       push cx\r
+       shr cx, 1                       ; store midsection\r
+       rep stosw\r
+       adc cx, 0\r
+       rep stosb\r
+\r
+       mov di, offset6         ; draw line from plot 6 to plot 2\r
+       inc di                          ; move past left edge\r
+       pop cx\r
+       shr cx, 1\r
+       rep stosw\r
+       adc cx, 0\r
+       rep stosb\r
+\r
+@@ClimaxOfPlot:\r
+       pop cx\r
+       jmp [jump_vector]       ; either @@Advance or @@NoAdvance\r
+\r
+\r
+; unlike their counterparts in the other function, these do not draw --\r
+; they only move the eight pointers\r
+\r
+; move the x-major plots horizontally and the y-major plots vertically\r
+@@NoAdvance:\r
+       mov al, byte ptr mask0n1 ; advance left x-major plots\r
+       mov di, offset0\r
+       rol al, 1           ; advance 0 right\r
+       mov byte ptr mask0n1, al\r
+       adc di, 0\r
+       mov offset0, di\r
+       mov di, offset1\r
+       ror al, 1           ; what was that bit again?\r
+       adc di, 0           ; advance 1 right\r
+       mov offset1, di\r
+\r
+       mov al, byte ptr mask4n5 ; advance left x-major plots\r
+       mov di, offset4\r
+       ror al, 1\r
+       mov byte ptr mask4n5, al\r
+       sbb di, 0\r
+       mov offset4, di\r
+       mov di, offset5\r
+       rol al, 1\r
+       sbb di, 0\r
+       mov offset5, di\r
+\r
+       mov al, byte ptr mask2n3\r
+       mov di, offset2\r
+       sub di, bx          ; advance 2 up\r
+       mov offset2, di\r
+       mov di, offset3\r
+       add di, bx          ; advance 3 down\r
+       mov offset3, di\r
+\r
+       mov al, byte ptr mask6n7\r
+       mov di, offset6\r
+       sub di, bx\r
+       mov offset6, di\r
+       mov di, offset7\r
+       add di, bx\r
+       mov offset7, di\r
+\r
+       jmp @@FilledCircleCalc\r
+\r
+; move all plots diagonally\r
+@@Advance:\r
+       mov al, byte ptr mask0n1\r
+       mov di, offset0\r
+       rol al, 1           ; advance 0 right and down\r
+       mov byte ptr mask0n1, al\r
+       adc di, bx\r
+       mov offset0, di\r
+       mov di, offset1\r
+       ror al, 1           ; what was that bit again?\r
+       adc di, 0           ; advance 1 right and up\r
+       sub di, bx\r
+       mov offset1, di\r
+\r
+       mov al, byte ptr mask2n3\r
+       mov di, offset2\r
+       ror al, 1           ; advance 2 up and left\r
+       mov byte ptr mask2n3, al\r
+       sbb di, bx\r
+       mov offset2, di\r
+       mov di, offset3\r
+       rol al, 1\r
+       sbb di, 0           ; advance 3 down and left\r
+       add di, bx\r
+       mov offset3, di\r
+\r
+       mov al, byte ptr mask4n5\r
+       mov di, offset4\r
+       ror al, 1\r
+       mov byte ptr mask4n5, al\r
+       sbb di, 0\r
+       add di, bx\r
+       mov offset4, di\r
+       mov di, offset5\r
+       rol al, 1\r
+       sbb di, bx\r
+       mov offset5, di\r
+\r
+       mov al, byte ptr mask6n7\r
+       mov di, offset6\r
+       rol al, 1\r
+       mov byte ptr mask6n7, al\r
+       adc di, 0\r
+       sub di, bx\r
+       mov offset6, di\r
+       mov di, offset7\r
+       ror al, 1\r
+       adc di, bx\r
+       mov offset7, di\r
+\r
+; do you realize the entire function has been set up around this little jot?\r
+; keep in mind that radii values are 2 per pixel\r
+@@FilledCircleCalc:\r
+       add cx, 2           ; x += 1\r
+       mov di, error\r
+       add di, cx          ; error += (2 * x) + 1\r
+       inc di\r
+       jl @@FilledCircleNoError\r
+       cmp cx, si          ; x > y?\r
+       ja @@FleeFlyFlowFum\r
+       sub si, 2           ; y -= 1\r
+       sub di, si          ; error -= (2 * y)\r
+       mov error, di\r
+       mov jump_vector, offset @@Advance\r
+       jmp @@PlotLines\r
+@@FilledCircleNoError:\r
+       mov error, di\r
+       mov jump_vector, offset @@NoAdvance\r
+       jmp @@PlotLines\r
+\r
+@@FleeFlyFlowFum:\r
+       pop di\r
+       pop si\r
+       mov sp,bp\r
+       pop bp\r
+\r
+       ret\r
+\r
+_x_filled_circle endp\r
+\r
+       end\r
+\r