;************************************************
;*	   Non-System Draw Line Example		*
;*    Made as help to demo and game creaters	*
;*						*
;*  ASM-One example coded by Rune Gram-Madsen	*
;*						*
;*   All rights reserved. Copyright (c) 1990	*
;************************************************

; Move the mouse around to draw a lot of lines.

;*****************
;*   Constants   *
;*****************

OldOpenLibrary	= -408
CloseLibrary	= -414

DMASET=	%1000000111000000
;	 -----a-bcdefghij

;	a: Blitter Nasty
;	b: Bitplane DMA (if this isn't set, sprites disappear!)
;	c: Copper DMA
;	d: Blitter DMA
;	e: Sprite DMA
;	f: Disk DMA
;	g-j: Audio 3-0 DMA

START:
	MOVEM.L	D0-D7/A0-A6,-(A7)	; Put registers on stack

;***********************************
;*   CLOSE ALL SYSTEM INTERRUPTS   *
;*                                 *
;*      START DEMO INTERRUPTS      *
;***********************************

	MOVE.L	$4.W,A6			; Exec pointer to A6
	LEA.L	GfxName(PC),A1		; Set library pointer
	MOVEQ	#0,D0
	JSR	OldOpenLibrary(A6)	; Open graphics.library
	MOVE.L	D0,A1			; Use Base-pointer
	MOVE.L	$26(A1),OLDCOP1		; Store copper1 start addr
	MOVE.L	$32(A1),OLDCOP2		; Store copper1 start addr
	JSR	CloseLibrary(A6)	; Close graphics library

	LEA	$DFF000,A6
	MOVE.W	$1C(A6),INTENA		; Store old INTENA
	MOVE.W	$2(A6),DMACON		; Store old DMACON
	MOVE.W	$10(A6),ADKCON		; Store old ADKCON

	MOVE.W	#$7FFF,$9A(A6)		; Clear interrupt enable

	BSR.L	Wait_Vert_Blank

	MOVE.W	#$7FFF,$96(A6)		; Clear DMA channels
	MOVE.L	#COPLIST,$80(A6)	; Copper1 start address
	MOVE.W	#DMASET!$8200,$96(A6)	; DMA kontrol data
	MOVE.L	$6C.W,OldInter		; Store old inter pointer
	MOVE.L	#INTER,$6C.W		; Set interrupt pointer

	MOVE.W	#$7FFF,$9C(A6)		; Clear request
	MOVE.W	#$C020,$9A(A6)		; Interrupt enable

;****       Your main routine      ****


;**** Main Loop  Test mouse button ****

LOOP:	BTST	#2,$dff016		; Test left mouse button
	bne.s	loop
	
noloop
;*****************************************
;*					 *
;*   RESTORE SYSTEM INTERRUPTS ECT ECT   *
;*					 *
;*****************************************

	LEA	$DFF000,A6

	MOVE.W	#$7FFF,$9A(A6)		; Disable interrupts

	BSR.S	Wait_Vert_Blank

	MOVE.W	#$7FFF,$96(A6)
	MOVE.L	OldCop1(PC),$80(A6)	; Restore old copper1
	MOVE.L	OldCop2(PC),$84(A6)	; Restore old copper1
	MOVE.L	OldInter(PC),$6C.W	; Restore inter pointer
	MOVE.W	DMACON,D0		; Restore old DMACON
	OR.W	#$8000,D0
	MOVE.W	D0,$96(A6)		
	MOVE.W	ADKCON,D0		; Restore old ADKCON
	OR.W	#$8000,D0
	MOVE.W	D0,$9E(A6)
	MOVE.W	INTENA,D0		; Restore inter data
	OR.W	#$C000,D0
	MOVE.W	#$7FFF,$9C(A6)
	MOVE.W	D0,$9A(A6)
	MOVEM.L	(A7)+,D0-D7/A0-A6	; Get registers from stack
	RTS

;*** WAIT VERTICAL BLANK ***

Wait_Vert_Blank:
	BTST	#0,$5(A6)
	BEQ.S	Wait_Vert_Blank
.loop	BTST	#0,$5(A6)
	BNE.S	.loop
	RTS

;*** DATA AREA ***

GfxName		DC.B	'graphics.library',0
		even
DosBase		DC.L	0
OldInter	DC.L	0
OldCop1		DC.L	0
OldCop2		DC.L	0
INTENA		DC.W	0
DMACON		DC.W	0
ADKCON		DC.W	0

;**********************************
;*				  *
;*    INTERRUPT ROUTINE. LEVEL 3  *
;*				  *
;**********************************

INTER:
	MOVEM.L	D0-D7/A0-A6,-(A7)	; Put registers on stack
	LEA.L	$DFF000,A6
	MOVE.L	#SCREEN,$E0(A6)

	BTST	#6,$BFE001		; Test left mouse button
	Bne.s	nodraw

;---  Place your interrupt routine here  ---

	BSR.S	INITLINE	; Init line registers

	MOVEQ	#0,D0		; Start X - Y coords
	MOVEQ	#0,D1

	MOVEQ	#0,D3		; End X - Y coords
	MOVEQ	#0,D2

	MOVE.W	$A(a6),D3	; Get mouse position
	MOVE.B	D3,D0
	MOVE.B	D3,D2

	LSR.W	#8,D3
	MOVE.B	D3,D1

	BSR.S	DRAWLINE	; Draw the line
nodraw

	MOVE.W	#$4020,$9C(A6)		; Clear interrupt request
	MOVEM.L	(A7)+,D0-D7/A0-A6	; Get registers from stack
	RTE

;********************
;*  Init line draw  *
;********************

SINGLE = 0		; 2 = SINGLE BIT WIDTH
BYTEWIDTH = 40

; The below registers only have to be set once each time
; you want to draw one or more lines.

INITLINE:
	LEA.L	$DFF000,A6

.WAIT:	BTST	#$E,$2(A6)
	BNE.S	.WAIT

	MOVEQ	#-1,D1
	MOVE.L	D1,$44(A6)		; FirstLastMask
	MOVE.W	#$8000,$74(A6)		; BLT data A
	MOVE.W	#BYTEWIDTH,$60(A6)	; Tot.Screen Width
	MOVE.W	#$FFFF,$72(A6)
	LEA.L	SCREEN,A5
	RTS

;*****************
;*   DRAW LINE   *
;*****************

; USES D0/D1/D2/D3/D4/D7/A5/A6

drawline:
	lea	draw_octselected(pc),a4
	sub.w	d3,d1
	mulu	#40,d3		; screenwidth * d3

	moveq	#$f,d4
	and.w	d2,d4		; get lowest bits from d2

;--------- select octant ---------

	sub.w	d2,d0
	blt.s	draw_dont0146
	tst.w	d1
	blt.s	draw_dont04

	cmp.w	d0,d1
	bge.s	draw_select0
	moveq	#$11+single,d7		; select oct 4
	jmp	(a4)

draw_select0:
	moveq	#1+single,d7		; select oct 0
	exg	d0,d1
	jmp	(a4)

draw_dont04:
	neg.w	d1
	cmp.w	d0,d1
	bge.s	draw_select1
	moveq	#$19+single,d7		; select oct 6
	jmp	(a4)

draw_select1:
	moveq	#5+single,d7		; select oct 1
	exg	d0,d1
	jmp	(a4)

draw_dont0146:
	neg.w	d0
	tst.w	d1
	blt.s	draw_dont25
	cmp.w	d0,d1
	bge.s	draw_select2
	moveq	#$15+single,d7		; select oct 5
	jmp	(a4)
	
draw_select2:
	moveq	#9+single,d7		; select oct 2
	exg	d0,d1
	jmp	(a4)

draw_dont25:
	neg.w	d1
	cmp.w	d0,d1
	bge.s	draw_select3
	moveq	#$1d+single,d7		; select oct 7
	jmp	(a4)

draw_select3:
	moveq	#$d+single,d7		; select oct 3
	exg	d0,d1

;---------   calculate start   ---------

draw_octselected:
	add.w	d1,d1			; 2*dy
	asr.w	#3,d2			; x=x/8
	ext.l	d2
	add.l	d2,d3			; d3 = x+y*40 = screen pos
	move.w	d1,d2			; d2 = 2*dy
	sub.w	d0,d2			; d2 = 2*dy-dx
	bge.s	draw_dontsetsign
	ori.w	#$40,d7			; dx < 2*dy
draw_dontsetsign:

;---------   SET BLITTER   ---------

.wait:
	btst	#$e,$2(a6)		; wait on the blitter
	bne.s	.wait

	move.w	d2,$52(a6)		; 2*dy-dx
	move.w	d1,$62(a6)		; 2*d2
	sub.w	d0,d2			; d2 = 2*dy-dx-dx
	move.w	d2,$64(a6)		; 2*dy-2*dx

;---------   make length   ---------

	asl.w	#6,d0			; d0 = 64*dx
	add.w	#$0042,d0		; d0 = 64*(dx+1)+2

;---------   make control 0+1   ---------

	ror.w	#4,d4
	ori.w	#$bea,d4		; $b4a - dma + minterm
	swap	d7
	move.w	d4,d7
	swap	d7
	add.l	a5,d3		; screen ptr

	move.l	d7,$40(a6)		; bltcon0 + bltcon1
	move.l	d3,$48(a6)		; source c
	move.l	d3,$54(a6)		; destination d
	move.w	d0,$58(a6)		; size
	rts

;*****************************
;*			     *
;*      COPPER1 PROGRAM      *
;*			     *
;*****************************

	SECTION	Copper,DATA_C

COPLIST:
	DC.W	$0100,$1200	; Bit-Plane control reg.
	DC.W	$0102,$0000	; Hor-Scroll
	DC.W	$0104,$0010	; Sprite/Gfx priority
	DC.W	$0108,$0000	; Modolu (odd)
	DC.W	$010A,$0000	; Modolu (even)
	DC.W	$008E,$2C81	; Screen Size
	DC.W	$0090,$2CC1	; Screen Size
	DC.W	$0092,$0038	; H-start
	DC.W	$0094,$00D0	; H-stop

	DC.W	$0180,$0fff	; Color #0 = 000
	DC.W	$0182,$000f	; Color #1 = fff
	DC.L	$FFFFFFFE

;*****************************
;*			     *
;*      SCREEN DATA AREA     *
;*			     *
;*****************************

	SECTION	Screen,BSS_C

SCREEN	DS.B	40*256
