    move.w	#$4000,$dff09a     ; INTENA  - disable all interrupts
    move.w	#$01a0,$dff096     ; DMACON - disable bitplane, copper, sprite

    lea.l	screen(pc),a1      ; move address of screen into a1
    lea.l	bplcop+2(pc),a2    ; move address of plcop+2 into a2
                               ; set BPL1PTH / BPL1PTL in bplcop to screen
    move.l	a1,d1              ; move screen pointer into d1
    move.w	d1,4(a2)           ; move a word to set BPL1PTL in bplcop
    swap	d1                 ; swap words in the 32 bit register d1
    move.w	d1,(a2)            ; move a word to set BPL1PTH in bplcop

    lea.l	copper(pc),a1      ; move address of copper into a1
    move.l	a1,$dff080         ; move long copper address into COP1LCH / COP1LCL

    move.w	#$8180,$dff096     ; DMACON - enable bitplane, copper

    bsr	initlinedraw           ; branch to subroutine initlinedraw

main:                          ; label
    moveq	#100,d0            ; first line pos x in d0
    moveq	#100,d1            ; first line pos y in d1

    move.w	$dff00a,d2         ; move value in JOY0DAT into d2
    move.w	d2,d3              ; move value in d2 into d3
    andi.w	#$ff,d2            ; second line pos is mouse x values in d2
    lsr.w	#8,d3              ; second line pos is mouse y values in d3

    bsr.s	linedraw           ; branch to subroutine linedraw

    btst	#6,$bfe001         ; test left mouse button
    bne.s	main               ; if not pressed goto main

    move.l	4.w,a6             ; make a6 point to ExecBase of exec.library
    move.l	156(a6),a6         ; IVBLIT points to GfxBase
    move.l	38(a6),$dff080     ; copinit ptr to copper start up list restore workbench copperlist

    move.w	#$8020,$dff096     ; DMACON enable sprite
    rts                        ; return from subroutine

; Subroutine linedraw
; If both points are equal, then no line is drawn.
; Input:
;   d0: x1 x-coordinate of first point
;   d1: y1 y-coordinate of first point
;   d2: x2 x-coordinate of second point
;   d3: y2 y-coordinate of second point
;   a0: pointer to the bitplane
;   a1: pointer to the octant table
;   a2: base address of the custom chip register $dff000

    swid=40                    ; screen width in bytes

linedraw:                      ; subroutine linedraw
    cmp.w	d0,d2              ; compare x1 and x2
    bne.s	ld_not1pix         ; if x1 != x2 goto ld_not1pix
    cmp.w	d1,d3              ; compare y1 and y2
    bne.s	ld_not1pix         ; if y1 != y2 goto ld_not1pix 
    rts                        ; return from subroutine
ld_not1pix:                    ; label, both points of line is not the same pixel
    movem.l	d4/d7/a3-a4,-(a7)  ; push registers on the stack
    moveq	#0,d7              ; clear octant index d7
    sub.w	d0,d2              ; store dx=x2-x1 in d2
    bge.s	ld_xok             ; if dx>=0 goto ld_xok
    neg.w	d2                 ; store -dx in d2
    addq.w	#2,d7              ; add 2 to octant index d7 (dx < 0)
ld_xok:                        ; label, dx is OK
    sub.w	d1,d3              ; store dy=y2-y1 in d3
    bge.s	ld_yok             ; if dy>=0 goto ld_yok
    neg.w	d3                 ; store -dy in d3
    addq.w	#4,d7              ; add 4 to octant index d7 (dy < 0)
ld_yok:                        ; label, dy is OK
    cmp.w	d3,d2              ; compare dy and dx
    bgt.s	ld_xyok            ; if dx > dy goto ld_xyok 
    ; bne.s	ld_not45           ; FIX: remove code
    ; add.w	#16,d7             ; FIX: remove code
ld_not45:                      ; Label line is not 45 degrees
    exg	d2,d3                  ; exchange dx and dy so that dx is largest
    addq.w	#8,d7              ; add 8 to octant index d7 (dy > dx)
ld_xyok:                       ; label, dx and dy is OK
    add.w	d3,d3              ; 2dy to d3 
    move.w	d3,d4              ; 2dy to d4
    cmp.w	d3,d2              ; FIX: compare d3=2dy with d2=dx
    bgt.s	ld_sign_ok         ; FIX: if dx > 2dy goto ld_sign_ok
    add.w	#16,d7             ; FIX: no sign is needed 2dy - dx >= 0    
ld_sign_ok:
    sub.w	d2,d4              ; 2dy-dx to d4
    add.w	d3,d3              ; 4dy to d3
    move.w	d3,a3              ; 4dy to a3
    add.w	d2,d2              ; 2dx in d2
    add.w	d2,d2              ; 4dx in d2
    sub.w	d2,d3              ; 4dy - 4dx in d3
    mulu	#swid,d1           ; convert y1 coordinate to byte offset
    move.l	a0,a4              ; Screen pointer to a4
    add.w	d1,a4              ; Screen + y1 to a4
    move.w	d0,d1              ; x1 to d1
    lsr.w	#3,d1              ; convert x1 coordinate to byte offset (x1/8)
    add.w	d1,a4              ; Screen + y1 + x1 to a4.
    andi.w	#$f,d0             ; d0 sets BLTCON0 / BLTCON1 Keep the first four bits of x1
    ror.w	#4,d0              ; Within a word rotate right 4 bits.
    add.w	#$bca,d0           ; FIX: Add values to three lowest nibbles 
    swap	d0                 ; Swap the words in d0
    move.w	(a1,d7.w),d0       ; move octant value at d7 into d0
    lsl.w	#4,d2              ; d2 sets BLTSIZE bit 15-6 holds dx  
    add.w	#$40,d2            ; FIX: bit 15-6 now holds dx + 1    
    addq.w	#2,d2              ; bit 5-0 holds 2
ld_wldraw:
    btst	#6,$2(a2)          ; DMACONR test Blitter DMA enable
    bne.s	ld_wldraw          ; if not set then goto ld_wldraw
    move.l	d0,$40(a2)         ; BLTCON0 / BLTCON1
    move.w	d3,$64(a2)         ; BLTAMOD
    move.w	a3,$62(a2)         ; BLTBMOD
    move.w	d4,$52(a2)         ; BLTAPTL
    move.l	a4,$48(a2)         ; BLTCPTH / BLTCPTL
    move.l	a4,$54(a2)         ; BLTDPTH / BLTDPTL
    move.w	d2,$58(a2)         ; BLTSIZE
    movem.l	(a7)+,d4/d7/a3-a4  ; pop the stack into registers
    rts

initlinedraw:                  ; subroutine initlinedraw
    lea.l	screen(pc),a0      ; move address of screen into a0
    lea.l	octant(pc),a1      ; move screen of octant into a1
    move.l	#$dff000,a2        ; move value into a2
waitinit:                      ; label waitinit
    btst	#6,$2(a2)          ; DMACONR test Blitter DMA enable
    bne.s	waitinit           ; if not Blitter DMA enable goto waitinit
    move.l	#-1,$44(a2)        ; BLTAFWM / BLTALWM
    move.l	#$ffff8000,$72(a2) ; BLTBDAT / BLTADAT
    move.w	#swid,$60(a2)      ; BLTCMOD
    move.w	#swid,$66(a2)      ; BLTDMOD
    rts                        ; return from subroutine

octant:
    dc.w	$0051,$0055,$0059,$005d
    dc.w	$0041,$0049,$0045,$004d
    dc.w	$0011,$0015,$0019,$001d
    dc.w	$0001,$0009,$0005,$000d

copper:
    dc.w	$2001,$fffe     ; wait for vpos >= $20 and hpos >= $0
    dc.w	$0102,$0000     ; set BPLCON1 (scroll)
    dc.w	$0104,$0000     ; set BPLCON2 (video)
    dc.w	$0108,$0000     ; BPL1MOD (odd bitplanes)
    dc.w	$010a,$0000     ; BPL2MOD (even bitplanes)
    dc.w	$008e,$2c81     ; DIWSTRT upper left corner at y/vpos = $2c, x = $81
    dc.w	$0090,$f4c1     ; DIWSTOP enable PAL trick
    dc.w	$0090,$38c1     ; DIWSTOP lower right corner at y/vpos = $12c, x = $1c1
    dc.w	$0092,$0038     ; DDFSTRT data fetch start at vpos = DIWSTRT, hpos = $38
    dc.w	$0094,$00d0     ; DDFSTOP data fetch stop at vpos = DIWSTOP, hpos = $d0
    dc.w	$0180,$0000     ; COLOR00 set to black - background color
    dc.w	$0182,$0ff0     ; COLOR01 set to yellow - foreground color
    dc.w	$2c01,$fffe     ; wait for vpos >= $2c and hpos >= $0
bplcop:
    dc.w	$00e0,$0000     ; BPL1PTH (high bit 16-31)
    dc.w	$00e2,$0000     ; BPL1PTL (low bit 0-15)
    dc.w	$0100,$1200     ; BPLCON0 enable 1 bitplane, enable color burst
    dc.w	$ffdf,$fffe     ; wait for vpos >= $ff and hpos >= $de
    dc.w	$2c01,$fffe     ; wait for vpos >= $12c and hpos >= $0 (counter roll over)
    dc.w	$0100,$0200     ; BPLCON0 disable bitplane - older PAL chips
    dc.w	$ffff,$fffe     ; wait for vpos >= $ff and hpos >= $fe
                            ; wait indefinitely - until next vertical blanking

screen:
    blk.w	5120,0          ; Allocate mem for a 320x256 screen