1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-08 15:29:37 +00:00

CircleDraw

This commit is contained in:
Dave Plummer 2023-10-09 09:08:03 -07:00
parent efd985a8df
commit 72f4d2e99f
2 changed files with 303 additions and 54 deletions

View File

@ -16,6 +16,17 @@ typedef unsigned char byte;
extern void ClearScreen(void); // In subs.asm
extern void ScrollScreen(void); // In subs.asm
extern void DrawCircle(void); // In subs.asm
extern int x1cord;
extern int y1cord;
extern int x2cord;
extern int y2cord;
#pragma zpsym("x1cord")
#pragma zpsym("x2cord")
#pragma zpsym("y1cord")
#pragma zpsym("y2cord")
// Screen memory is placed at A000-BFFF, 320x200 pixels, mapped right to left within each horizontal byte
@ -216,30 +227,12 @@ void DrawLine(int x0, int y0, int x1, int y1, byte val)
//
// Draw a circle without sin, cos, or floating point!
void DrawCircle(int x0, int y0, int radius, byte val)
void DrawCircleC(int x0, int y0, int radius, byte)
{
int x = radius;
int y = 0;
int err = 0;
while (x >= y)
{
SETPIXEL(x0 + x, y0 + y, val);
SETPIXEL(x0 + y, y0 + x, val);
SETPIXEL(x0 - y, y0 + x, val);
SETPIXEL(x0 - x, y0 + y, val);
SETPIXEL(x0 - x, y0 - y, val);
SETPIXEL(x0 - y, y0 - x, val);
SETPIXEL(x0 + y, y0 - x, val);
SETPIXEL(x0 + x, y0 - y, val);
y++;
err += 1 + 2 * y;
if (2 * (err - x) + 1 > 0) {
x--;
err += 1 - 2 * x;
}
}
x1cord = x0;
y1cord = y0;
y2cord = radius;
DrawCircle();
}
// reverse_bits
@ -308,7 +301,7 @@ int main (void)
// Print the numbers from 0-9999, forcing the screen to scroll
for (i = 5; i < 75; i+=5)
DrawCircle(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, i, 1);
DrawCircleC(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, i, 1);
printf("Done, exiting...\r\n");
return 0;

View File

@ -14,12 +14,24 @@
.export _ClearScreen
.export _ScrollScreen
.export _SetPixel
.export _DrawCircle
SCREEN = $A000
.segment "ZEROPAGE"
temp: .res 1
btpt: .res 1
_x1cord: .res 2
_x2cord: .res 2
_y1cord: .res 2
_y2cord: .res 2
.exportzp _x1cord
.exportzp _x2cord
.exportzp _y1cord
.exportzp _y2cord
dest = $02
dest_lo = dest
@ -37,13 +49,6 @@ adp2 = $08
adp2_lo = adp2
adp2_hi = adp2+1
x1cord = $0A
x1cord_lo = x1cord
x1cord_hi = x1cord+1
y1cord = $0C
y1cord_lo = y1cord
y1cord_hi = y1cord+1
.segment "CODE"
@ -53,18 +58,18 @@ y1cord_hi = y1cord+1
;-----------------------------------------------------------------------------------
; Based on MTU PIXADR code
;-----------------------------------------------------------------------------------
; x - x1cord (16-bit)
; y - y1cord (16-bit)
; x - _x1cord (16-bit)
; y - _y1cord (16-bit)
; adp2 - address of pixel to set (16-bit)
;-----------------------------------------------------------------------------------
_GetPixelAddress:
lda x1cord ; compute bit address first
sta adp1 ; also transfer x1cord to adp1
lda _x1cord ; compute bit address first
sta adp1 ; also transfer _x1cord to adp1
and #$07 ; + which is simply the low 3 bits of x
sta btpt
lda x1cord+1 ; finish transferring x1cord to adp1
lda _x1cord+1 ; finish transferring _x1cord to adp1
sta adp1+1
lsr adp1+1 ; double shift adp1 right 3 to get
ror adp1 ; int(xcord/8 )
@ -72,34 +77,34 @@ _GetPixelAddress:
ror adp1
lsr adp1+1
ror adp1
lda #199 ; transfer (199-y1cord) to adp2
lda #199 ; transfer (199-_y1cord) to adp2
sec ; and temporary storage
sbc y1cord
sbc _y1cord
sta adp2
sta temp
lda #0
sbc y1cord+1
sbc _y1cord+1
sta adp2+1
sta temp+1
asl adp2 ; compute 40*(199-y1cord)
rol adp2+1 ; 2*(199-y1cord)
asl adp2 ; compute 40*(199-_y1cord)
rol adp2+1 ; 2*(199-_y1cord)
asl adp2
rol adp2+1 ; 4*(199-y1cord)
lda adp2 ; add in temporary save of (199-y1cord)
clc ; to make 5*(199-y1cord)
rol adp2+1 ; 4*(199-_y1cord)
lda adp2 ; add in temporary save of (199-_y1cord)
clc ; to make 5*(199-_y1cord)
adc temp
sta adp2
lda adp2+1
adc temp+1
sta adp2+1 ; 5*(199-y1cord)
asl adp2 ; 10*(199-y1cord)
sta adp2+1 ; 5*(199-_y1cord)
asl adp2 ; 10*(199-_y1cord)
rol adp2+1
asl adp2 ; 20#(199-y1cord)
asl adp2 ; 20#(199-_y1cord)
rol adp2+1
asl adp2 ; 40*(199-y1cord)
asl adp2 ; 40*(199-_y1cord)
rol adp2+1
lda adp2 ; add in int(x1cord/8) computed earlier
lda adp2 ; add in int(_x1cord/8) computed earlier
clc
adc adp1
sta adp1
@ -122,13 +127,13 @@ msktb2: .byte $7F,$BF,$DF,$EF,$F7,$FB,$FD,$FE
;-----------------------------------------------------------------------------------
; SetPixel - Set a pixel in the video memory
;-----------------------------------------------------------------------------------
; x - x1cord (16-bit)
; y - y1cord (16-bit)
; x - _x1cord (16-bit)
; y - _y1cord (16-bit)
;-----------------------------------------------------------------------------------
; Mask tables for individual pixel subroutines
;-----------------------------------------------------------------------------------
_SetPixel: jsr _GetPixelAddress
_SetPixel: jsr _GetPixelAddress
ldy btpt ; get bit number in y
lda msktb1,y ; get a byte with that bit =1, others =0
ldy #0
@ -139,8 +144,8 @@ _SetPixel: jsr _GetPixelAddress
;-----------------------------------------------------------------------------------
; ClearPixel - Clears a pixel in the video memory
;-----------------------------------------------------------------------------------
; x - x1cord (16-bit)
; y - y1cord (16-bit)
; x - _x1cord (16-bit)
; y - _y1cord (16-bit)
;-----------------------------------------------------------------------------------
_ClearPixel: jsr _GetPixelAddress
@ -175,6 +180,10 @@ _ClearScreen:
rts
;-----------------------------------------------------------------------------------
; ScrollScreen - Scrolls the entire video memory (and thus the screen) up one row
;-----------------------------------------------------------------------------------
_ScrollScreen:
; Load the source (A140) and destination (A000) addresses. Each row of characters
; occupies 320 bytes, so we start source as being one line ahead of the destination
@ -210,6 +219,253 @@ _ScrollScreen:
bne :-
rts
;-----------------------------------------------------------------------------------
; DrawCircle - Draws a circle in video memory of a given radius at a given coord
;-----------------------------------------------------------------------------------
; x - _x1cord (16-bit)
; y - _y1cord (16-bit)
; radius - _y2cord (16-bit)
;-----------------------------------------------------------------------------------
xval: .res 2
yval: .res 2
err: .res 2
tempsum: .res 2
tempx: .res 2
tempy: .res 2
_DrawCircle: lda _x1cord ; tempx = _x1cord
sta tempx
lda _x1cord+1
sta tempx+1
lda _y1cord ; tempy = _y1cord
sta tempy
lda _y1cord+1
sta tempy+1
lda _y2cord ; x = radius
sta xval
lda _y2cord+1
sta xval+1
lda #$0 ; yval = 0;
sta yval
sta yval+1
sta err ; err = 0;
sta err+1
circleloop:
lda xval+1 ; if (xval < yval) goto done;
cmp yval+1
bcs docircle
lda xval
cmp yval
bcs docircle
rts
docircle:
lda tempx
clc
adc yval
sta _x1cord
lda tempx+1
adc yval+1
sta _x1cord+1
lda tempy
sec
sbc xval
sta _y1cord
lda tempy+1
sbc xval+1
sta _y1cord+1
jsr _SetPixel ; SETPIXEL(x0 + y, y0 - x, val);
lda tempx
sec
sbc yval
sta _x1cord
lda tempx+1
sbc yval+1
sta _x1cord+1
lda tempy
sec
sbc xval
sta _y1cord
lda tempy+1
sbc xval+1
sta _y1cord+1
jsr _SetPixel ; SETPIXEL(x0 - y, y0 - x, val);
lda tempx
sec
sbc xval
sta _x1cord
lda tempx+1
sbc xval+1
sta _x1cord+1
lda tempy
sec
sbc yval
sta _y1cord
lda tempy+1
sbc yval+1
sta _y1cord+1
jsr _SetPixel ; SETPIXEL(x0 - x, y0 - y, val);
lda tempx
sec
sbc xval
sta _x1cord
lda tempx+1
sbc xval+1
sta _x1cord+1
lda tempy
clc
adc yval
sta _y1cord
lda tempy+1
adc yval+1
sta _y1cord+1
jsr _SetPixel ; SETPIXEL(x0 - x, y0 + y, val);
lda tempx
clc
adc yval
sta _x1cord
lda tempx+1
adc yval+1
sta _x1cord+1
lda tempy
clc
adc xval
sta _y1cord
lda tempy+1
adc xval+1
sta _y1cord+1
jsr _SetPixel ; SETPIXEL(x0 + y, y0 + x, val);
lda tempx
clc
adc xval
sta _x1cord
lda tempx+1
adc xval+1
sta _x1cord+1
lda tempy
clc
adc yval
sta _y1cord
lda tempy+1
adc yval+1
sta _y1cord+1
jsr _SetPixel ; SETPIXEL(x0 + x, y0 + y, val);
lda tempx
clc
adc xval
sta _x1cord
lda tempx+1
adc xval+1
sta _x1cord+1
lda tempy
sec
sbc yval
sta _y1cord
lda tempy+1
sbc yval+1
sta _y1cord+1
jsr _SetPixel ; SETPIXEL(x0 + x, y0 - y, val);
lda tempx
sec
sbc yval
sta _x1cord
lda tempx+1
sbc yval+1
sta _x1cord+1
lda tempy
clc
adc xval
sta _y1cord
lda tempy+1
adc xval+1
sta _y1cord+1
jsr _SetPixel ; SETPIXEL(x0 - y, y0 + x, val);
inc yval ; yval++;
bcc :+
inc yval+1
:
lda #0 ; tempsum = 2 * yval + 1;
sta tempsum
sta tempsum+1
lda yval
asl
rol yval+1
clc
adc #01
sta tempsum
bcc :+
inc tempsum+1
lda err ; err += tempsum
clc
adc tempsum
sta err
bcc :+
lda err+1
adc tempsum+1
sta err+1
:
lda err ; tempsum = err-xval
sec
sbc xval
sta tempsum
bcs :+
lda err+1
sbc xval+1
sta tempsum+1
asl tempsum ; tempsum = 2*(err-xval)
rol tempsum+1
clc ; tempsum = 2*(err-xval)+1
inc tempsum
bcc :+
inc tempsum+1
:
lda tempsum+1 ; if (tempsum <= 0) don't inc the xval
beq noadd
bmi noadd
sec ; xval--
dec xval
bcs noadd
dec xval+1
noadd:
lda xval ; tempsum = xval * 2
asl
sta tempsum
lda xval+1
rol
sta tempsum+1
lda #1 ; tempsum = 1-(xval*2)
sec
sbc tempsum
sta tempsum
lda #0
sbc tempsum+1
sta tempsum+1
lda err ; err += 1-(xval*2)
clc
adc tempsum
sta err
lda err+1
adc tempsum+1
sta err+1
jmp circleloop
donecircle:
rts