*************************************************************************
* Nome: BLIT2B.s							*
*									*
* Autore: Fabrizio Farenga						*
*									*
* Commento: La routine traccia un rettangolo e lo riempie.		*
*									*
* Versione: 1.0								*
*									*
* Ultimo aggiornamento: 17-Nov-92 | 21:50:51				*
*									*
* Bugs: Nessuno conosciuto						*
*									*
*************************************************************************

DMACONR:	EQU   $DFF002	;Registri utilizzati.
VHPOSR:		EQU   $DFF006
BLTCON0:	EQU   $DFF040
BLTCON1:	EQU   $DFF042
BLTAFWM:	EQU   $DFF044
BLTALWM:	EQU   $DFF044
BLTCPT:		EQU   $DFF048
BLTBPT:		EQU   $DFF04C
BLTAPT:		EQU   $DFF050
BLTDPT:		EQU   $DFF054
BLTSIZE:	EQU   $DFF058
BLTCMOD:	EQU   $DFF060
BLTBMOD:	EQU   $DFF062
BLTAMOD:	EQU   $DFF064
BLTDMOD:	EQU   $DFF066
BLTBDAT:	EQU   $DFF072
BLTADAT:	EQU   $DFF074
COP1LC:		EQU   $DFF080
DMACON:		EQU   $DFF096

LINEMODE=	$1		;Flag usati dal LineMode.
ONEDOT	=	$2
SIGNFLAG=	$40
OCTANT8	=	24
OCTANT7	=	4
OCTANT6	=	12
OCTANT5	=	28
OCTANT4	=	20
OCTANT3	=	8
OCTANT2	=	0
OCTANT1	=	16


CALLEXEC:	MACRO			;Macro di chiamata per le routine
	MOVE.L	[_SysBase].W,A6		;dell'Exec.
	JSR	_LVO\1(A6)
	ENDM


	SECTION BlitCode,Code

_SysBase=4			;EXECBASE.

_LVODisable	=	-120 	;Routine dell'EXEC utilizzate dal programma.
_LVOEnable	=	-126 
_LVOAllocMem	=	-198 
_LVOFreeMem	=	-210 
_LVOOpenLibrary	=	-552 

MEMF_CHIP:	EQU 2		;Flag di definizione del tipo di Memoria.
MEMF_CLEAR:	EQU $10000

CIAAPRA:	EQU   $BFE001	;Registro del CIAA utilizzato dal programma.

Start:
	lea	GFXName,a1	;Apre la 'graphics.library'.
	moveq	#0,d0
	CALLEXEC OpenLibrary
	move.l	d0,GFXBase

	move.l	d0,a0		;Memorizza in OLDCOP l'indirizzo della
	move.l	$26(a0),OldCop	;Copperlist del Sistema Operativo.

	move.l	#$1F40,d0			;Tenta di allocare la memoria
	move.l	#MEMF_CHIP!MEMF_CLEAR,d1	;necessaria per uno schermo
	CALLEXEC AllocMem			;320x200 a 1 bitplane.
	move.l	d0,Screen
	beq	ErrorExit	;Se non c'e' abbastanza memoria esci.

	CALLEXEC Disable	;Disabilita il Sistema Operativo.

	move.l	Screen,d0	;Punta la nostra CopperList allo schermo
	swap	d0		;che abbiamo appena allocato.
	move.w	d0,BPL1H
	move.l	Screen,d0
	move.w	d0,BPL1L

	move.w	#$0020,DMACON	;Spegne gli Sprite.
	move.l	#CopList,COP1LC	;Attiva la nostra CopperList.

	jsr	BlitLine

WLine:	btst	#14,DMACONR	;Aspetta che le 2 linee siano state
	bne	WLine		;completamente tracciate.

	move.l	Screen,a0	;Punta i canali A e D all'ultima word dello
	add.l	#$1f40-2,a0	;schermo in cui effettuare il riempimento.
	move.l	a0,bltapt
	move.l	a0,bltdpt
	move.w	#$09f0,bltcon0	;Attivazione canali A e D, e mintermi settati
				;per "copiatura semplice".
	move.w	#$000a,bltcon1	;Copia discendente con riempimento inclusivo.
	move.w	#$ffff,bltafwm	;Maschere attive.
	move.w	#$ffff,bltalwm

	move.w	#0,bltamod	;Moduli dei canali A e D a 0.
	move.w	#0,bltdmod

	move.w	#200*64+20,bltsize	;Dimensioni: 320x200 (20 Word * 200).


WaitLoop:
	btst	#6,CIAAPRA	;Se il tasto sinistro del Mouse e' premuto
	bne	WaitLoop	;esce.

Exit:				;Routine di uscita.
	move.l	OldCop,COP1LC	;Rimette a posto la CopperList del S.O.
	move.w	#$8020,DMACON	;Riattiva gli sprite.
	CALLEXEC Enable		;Riattiva il Sistema Operativo.
	jsr	FreeMem		;Libera la memoria allocata.
ErrorExit:
	moveq	#0,d0
	rts

;***********************************

BlitLine:
	move.w	#160,d0		;Traccia una linea da 50,100 a 100,100
	move.w	#5,d1
	move.w	#300,d2
	move.w	#100,d3
	move.w	#$ffff,a2
	jsr	DrawBlit

	move.w	#159,d0		;Traccia una linea da 50,50 a 50,100
	move.w	#5,d1
	move.w	#20,d2
	move.w	#100,d3
	move.w	#$ffff,a2
	jsr	DrawBlit

	rts

DrawBlit:
	move.l screen,a0      	;Puntatore alla memoria in cui tracciare.
	move.l #40,a1		;Larghezza (in bytes) dello schermo.

drawline:
	move.l	a1,d4	;Larghezza in d4.
	mulu	d1,d4	;Y1 * Byte per linea.
	moveq	#-$10,d5 ;Elimina da X1 i 4 bit meno significativi.
	and.w	d0,d5
	lsr.w	#3,d5	;Dividi i rimanenti per 8.
	add.w	d5,d4	;Y1 * Bytes per linea + X1/8.
	add.l	a0,d4	;Sommaci ora l'indirizzo di inizio del Bitplane.
			;d4 adesso contiene il punto in memoria da cui partira'
			;la linea.
	
	clr.l	d5
	sub.w	d1,d3	;y2-y1: calcola DeltaY.
	roxl.b	#1,d5	;Sposta il bit di extend (di DeltaY) in d5.
	tst.w	d3	;Se DeltaY e' positivo vai a y2gy1.
	bge.s	y2gy1
	neg.w	d3	;Altrimenti invertilo.
y2gy1:	
	sub.w	d0,d2	;x2-x1: calcola DeltaX.
	roxl.b	#1,d5	;Sposta il bit di extend (di DeltaX) in d5.
	tst.w	d2	;Se DeltaX e' positivo vai a x2gx1.
	bge.s	x2gx1
	neg.w	d2	;Altrimenti invertilo.
x2gx1:	
	move.w	d3,d1	;DeltaY-DeltaX.
	sub.w	d2,d1
	bge.s	dygdx	;Se DeltaY > DeltaX vai a dygdx.
	exg	d2,d3	;Altrimenti scambiali (fai in modo che il Delta piu'
			;piccolo sia sempre in d2).
dygdx:
	roxl.b	#1,d5	;d5, che contiene il risultato delle 3 comparazioni,
			;verra' ora usato come indice della tabella degli
			;ottanti.
	move.b	Ottanti(pc,d5),d5	;Prendi l'ottante corretto.
	add.w	d2,d2	;Moltiplica *2 il Delta piu' piccolo.
		
dwblit:
	btst	#14,DMACONR	;Aspetta che il Blitter sia libero.
	bne.s	dwblit
		
	move.w	d2,BLTBMOD	;Il Delta piu' piccolo *2 nel modulo di b
	sub.w	d3,d2		;Se il Delta piu' piccolo *2 e' piu' grande
	bge.s	signnl		;del Delta piu' grande. attiva il "Segno".
	or.b	#SIGNFLAG,d5
signnl:	
	move.w	d2,BLTAPT+2	;Metti (il Delta piu' piccolo *2) - (il Delta
				;piu' grande) nel puntatore al canale A.

	sub.w	d3,d2		;Metti il (Delta piu' piccolo *2) - (Delta piu'
	move.w	d2,BLTAMOD	;grande *2) nel modulo del canale A.
	
	move.w	#$8000,BLTADAT	;Inizializza il BLTADAT.
	move.w	a2,BLTBDAT	;Inizializza il Texture.
	move.w	#$ffff,BLTAFWM	;Inizializza la maschera sinistra del canale A.
	and.w	#$000f,d0	;Metti i 4 bits piu' bassi di X1 (che
	ror.w	#4,d0		;rappresentano lo shifter) insieme ai bit
	or.w	#$0bca,d0	;di attivazioni dei canali e i mintermini,
	move.w	d0,BLTCON0	;e metti tutto nel registro di controllo 0
	or.w	#Onedot,d5
	move.w	d5,bltcon1	;Inizializza l'ottante corretto.
	move.l	d4,BLTCPT	;Metti l'indirizzo in memoria dell'inizio della
	move.l	d4,BLTDPT	;linea nel puntatore dei canali C e D.
	move.w	a1,BLTCMOD	;E metti la larghezza (in Bytes) dello schermo
	move.w	a1,BLTDMOD	;nel modulo del canali C e D.
	
	lsl.w	#6,d3		;Moltiplica *64 la lunghezza e metti 2 nella
	addq.w	#2,d3		;larghezza, per generare il formato corretto
	move.w	d3,BLTSIZE	;per l'immissione in BLTSIZE.
	rts

Ottanti:			;Tavola degli ottanti
	dc.b	OCTANT2+LINEMODE
	dc.b	OCTANT1+LINEMODE
	dc.b	OCTANT3+LINEMODE
	dc.b	OCTANT4+LINEMODE
	dc.b	OCTANT7+LINEMODE
	dc.b	OCTANT8+LINEMODE
	dc.b	OCTANT6+LINEMODE
	dc.b	OCTANT5+LINEMODE


;*************************************

FreeMem:			;Routine che libera la memoria allocata.
	move.l	Screen,a1
	move.l	#$1F40,d0
	CALLEXEC FreeMem
	rts

;*************************

	dc.b 0,'$VER: Blit2B.EXE 1.0 (17.11.92)',0	;Versione

;*************************

	SECTION BlitChipData,DATA_C

CopList:
	dc.w $0180,$0000,$0100,$0200,$0182,$0fff
	dc.w $008E,$2C81,$0090,$F4C1,$0092,$0038,$0094,$00D0
	dc.w $3001,$fffe,$00e0
BPL1H:
	dc.w $0000,$00e2
BPL1L:
	dc.w $0000
	dc.w $0108,$0000,$010a,$0000
	dc.w $3101,$fffe,$0100,$1200
	dc.w $ff01,$fffe,$0100,$0200
	dc.w $ffff,$fffe



	SECTION BlitData,DATA

Screen:		dc.l 0		;Puntatore alla memoria per lo schermo
GFXBase:	dc.l 0		;Puntatore alla Base della 'graphics.library'
OldCop:		dc.l 0		;Puntatore alla Copperlist del S.O.
GFXName:	dc.b 'graphics.library',0	;Nome della libreria
		CNOP 0,2
