# Z80 Routines:Graphic:LineDraw

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

## Code

These routines are the best line draws routines around for z80.

### Small (and fast for its size)

```; Small and quite fast
; by Patai Gergely, thanks
DrawLineCompact		; This routine draws an unclipped line on an IX-pointed screen from (d,e) to (h,l)
ld a,h			; Calculating delta X and swapping points if negative
sub d			; (Lines are always drawn from left to right)
jp nc,DL_okaydx
ex de,hl
neg
DL_okaydx:
push af		; Saving DX (it will be popped into DE below)
ld b,0			; Calculating the position of the first pixel to be drawn
ld c,d			; IX+=D/8+E*12 (actually E*4+E*4+E*4)
srl c
srl c
srl c
ld c,e
sla c
sla c
ld a,d			; Calculating the starting pixel mask
ld c,\$80
and 7
srl c
dec a
ld a,l			; Calculating delta Y and negating the Y increment if necessary
sub e			; This is the last instruction for which we need the original data
ld hl,12
jp nc,DL_okaydy
ld hl,-12
neg
DL_okaydy:
pop de			; Recalling DX
ld e,a			; D=DX, E=DY
cp d
jp c,DL_horizontal	; Line is rather horizontal than vertical
ld (DL_VLinc+1),hl	; Modifying y increment
push ix		; Loading IX to HL for speed; we don't need the old value of HL any more
pop hl
ld b,e			; Pixel counter
inc b
srl a			; Setting up gradient counter (A=E/2)
ld (DL_HLinc+1),sp	; Backing up SP to a safe place
di			; Interrupts are undesirable when we play around with SP :)
DL_VLinc:
ld sp,0		; This value is replaced by +/- 12
DL_Vloop:
ex af,af'		; Saving A to alternative register
ld a,(hl)
or c			; Writing pixel to current position
ld (hl),a
ex af,af'		; Recalling A (faster than push-pop, and there's no need for SP)
jp nc,DL_VnoSideStep
jp nc,DL_VnoByte	; Handling byte boundary
inc hl
DL_VnoByte:
DL_VnoSideStep:
djnz DL_Vloop
ld sp,(DL_HLinc+1)
ret
DL_horizontal:
ld (DL_HLinc+1),hl	; Modifying y increment
push ix		; Loading IX to HL for speed; we don't need the old value of HL any more
pop hl
ld b,d			; Pixel counter
inc b
ld a,d			; Setting up gradient counter
srl a
ld (DL_VLinc+1),sp	; Backing up SP to a safe place
di			; Interrupts again...
DL_HLinc:
ld sp,0		; This value is replaced by +/- 12
DL_Hloop:
ex af,af'		; Saving A to alternative register
ld a,(hl)
or c			; Writing pixel to current position
ld (hl),a
ex af,af'		; Recalling A
jp nc,DL_HnoByte	; Handling byte boundary
inc hl
DL_HnoByte:
jp nc,DL_HnoSideStep
DL_HnoSideStep:
djnz DL_Hloop
ld sp,(DL_VLinc+1)
ret

```

### Fast Version

```;Fast line routine, only sets pixels
;(d,e),(h,l) = (x1,y1),(x2,y2)
;NO clipping
;James Montelongo
FastLine:
ld a,h
cp d
jp nc,noswapx
ex de,hl
noswapx:

ld a,h
sub d
jp nc,posx
neg
posx:
ld b,a
ld a,l
sub e
jp nc,posy
neg
posY:
ld c,a
ld a,l
ld hl,-12
cp e
jp c,lineup
ld hl,12
lineup:
ld ix,xbit
ld a,b
cp c
jp nc,xline
ld b,c
ld c,a
ld ix,ybit
xline:
push hl
ld a,d
ld d,0
ld h,d
sla e
sla e
ld l,e
ld e,a
and %00000111
srl e
srl e
srl e
ld de,gbuf
ld e,a
ld d,0
ld e,(ix)
ld d,(ix+1)
push hl
pop ix
ex de,hl
pop de
push hl
ld h,b
ld l,c
ld a,h
srl a
inc b
ret

Xbit:
.dw drawX0,drawX1,drawX2,drawX3
.dw drawX4,drawX5,drawX6,drawX7
Ybit:
.dw drawY0,drawY1,drawY2,drawY3
.dw drawY4,drawY5,drawY6,drawY7

DrawX0:
set 7,(ix)
cp h
jp c,\$+3+2+1
sub h
djnz DrawX1
ret
DrawX1:
set 6,(ix)
cp h
jp c,\$+3+2+1
sub h
djnz DrawX2
ret
DrawX2:
set 5,(ix)
cp h
jp c,\$+3+2+1
sub h
djnz DrawX3
ret
DrawX3:
set 4,(ix)
cp h
jp c,\$+3+2+1
sub h
djnz DrawX4
ret
DrawX4:
set 3,(ix)
cp h
jp c,\$+3+2+1
sub h
djnz DrawX5
ret
DrawX5:
set 2,(ix)
cp h
jp c,\$+3+2+1
sub h
djnz DrawX6
ret
DrawX6:
set 1,(ix)
cp h
jp c,\$+3+2+1
sub h
djnz DrawX7
ret
DrawX7:
set 0,(ix)
inc ix
cp h
jp c,\$+3+2+1
sub h
djnz DrawX0
ret

DrawY0_:
inc ix
sub h
dec b
ret z
DrawY0:
set 7,(ix)
cp h
jp nc,DrawY1_
djnz DrawY0
ret
DrawY1_:
sub h
dec b
ret z
DrawY1:
set 6,(ix)
cp h
jp nc,DrawY2_
djnz DrawY1
ret
DrawY2_:
sub h
dec b
ret z
DrawY2:
set 5,(ix)
cp h
jp nc,DrawY3_
djnz DrawY2
ret
DrawY3_:
sub h
dec b
ret z
DrawY3:
set 4,(ix)
cp h
jp nc,DrawY4_
djnz DrawY3
ret
DrawY4_:
sub h
dec b
ret z
DrawY4:
set 3,(ix)
cp h
jp nc,DrawY5_
djnz DrawY4
ret
DrawY5_:
sub h
dec b
ret z
DrawY5:
set 2,(ix)
cp h
jp nc,DrawY6_
djnz DrawY5
ret
DrawY6_:
sub h
dec b
ret z
DrawY6:
set 1,(ix)
cp h
jp nc,DrawY7_
djnz DrawY6
ret
DrawY7_:
sub h
dec b
ret z
DrawY7:
set 0,(ix)
cp h
jp nc,DrawY0_
djnz DrawY7
ret

```

## Examples

For the compact version.

``` ld hl,plotsscreen
call ClearScreen
ld de,\$0000		; Hint: top left corner is at 0,0 and the bottom right at 95,63
ld hl,\$1008
ld ix,plotsscreen
call DrawLineCompact
ld hl,SAVESSCREEN
call ifastcopy
call _getkey
ret

```