Skip to content

Instantly share code, notes, and snippets.

@BalorPrice
Created May 15, 2019 21:33
Show Gist options
  • Save BalorPrice/bccdfdcc55a59e0bdbe8c9c2b50892ca to your computer and use it in GitHub Desktop.
Save BalorPrice/bccdfdcc55a59e0bdbe8c9c2b50892ca to your computer and use it in GitHub Desktop.
Bresenham line drawing example
; BRESENHAM LINE DRAWING
; This assumes MODE 4 (SAM coupé) with screen in 0-24575.
;-------------------------------------------
line.plotHLC:
; Plot a point at (L,H) with colour C (0-15 only)
ex af,af'
push bc
push hl
@find_scr_address:
srl h
rr l
@plot_right:
ld b,&f0 ; Assume plotting right nibble
jp c,@+do_plot ; If not carried, prepare plotting left nibble
@plot_left:
ld b,&0f
for 4, sla c
@do_plot:
ld a,(hl) ; Get background
and b ; mask nibble
or c ; set colour
ld (hl),a ; plot
pop hl
pop bc
ex af,af'
ret
line.plotHLDEC:
; Plot a point at (D.E,H.L) with colour C (0-15 only)
ex af,af'
push bc
push de
push hl
@round: ; Round up/down H and L to natural coordinates
ld b,0
ld a,h
rl l
adc b
ld h,a
ld a,d
rl e
adc b
ld l,a
@find_scrn_addr:
srl h
rr l
@plot_right:
ld b,&f0
jp c,@+do_plot
@plot_left:
ld b,&0f
for 4,sla c
@do_plot:
ld a,(hl)
and b
or c
ld (hl),a
pop hl
pop de
pop bc
ex af,af'
ret
;-------------------------------------------------
line.drawDEBCA:
; Make Bresenham line drawer to plot from (E,D) to (C,B), colour A
push bc
push de
push hl
ld (@+h_colour+1),a
ld (@+v_colour+1),a
ex de,hl
@test_plot_vert: ; Test if line is more vertical or horizontal
ld a,c
sub l
jp nc,@+skip
neg
@skip:
ld e,a
ld a,b
sub h
jp nc,@+skip
neg
@skip:
sub e
jp c,@+plot_horiz
@plot_vert: ; Line is <=45 degrees from vertical
@test_order: ; HL should be top if mostly vertical line
ld a,b
sub h
jp nc,@+get_dx
@swap_HL_BC:
ld a,h
ld h,b
ld b,a
ld a,l
ld l,c
ld c,a
@get_dx: ; Get difference in X movement per line moved
ld a,c
sub l
jp nc,@move_right ; If -ve result, move left after overflows
@move_left:
neg
ld e,a
ld a,dec_l ; change code to move left when going down screen
ld (@+move_pix),a
jp @+get_dy
@move_right: ; If +ve, set to move right on overflows.
ld e,a
ld a,inc_l
ld (@+move_pix),a
@get_dy:
ld a,b ; Get difference in Y movement to test for
sub h
ld d,a
ld b,a ; Get loop counter
inc b
@v_colour: ld c,yellow
srl a ; Halve dy for starting point
@plot_loop:
@plot_pix:
call line.plotHLC ; Plot this position
@upd_pos:
add e ; Update dx and test for over dy
cp d
jp m,@+next_line
@carry_pixel: ; If over threshold, move pixel along and update dx
sub d
@move_pix: inc l
@next_line:
inc h
djnz @-plot_loop
pop hl
pop de
pop bc
ret
@plot_horiz: ; Line is <=45 degrees from horiztonal
@test_order: ; HL should be left if mostly horizontal line
ld a,c
sub l
jp nc,@+get_dy
@swap_HL_BC:
ld a,h
ld h,b
ld b,a
ld a,l
ld l,c
ld c,a
@get_dy: ; Get difference in y movement per pixel column moved
ld a,b
sub h
jp nc,@+move_up ; If -ve result, move up after overflows
@move_down:
neg
ld e,a
ld a,dec_h ; change code to move left when going down screen
ld (@+move_pix),a
jp @+get_dx
@move_up: ; If +ve, set to move right on overflows.
ld e,a
ld a,inc_h
ld (@+move_pix),a
@get_dx:
ld a,c ; Get difference in X movement to test for
sub l
ld d,a
ld b,a ; Get loop counter
inc b
@h_colour: ld c,yellow
srl a ; Halve dx for starting point
@plot_loop:
@plot_pix:
call line.plotHLC ; Plot this position
@upd_pos:
add e ; Update dx and test for over dy
cp d
jp m,@+next_line
@carry_pixel: ; If over threshold, move pixel along and update dx
sub d
@move_pix: inc h
@next_line:
inc l
djnz @-plot_loop
pop hl
pop de
pop bc
ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment